Android 应用程序恢复时保存列表数据的状态

Android 应用程序恢复时保存列表数据的状态,android,android-activity,android-listview,android-fragments,Android,Android Activity,Android Listview,Android Fragments,这是我的设置 我有一个主要的SherlockFragmentActivity。它将许多列表片段与片段事务来回交换。要指示加载,只要ListFragment加载我调用的数据: setSupportProgressBarIndeterminateVisibility(true); 问题是: 当上面提到的主活动首次启动时,或者用户离开并转到其他应用程序,然后在一段时间后重新启动此应用程序时,SherlockFragmentActivity似乎会重新加载,操作栏中没有进度对话框,屏幕会在几秒钟内保持白

这是我的设置

我有一个主要的
SherlockFragmentActivity
。它将许多
列表片段
片段事务
来回交换。要指示加载,只要
ListFragment
加载我调用的数据:

setSupportProgressBarIndeterminateVisibility(true);
问题是:

当上面提到的主
活动
首次启动时,或者用户离开并转到其他应用程序,然后在一段时间后重新启动此应用程序时,
SherlockFragmentActivity
似乎会重新加载,
操作栏中没有进度对话框
,屏幕会在几秒钟内保持白色,然后列表数据修复(长度取决于数据连接)

下面是一些补充代码:当主/base
活动第一次加载时,这是我在
onCreate()中首先做的事情之一:

followFragment
是将始终在此实例中加载的片段。它包含一个
ListView
和一个
AsyncTask
MySQL
数据库中提取数据

我的问题:如何防止这种延迟?当用户长时间离开时,如何维护数据

根据,在调用
setSupportProgressBarInDeterminateVibility()之前,必须请求进度条功能。

另一个问题是重新加载片段,这是由于Android杀死了您的
ListFragment
,因此必须重新加载这些片段可以通过覆盖
onSaveInstanceState(Bundle outState)
并在那里缓存要在
ListFragment
中检索的数据来解决:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if(savedInstanceState != null) {
        // retrieve data from Bundle here
    } else {
        // no data, we need to reload from network
    }

    // initialize your View here
}
但是,这个方法不能保证一直运行(它不在片段生命周期中)。因此,您还应该确保将数据缓存在
onPause()
中,并使用它,而不是总是从网络连接加载数据

@Override
public void onPause() {
    super.onPause();
    SharedPreferences prefs = getActivity().getSharedPreferences();
    SharedPreferences.Editor editor = prefs.edit();
    // put your data here using editor
    editor.commit();
}

然后,您可以通过检索
SharedReferences
的实例,并使用
prefs.getString(字符串键)
和其他方法,将此数据加载到
onCreateView()
中。

这是正常的行为,因为当您的应用程序处于后台时,您的活动已被终止,以便为其他应用程序节省内存。当它回到前台时,系统会重新创建你的活动,这将重新创建你的片段

但如果您确实希望避免重新创建片段,可以在片段的onCreate方法中使用setRetainInstance:

公共void setRetainInstance(布尔保留)

控制是否在活动重新创建期间保留片段实例(例如从配置更改)。这只能用于不在后堆栈中的片段。如果设置,则重新创建活动时片段生命周期将略有不同:

不会调用onDestroy()(但仍然会调用onDetach(),因为片段正在从其当前活动中分离)。 由于未重新创建片段,因此不会调用onCreate(Bundle)。 仍将调用onAttach(活动)和onActivityCreated(捆绑)

并在FragmentActivity的onActivityCreated方法中使用如下内容:

@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        FragmentManager fm = getFragmentManager();

        // Check to see if we have retained the worker fragment.
        mRetainableFragment = (RetainedFragment)fm.findFragmentByTag("fragmentTag");

        // If not retained (or first time running), we need to create it.
        if (mRetainableFragment == null) {
            mRetainableFragment = new RetainedFragment();
            // Tell it who it is working with.
            mRetainableFragment.setTargetFragment(this, 0);
            fm.beginTransaction().add(mRetainableFragment, "fragmentTag").commit();
        }
    }
但请注意,这应该只用于无头片段(没有UI的片段,即onCreateView中返回null,也称为工作片段)。不过,您仍然可以对UI片段使用此方法,但google不建议使用此方法,在这种情况下,数据必须存储为活动中的成员(字段)。如果Bundle类支持应存储的数据,则可以使用onSaveInstanceState()方法将数据放置在Bundle中,并使用onActivityCreated()方法检索该数据


此外,这仅在片段未添加到backbackback时有效。

当您在延长时间后返回活动时,整个应用程序将重新启动。因此,您不能依赖对象变量来保存数据

所以,在activity onStop()方法中将数据保存到某些本地存储中,可以避免前面提到的延迟。例如,共享首选项


当您调用onCreate()时,请检查是否保存了数据,并在数据存在时使用它(并在下次清理时启动“清理”),否则启动asynctask

当您的应用程序被终止时,您将丢失活动状态和数据!关于您的
异步任务
,我可以假设两种情况:
1.您正在从
Web服务器
中提取一些数据。在这种情况下,我个人认为缓存从
webserver
检索的数据比实现
serializable
更好 2.您正在从本地数据库中提取大量数据(这导致检索数据需要一些时间)。在这种情况下,我建议只检索您需要的数据,而不是更多!(例如,您可以检索20个项目,当用户滚动到
ListView
的末尾时,可以检索下20个项目)。 此解决方案可帮助应用程序更快地检索数据


PS:为了给您一个如何使用缓存功能实现
WebserviceModule
的线索,我假设它位于
AsyncTask
中,您可以将
webserver
的每个响应保存在SD卡中,并且每次尝试从
webserver
检索某些资源时,您应该检查SD卡,查看您的请求是否已发送和缓存!对于每个请求,您应该基于
url
post参数创建一个唯一的签名,以识别缓存文件。

是,这是一个UI
片段。所以我想我需要使用
onSaveInstanceState()
方法。您将如何使用它并保存列表数据?列表由一个
列表组成。我通常将数据存储在一个管理器(单例)中,在那里我可以从任何地方获取数据。这样我就不需要保存UI实例状态。否则,您可以轻松地存储列表,因为它实现了serializ
@Override
public void onPause() {
    super.onPause();
    SharedPreferences prefs = getActivity().getSharedPreferences();
    SharedPreferences.Editor editor = prefs.edit();
    // put your data here using editor
    editor.commit();
}
@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        FragmentManager fm = getFragmentManager();

        // Check to see if we have retained the worker fragment.
        mRetainableFragment = (RetainedFragment)fm.findFragmentByTag("fragmentTag");

        // If not retained (or first time running), we need to create it.
        if (mRetainableFragment == null) {
            mRetainableFragment = new RetainedFragment();
            // Tell it who it is working with.
            mRetainableFragment.setTargetFragment(this, 0);
            fm.beginTransaction().add(mRetainableFragment, "fragmentTag").commit();
        }
    }