JVi*_*lla 8 android android-asynctask android-fragments progress-bar
我一直在使用这种模式.这是一个非常人为的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();
Run Code Online (Sandbox Code Playgroud)
方向更改它可以正常工作,但我注意到当我从backstack弹出片段时,片段是非null而fragment.getView()为null.这显然会导致崩溃.你们用什么方法?我似乎无法在网上找到完美的解决方案.重要提示,这是一个片段,我setRetainInstance(true);在onActivityCreated(...)中调用该片段.
AsyncTask is an asynchronous task which means you usually do not know when it is completed and when it calls onPostExecute(). I think your problem is here. When you rotate your device your asynctask has not finished yet and your fragment view is destroyed and recreates again very quickly while still asynctask is on the worker thread and when it has done its job your fragment has a view and getView's return value is not null. But if the rotation time takes much you will get null because the AsyncTask has finished but your fragment does not have any view. Now this scenario is exactly happens to your backstack When you push your fragment on to the backstack its view is destroyed(look at the picture) but the fragment itself is not (the fragment returns to the layout from backstack). Now your AsyncTask finishes and call your fragment getView method and it dose not have any view so you will get NPE.
My solution:
First you should use WeakReference<ProgressBar> instead of WeakReference<MyFragment> and in onPostExecute() check whether it is null or not, if it is null do nothing because the default value is invisible if it is not null call setVisibility(View.GONE).
Update:
the fragment is alive but the view has been dealloc'd. Is this possible?
Yes, just look at the figure2 from link. When fragment is active (green box) the fragment added to back stack fragment goes to onPause, onStop onDestroyView. Then when the fragment pops up from back stack it goes right to onCreateView the arrow link with this text:the fragment returns to the layout from backstack.
In order to confirm my answer you can create an AsyncTask and call SystemClock.sleep(30000) inside your doInbackground. Now you can push your fragment in to the backstack and pops it up from backstack with no exception because the asynctask has not finished and when it will call onPostExecute() your fragment already has a view.
Another good thing you can see is setRetainInstance
This can only be used with fragments not in the back stack.
因此,当您将片段推入后台堆栈时,它可能会完全销毁,并且在弹出时您可能会获得新的片段引用。但是,当您用于setRetainInstance(true);配置更改时,您的片段将在活动重新创建过程中保留,这意味着它是same fragment and onCreate is not called. And this is a very very important thing because if you start your AsyncTask at the onCreate method, when you push your fragment into the back stack and pop it up you may have a new fragment and this means onCreate method runs and another AsyncTask is fired. That means you do not have any control over the number of calling AsyncTasks so watch out for
memory leaks!
| 归档时间: |
|
| 查看次数: |
769 次 |
| 最近记录: |