这是我的设置。
我有一个主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
数据库的AsyncTask
和MySQL
数据。
我的问题:如何防止这种延迟?当用户离开较长时间时,如何处理数据维护?
答案 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卡,看看您的请求是否已经发送并缓存了!对于每个请求,您都应该在url
和post parameters
上创建一个唯一的签名库来识别缓存的文件。
答案 3 :(得分:0)
延长一段时间后返回活动时,整个应用程序将重新启动。所以你不能依赖对象变量来保存数据。
所以你可以避免延迟你提到过在活动onStop()方法中将数据保存到某个本地存储。例如,共享偏好。
当你调用onCreate()时,检查你是否已保存数据并在存在时使用它(并清理下次启动时“清理”),否则启动asynctask。