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(…)中的那个片段上.
解决方法
我的解决方案
首先,你应该使用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的数量,因此请注意内存泄漏!