应用程序恢复时在列表数据上保存状态

时间:2013-07-22 16:41:16

标签: android android-activity android-listview android-fragments

这是我的设置。

我有一个主SherlockFragmentActivity。它与ListFragments来回交换许多FragmentTransaction。要指示加载,只要ListFragment加载我调用的数据:

setSupportProgressBarIndeterminateVisibility(true);

问题:

当上面提到的主Activity 开始时,或者用户离开并转到其他应用,然后在一段时间后重新启动此 SherlockFragmentActivity看似重新加载,ActionBar中没有进度对话框,屏幕为白色几秒钟,然后列表数据修复(长度取决于数据连接)。

以下是一些补充代码:当主要/基本Activity首次加载时,这是我在onCreate()中做的第一件事:

// Set up Main Screen
FragmentTransaction t2 = this.getSupportFragmentManager().beginTransaction();
SherlockListFragment mainFrag = new FollowingFragment();
t2.replace(R.id.main_frag, mainFrag);
t2.commit();

FollowingFragment是在此实例中始终加载的那个。它包含来自ListView数据库的AsyncTaskMySQL数据。

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

4 个答案:

答案 0 :(得分:3)

这是正常行为,因为当您的应用在后台时,您的活动已被杀死以节省其他应用的内存。当它返回到前台时,系统会重新创建您的活动,这将重新创建您的片段。

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

  

public void setRetainInstance(boolean retain)

     

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

     

onDestroy()不会被调用(但是onDetach()仍然会被调用,因为片段正在与其当前活动分离。   因为片段没有被重新创建,所以不会调用onCreate(Bundle)。   仍将调用onAttach(Activity)和onActivityCreated(Bundle)。

在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片段,但谷歌不建议使用此方法,在这种情况下,数据必须作为成员(字段)存储在您的活动中。如果Bundle类支持应存储的数据,则可以使用onSaveInstanceState()方法将数据放入Bundle中,并在onActivityCreated()方法中检索该数据。

此外,只有在未将碎片添加到靠背堆中时,这才有效。

答案 1 :(得分:1)

根据Android developer reference page on Activity,您必须在致电setSupportProgressBarIndeterminateVisibility()之前申请进度条功能:

requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);  
setSupportProgressBarIndeterminateVisibility(true);

另一个问题,重新加载片段,是由于Android杀死了您的ListFragment,因此可以通过覆盖onSaveInstanceState(Bundle outState)来解决他们必须重新加载的问题,并将您的数据缓存到那里以便在{{{ 1}}:

ListFragment

但是不保证此方法始终运行(它不在Fragment生命周期中)。因此,您还应确保将数据缓存在@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(); } 的实例并使用onCreateView()和其他方法在SharedPreferences中加载此数据。

答案 2 :(得分:1)

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

PS:为了向您提供如何实现具有缓存功能的WebserviceModule的线索,我假设该功能位于AsyncTask,您可以保存SD卡中webserver的每个响应每次尝试从webserver检索某些资源时,都应检查SD卡,看看您的请求是否已经发送并缓存了!对于每个请求,您都应该在urlpost parameters上创建一个唯一的签名库来识别缓存的文件。

答案 3 :(得分:0)

延长一段时间后返回活动时,整个应用程序将重新启动。所以你不能依赖对象变量来保存数据。

所以你可以避免延迟你提到过在活动onStop()方法中将数据保存到某个本地存储。例如,共享偏好。

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