保持应用程序状态在Android上

时间:2012-10-26 21:00:22

标签: android

我无法保存应用程序的状态/单例。

当应用程序启动时,会显示一个加载屏幕(活动),并使用来自Web服务调用的值初始化单例(请注意,网络访问不能在主线程上运行)。

创建单身人士后,我打开我的主要活动。请注意,构建布局需要单例中的值。

现在假设应用程序进入后台并在那里被杀死(例如由于内存不足)。应用程序被杀死时,我的单例实例被删除。当我切换回我的应用程序时,它会尝试重新创建主要活动。正如我前面提到的,构建布局需要单例的值,因此这会导致NullPointerException(当我尝试访问单例的成员时,因为它不再存在)。

我可以以某种方式告诉android在应用程序被杀后启动第一个加载活动吗?如果我可以在重新创建布局之前刷新单例,那将是很好的,但这似乎是一个问题,因为网络调用不能在主线程上,因此在刷新完成之前不会阻塞。 我假设我可以在onStop的所有活动中保存单例并在onCreate方法中重新创建它,但这似乎有点太不可预测,可能会导致状态不一致...

另一种方法可能就是总是在onStop上完成我的活动,但是这会导致丢失用户最后的标签,依此类推,即使应用程序没有被杀死,所以这不是一个好的选择。

关于如何解决这个问题的任何想法?

3 个答案:

答案 0 :(得分:4)

为什么不使用SharedPreferences而不是单身?

只要您想保存某些全局状态,请将其提交到首选项。无论何时您想要读取全局状态,请从首选项中读取它。

然后您根本不必关心应用程序生命周期,因为无论手机在做什么,您的数据都将始终保留。

答案 1 :(得分:0)

对于类似的东西,我使用伪singelton对象作为Application类。此对象将在开头创建,并将在内存中。但请注意,如果其他应用程序需要内存,系统将终止应用程序。然而,即使所有活动都暂时终止,这个目标仍然是持久的。

要使用它,你需要在你的Android清单中声明,如:

<application android:label="@string/app_name"
             android:icon="@drawable/icon"
             android:description="@string/desc"
             android:name=".MySingeltonClass"
             ...

这是一个代码示例:

public abstract class MySingeltonClass extends Application {
    // ...

    public void informClientOnline() {
        clientOnline=true;
        Log.v(LOG_TAG, "Client is online!");
    }

    public void informClientShutdown() {
        clientOnline=false;
        Log.v(LOG_TAG, "Client is going offline. Waiting for restart...");
        Timer t=new Timer("shutdowntimer", false);
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                if(!clientOnline) {
                    Log.v(LOG_TAG, "Client has not restartet! Shutting down framework.");
                    shutdown();
                    System.exit(0);
                }
            }
        }, 5000);
    }
}

这两个函数的调用方式如下:

((MySingeltonClass)getApplicationContext()).informClientOnline();

答案 2 :(得分:0)

您可以在调用Activity中的onSaveInstanceState()时保存您的Singleton。您需要做的就是让它实现Parcelable(它是Androids自己的序列化形式),然后您可以将它放在outState中的Bundle onSaveInstanceState()中您可以在活动中的onCreate()onRestoreInstanceState()中检索它,无论您喜欢哪种。

我为你提供了一个例子:

public class TestActivity extends Activity {

    private MySingleton singleton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState.containsKey("singleton")) {
            singleton = savedInstanceState.getParcelable("singleton");
        } else {
            singleton = MySingleton.getInstance(5);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("singleton", singleton);
    }

    public static class MySingleton implements Parcelable {

        private static MySingleton instance;
        private int myData;

        private MySingleton(int data) {
            myData = data;
        }

        public static MySingleton getInstance(int initdata) {
            if(instance == null) {
                instance = new MySingleton(initdata);
            }

            return instance;
        }

        public static final Parcelable.Creator<MySingleton> CREATOR = new Creator<TestActivity.MySingleton>() {

            @Override
            public MySingleton[] newArray(int size) {
                return new MySingleton[size];
            }

            @Override
            public MySingleton createFromParcel(Parcel source) {
                return new MySingleton(source.readInt());
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeInt(myData);
        }

    }

}