处理不同活动、片段、任务等之间的公共代码

Handling common code between different activities, fragments, tasks, etc

我在 Java 和其他语言的面向对象编程方面有很多(不是太多,但相当多)经验,但对 Android 和我对它的所有理解还很陌生不同的 classes 最多被描述为 limited(更现实的是 confused)。

我正在创建一个应用程序,目前包含一个 activity 和一个小部件。它的功能之一是从互联网上获取一些数据。此数据只会在每天的某个任意时刻发生变化,因此无需在每次启动应用程序或查看小部件时都获取此数据。

我的问题是我想要一种方法来获取数据并将其与更新时间一起存储在共享首选项中(这样它每天只更新一次)。必须可以从小部件和 activity.

访问此方法

通常我会简单地用静态方法创建一些 class 来做到这一点。但是,要访问共享首选项,您需要 Context。我可以想出两种方法:

选项 1:静态方法,Context 作为参数

public class MyClass {
    public static String fetchData(Context context) {
        return // ...
    }
}

选项 2:单例

public class MyClass {
    private static MyClass instance = null;
    private Context context;

    public MyClass(Context context) {
        this.context = context;
    }

    public String fetchData() {
        return ...;
    }

    public static MyClass getInstance(Context context) {
        if (instance == null)
            instance = new MyClass(context);
        return instance;
    }

    public static MyClass getInstance() {
        return instance;
    }
}

现在我第一次用 MyClass.getInstance(getActivity()).fetchData() 调用它,然后 MyClass.getInstance().fetchData().

我的问题

这两者中的哪一个比另一个更受欢迎吗?如果是,为什么?还是有另一种更好的方法来做这种事情?还是视情况而定(在那种情况下,具体取决于什么?)?

以后我可能会有更多这样的方法。由于上下文通常不会改变,我认为单例在这里可能会有用,因为在第一次实例化之后你不需要再提供上下文。

选项1几乎可以一直使用。选项 2 很危险,因为您要保留对 Context 的引用。如果 ContextActivity 类型,您可能会发生内存泄漏 - 您引用的 Activity 不会是 GC

如果您使用的是选项 2,请确保您使用的是 Application Context

要初始化单例,请执行以下操作:

getInstance(myActivity.getApplicationContext()) 

选项 1 如果该方法是实用方法则更好 - 执行某些操作并且在方法返回后不需要更改其状态。

首先,您没有保留对 Context 的引用。你也不需要在内存中保存一个单身人士。 Last Static methods are efficient

如果您一直使用 Singleton 并在此过程中重新创建对象,请使用选项 2(Picasso, RetroFit 是需要 Singleton 的好例子)

何时使用 Singleton 的一个很好的例子是 Android Volley library。它也与从远程获取数据有关所以看看

本质上,您最初描述的内容都不需要您的方法...

I'm creating an application that for now consists of one activity and a widget. One of its functionality will be fetching some data from the internet. This data will only change every midnight, so there's no need to fetch this data every time you start the app or look at the widget.

那么每日下载具体由什么负责,将如何触发? Activity 和 App Widget 都不合适。

添加一些点点滴滴 - 使用 AlarmManager 创建一个午夜左右的重复闹钟集(它不会很准确,但通常在几秒钟内)。让警报触发由 BroadcastReceiver 接收的广播,然后让接收器启动 IntentService 以下载并保存需要的内容。

这是一个双赢的局面。无论您的应用程序是否处于 'running' 状态(或者 phone 是否处于睡眠状态),都会触发警报。接收器将被触发并且 IntentService 使用自己的工作线程,因此无需担心 main/UI 线程上的 运行 网络代码出现任何问题。此外,IntentService 有一个 Context,可用于访问 SharedPreferences,并在完成工作后自行关闭。