【问题标题】:How to hold an Object as long as a service live?只要服务存在,如何保持对象?
【发布时间】:2013-11-20 05:50:52
【问题描述】:

我有一个我在所有活动中使用的对象,其中包含大量复杂数据,使用 Android 框架保存对象状态并将其从活动传递到活动会很麻烦,所以我认为可以创建一个管理此对象并使其与应用程序一样长的单例。

尝试使用常规的Java Singleton方案,普通类和普通静态实例,但是一段时间后实例变为null(这很令人困惑,为什么仍然引用的Object会变成null并被垃圾收集?) .所以我决定与 Android 设计师合作并创建一个服务来管理这个对象,服务看起来像这样:

public class DataService extends Service {
    private Data data;
    private static DataService instance;
    @Override
    public void onCreate() {
        instance = this;
        data= new Data(...);
        instance.data.addProgressListener(listener);
        (new Thread() {
            @Override
            public void run() {
                data.doInitProgress();
                listener = null;
            };
        }).start();

    }


    public static void listenToInitDataProcess(final ProgressBar progressBar,final Runnable onDone) {

        listener = new ProgressListener() {
            private int progress;
            private int max;
            @Override
            public void onUpdateProgress(final long i) {
                progressBar.setProgress(progress+=i);
            }

            @Override
            public void onProgressEndComputed(final long n) {
                progressBar.setMax(max=(int) n);
            }

            @Override
            public void onDone() {
                progressBar.setProgress(max);
                onDone.run();
            }
        };
            if (instance!=null) instance.data.addProgressListener(listener);
    }

    public static Data getData() {
        return instance.data;
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

现在的问题是,在应用程序启动一段时间后,我得到由实例导致的 NPE 为空...请注意,我正在侦听数据对象的创建,并且我只是在它之后才尝试获取它一旦启动,所以该实例不可能为空......

那该怎么做呢?

【问题讨论】:

  • 使用“私有静态”变量可能会导致内存泄漏,因为它们是可变共享变量。我敦促您避免这种做法。

标签: android service singleton


【解决方案1】:

如果您想要一个与您的应用程序一样长的对象(即只要其进程未被操作系统杀死),您可以扩展android.app.Application,将您的“全局”数据放在那里并将该子类用作您的应用程序上下文(需要在清单中声明)

然而,许多人认为单例提供的结果与自定义上下文基本相同,例如
Singletons vs. Application Context in Android?

【讨论】:

    【解决方案2】:

    但一段时间后实例变为空

    首先,了解Effective Java 的单例建议,以及某些内容如何不会变为空:

    // Singleton with public final field
    public class Elvis {
        public static final Elvis INSTANCE = new Elvis();
        private Elvis() { ... }
    
        public void leaveTheBuilding() { ... }
    }
    

    但 Service 不同,因为那里没有公共构造函数。因此,首先检查 Service 是否正在运行(在这篇文章中引用:Check if Service is running from a Broadcast Receiver):

    private boolean isMyServiceRunning(Context context) {
        ActivityManager manager = (ActivityManager)      context.getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (DataService.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
    
        return false;
    }
    

    然后在你的服务中定义一些方法来返回你需要的状态变量。

    【讨论】:

      猜你喜欢
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 2019-01-01
      相关资源
      最近更新 更多