我的设置如下.
我有一个从我的Activity调用的FragmentPagerAdapter,它加载了两个片段.这是在onCreate中设置的.
在onResume中,我调用ASyncTask从数据库加载数据,然后通过加载数据监听器在我的活动onLoadComplete中调用回调.
@OverrIDepublic voID onl oadComplete(JsONArray data) { // Todo auto-generated method stub LocalFragment fragmentB = (LocalFragment)getSupportFragmentManager().findFragmentByTag(ListTag); fragmentB.setList(data); LMapFragment fragmentA = (LMapFragment)getSupportFragmentManager().findFragmentByTag(MapTag); GoogleMap our_map = fragmentA.getMap(); fragmentA.plotP(myLocation,data);}
片段由寻呼机初始化,并且在每个片段代码中,我设置相应的标签,例如在LocalFragment中
@OverrIDepublic voID onAttach(Activity activity) { // Todo auto-generated method stub super.onAttach(activity); String mytag = getTag(); ((PagerTest) activity).setListTag(mytag); Log.d("what",mytag);}
这允许我访问片段,调用其中填充列表或填充地图的函数.有用.
我现在要做的是考虑屏幕方向的变化.如果ASyncTask正在运行时方向已更改,则应用程序崩溃.
正如这里建议的:Hidden Fragments我一直在尝试实现一个隐藏的片段,它保存了我的ASyncTask的状态.所以我所做的就是设置它,所以在我的Activity的onResume中调用一个函数
static LoadDataFromURL the_data = null;static JsONArray pub_data = null;private static final String TAG = "RetainFragment";public RetainFragment() {}public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) { RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG); if (fragment == null) { fragment = new RetainFragment(); fm.beginTransaction().add(fragment, TAG).commit(); // add this } return fragment;}
这基本上保存了我的数据.
基本上这意味着,如果我旋转我的屏幕,我不会再次调用我的ASyncTask ..屏幕只是旋转..它完美地工作.
但是,如果我返回主菜单然后再次单击活动,屏幕将返回空白(但不会崩溃).我的理解是数据作为片段中的对象保留,但重新重新加载活动时,需要再次设置数据.需要调用I.E onl oadComplete来填充列表/映射.
所以我总结说,如果最初在ASyncTask完成之后我将返回的数据保存在我的隐藏片段onRetainInstance中,那么我可以简单地调用onLoadComplete并传递它.
问题是,在这种情况下,似乎尚未调用片段,因此标记为null,并且在onLoadComplete中调用回调会使应用程序崩溃.
多年来我一直在为此而奋斗.
我的ASyncTask是一个单独的类:LoadDataFromURL
我想要实现的目标如下 – 一个fragmentvIEwpager,在屏幕上旋转ASyncTask保留在旋转/附加到新活动,如果它已完成,它不应该再次运行..
任何人都可以建议.
非常感谢
编辑
将我的秘密片段中的变量更改为公共变量后,所有内容似乎都聚集在一起.但是因为我不是100%确定如何/何时调用事物,我不完全理解为什么它起作用..
所以..我调用findOrCreateRetainFragment,它或者创建一个新的’secret’片段或者返回当前实例.
如果它返回当前实例,我不会再次调用我的异步任务.如果不是,我调用我的asynctask并加载数据.
使用此设置,当我加载活动并旋转屏幕时,它会按预期旋转.
现在,当我返回主菜单然后再次单击活动时,它会调用异步任务.
我的理解是,在旋转时,不会再次调用异步任务,并且vIEwpager以某种方式保存片段.
另一方面,当我回去时,我的活动被破坏,就像我的秘密片段一样,当我再次点击它时,它会加载数据.这基本上就是我想要的……
我理解正确吗?
谢谢
解决方法:
这里有一些你遇到的问题(我认为).
首先,回调崩溃的原因是因为它们附加到屏幕方向和/或活动推送后不再“存在”的旧活动.如果使用onAttach()将回调附加到片段,则必须使用onDetach()在从活动中删除片段时分离该回调.然后,每当您调用回调时,请检查null,以便不将数据发送到死对象.
基本上,你在这里尝试使用的逻辑是:
>开始活动.
>检查您的碎片是否存在.如果是的话,抓住它.否则,创造它.
>检索数据是否存在.如果没有,请等待回调.
由于回调的性质(取决于您的实现),在事件触发之前您不会收到数据.但是,如果Activity已经消失并且事件已经触发,则不会执行回调.因此,您必须手动检索数据.使用setRetainInstance()时,将其视为从您的Activity中分离出来的实体是有帮助的.只要您不d出当前活动或推送新活动,它就会存在.但是,当屏幕方向更改时,您的当前活动将被销毁,而片段则不会.因此,Fragment不应该依赖于Activity的存在.
您可能希望查看的问题的更优雅的解决方案是实现AndroID Loader API.加载程序是由系统处理的方便工具,其工作方式大致相同,但与异步检索数据更加协调.他们以同样的方式有效地工作.您只需启动您的加载器和系统,如果它不存在则创建一个或重新使用已存在的系统.配置更改后,LoaderManager将保留在系统中.
编辑:
要回答你的编辑,我想我会解释发生了什么.这是令人费解的,所以只要告诉我是否需要澄清.
从技术上讲,碎片不是您当前运行的Activity的一部分.创建Fragment的实例时,必须在FragmentManager上调用beginTransation()和commit(). FragmentManager是一个存在于应用程序领域内的单例. FragmentManager会为您保留Fragment的实例.然后FragmentManager将Fragment附加到您的Activity(请参阅onAttach()). Fragment然后存在于FragmentManager中,这就是为什么你永远不必在你的应用程序中持有对它的引用.您可以调用findFragmentByTag / ID()来检索它.
在正常情况下,当您的Activity被销毁时,FragmentManager将分离Fragment的实例(请参阅onDetach())并让它继续. Java垃圾收集器将检测到没有对Fragment的引用,并将清理它.
当你调用setRetainInstace()时,你告诉FragmentManager保持它.因此,当您的Activity在配置更改时被销毁时,FragmentManager将保留Fragment的引用.因此,重建Activity时,可以调用findFragmentByTag / ID()来检索最后一个实例.只要它没有保留最后一个Activity的任何上下文,就不应该有任何问题.
传统上,人们会用它来保持对长期数据的引用(就像你一样)或保持连接套接字打开,这样手机翻转就不会删除它.
您的VIEwPager与此无关.它如何检索Fragments完全取决于您如何实现它附加到的Adapter.通常,保留的片段本身没有视图,因为视图保存了创建它们的活动的上下文数据.您基本上只想使它成为一个数据桶,以保持视图从它们被拉出时的数据被夸大了.
总结以上是内存溢出为你收集整理的android – ASyncTask,隐藏片段,保留实例和屏幕方向更改全部内容,希望文章能够帮你解决android – ASyncTask,隐藏片段,保留实例和屏幕方向更改所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)