android – AsyncTask,Fragments,Views和Backstacks

前端之家收集整理的这篇文章主要介绍了android – AsyncTask,Fragments,Views和Backstacks前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在使用这种模式.这是一个非常人为的AsyncTask进度指示器示例:
new AsyncTask<Void,Void,Void>() {
    WeakReference<MyFragment> weakFragment = new WeakReference<MyFragment>(MyFragment.this);

    @Override
    protected void onPreExecute() {
        Fragment fragment = weakFragment.get();
        if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.VISIBLE);        
    }

    @Override
    protected Document doInBackground(Void... params) {
        Fragment fragment = weakFragment.get();
        if(fragment == null) return null;

        // Do something ...
    }

    @Override
    protected void onPostExecute() {                
        Fragment fragment = weakFragment.get();
        if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.GONE);
    }
}.execute();

方向更改它可以正常工作,但我注意到当我从backstack中弹出片段时,片段非空,fragment.getView()为null.这显然会导致崩溃.你们用什么方法?我似乎无法在网上找到完美的解决方案.重要提示,这是一个片段,我调用setRetainInstance(true);在onActivityCreated(…)中的那个片段上.

解决方法

AsyncTask是一个异步任务,这意味着您通常不知道它何时完成以及何时调用onPostExecute().我想你的问题就在这里.当你旋转你的设备你的asynctask还没有完成你的片段视图被破坏并再次重新创建,而asynctask仍在工作线程上,当它完成它的工作时你的片段有一个视图和getView的返回值不为空.但是如果旋转时间花费很多,那么你将获得null,因为AsyncTask已经完成,但你的片段没有任何视图.现在这个场景恰好发生在你的backstack上当你将你的片段推到backstack时,它的视图被销毁( look at the picture)但是片段本身不是(片段从backstack返回到布局).现在您的AsyncTask完成并调用您的片段getView方法,它没有任何视图,因此您将获得NPE.

我的解决方

首先,你应该使用WeakReference< ProgressBar>而不是WeakReference< MyFragment>并在onPostExecute()中检查它是否为null,如果它为null则不执行任何操作,因为如果它不是null,则默认值是不可见的调用setVisibility(View.GONE).

更新:

the fragment is alive but the view has been dealloc’d. Is this
possible?

是的,只需从链接中查看图2.当片段处于​​活动状态时(绿色框),添加后台堆栈片段的片段将转到onPause,onStop onDestroyView.然后,当片段从后面的堆栈弹出时,它会直接转到onCreateView上带有此文本的箭头链接:片段从backstack返回到布局.

为了确认我的答案,您可以创建一个AsyncTask并在doInbackground中调用SystemClock.sleep(30000).现在你可以将你的片段推送到backstack并从backstack弹出它,没有异常,因为asynctask还没有完成,当它调用onPostExecute()时你的片段已经有了一个视图.

你能看到的另一件好事是setRetainInstance

This can only be used with fragments not in the back stack.

因此,当您将片段推入后堆栈时,它可能会完全破坏,并且当弹出时您可能会获得新的片段引用.但是当你使用setRetainInstance(true)时;对于配置更改,您的片段将在Activity重新创建中保留,这意味着它是相同的片段,并且不会调用onCreate.这是一个非常非常重要的事情,因为如果你在onCreate方法中启动你的AsyncTask,当你将你的片段推入后栈并弹出它时你可能有一个新的片段,这意味着onCreate方法运行并且另一个AsyncTask被触发.这意味着您无法控制调用AsyncTasks的数量,因此请注意内存泄漏!

原文链接:https://www.f2er.com/android/317957.html

猜你在找的Android相关文章