Thank you a lot!
Just setting setRetainInstance(true) in DialogFragment is not enough. The
dialog just disappears after rotation.
I happen to find a thread:
http://stackoverflow.com/questions/8235080/fragments-dialogfragment-and-screen-rotation
In addition to setRetainInstance(true), we should override
@Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setOnDismissListener(null);
super.onDestroyView();
}
and it works!
However, it is very strange that "IllegalStateException: Can't retain
fragements that are nested in other fragments" does not occur.
ProgressDialog fragment is in fragmentA. It is nested.
2013/9/15 Piren <[email protected]>
> err, actually i've also missed something and read the stacktrace
> incorrectly. Only now i've noticed the NPE was actually in the framework
> code...
> If you didn't already, add SetRetainInstance to the DialogFragment as well
> (in its onCreate, not onCreateDialog).
> as a last resort you can always override onDismiss and avoid calling the
> base class (you should probably still call the Fragment.Dissmiss method and
> handle the BackStack on your own)
>
>
>
>
> On Sunday, September 15, 2013 3:25:41 PM UTC+3, Greenhand wrote:
>>
>> Yes. I am pretty sorry for my carelessness when extracting the related
>> code snippets.
>> new MyAsyncTask.execute() should be new MyAsyncTask(this).execute().
>>
>> As for the MyAsyncTask:
>>
>> public class MyAsyncTask extends AsyncTask<Void,Void,Void>{ //do network
>> operation
>> private Fragment*A* fragment;
>>
>> public MyAsyncTask(Fragment*A* fragmentA){
>> fragment = fragmentA;
>> }
>> If there is any mistake, please feel free to correct me.
>>
>>
>> Piren於 2013年9月15日星期日UTC+**8下午8時08分31秒寫道:
>>
>>> and did you use that constructor? because the code snippet shows you've
>>> used the default constructor
>>>
>>> On Sunday, September 15, 2013 1:52:22 PM UTC+3, Greenhand wrote:
>>>>
>>>> Thanks for pointing out the mistakes. The whole code is too long to
>>>> post and maintain readability so I just put some snippet. The "MyAsyncTask
>>>> having a constructor named GetTokenAsyncTask" is a typo, the constructor
>>>> should named MyAsyncTask.
>>>> As for ProgressFragment, I use its toString() method to check using
>>>> Log.d(). They are the same across rotation.
>>>>
>>>>
>>>>
>>>> 2013/9/15 Piren <[email protected]>
>>>>
>>>>> It's hard to follow your code since it seems some of it is incorrect
>>>>> (like MyAsyncTask having a constructor named GetTokenAsyncTask) and
>>>>> some
>>>>> of it is missing...
>>>>> Either way you should verify you actually used that constructor (in
>>>>> the current code you don't, so the member "fragment" is null).Either case,
>>>>> you should also verify that the proper ProgressFragment is being set
>>>>> during
>>>>> onAttach of FragmentA since i assume a new one will be created after
>>>>> rotation (though i'm not sure about that).
>>>>>
>>>>> Since this isn't that much code, you should probably just find a
>>>>> tutorial on how to do that (there's a lot of those online) and start from
>>>>> scratch (just so you wouldn't miss something)
>>>>>
>>>>> On Sunday, September 15, 2013 1:30:20 PM UTC+3, Greenhand wrote:
>>>>>>
>>>>>> I use appcompat library to host some fragments for tabs. In a
>>>>>> specific fragment A, I need to do network operation. In order not to
>>>>>> block
>>>>>> the UI thread, I use an AsyncTask and do the network operation in
>>>>>> doInBackGround().
>>>>>>
>>>>>> To prevent messing around keep AsyncTask to survive rotation in the
>>>>>> fragment, I call setRetainInstance(true) in the fragment A oncreate().
>>>>>>
>>>>>> It works fine but I need to prompt user something when the network
>>>>>> operation is in progress. Therefore, I use DialogFragment. In the
>>>>>> DialogFragment onCreateView(), it instantiates a ProgressDialog and
>>>>>> returns.
>>>>>>
>>>>>> To be concrete, the following is the code snippets of FragmentA,
>>>>>> MyDialogFragment and AsyncTask :
>>>>>> public class FragmentA extends Fragment{ //as tab for actionbar
>>>>>> (appcompat)
>>>>>> private boolean isNetworkOperationCalled;
>>>>>> private MyDialogFragment myDialogFragment;
>>>>>> ...
>>>>>> public void showProgressDialog(){ //for MyAsyncTask#onPreExecute()
>>>>>> myDialogFragment = new MyDialogFragment();
>>>>>> myDialogFragment.show(**getFra**gmentManager(), "mydialog");
>>>>>> }
>>>>>> public void showProgressDialog(){ //for MyAsyncTask#onPostExecute()
>>>>>> myDialogFragment.dismiss();
>>>>>> }
>>>>>> public void onResume() {
>>>>>> if(!**isNetworkOperationCalled**){
>>>>>> isNetworkOperationCalled=true;
>>>>>> new MyAsyncTask.execute();//do the network operation
>>>>>> }
>>>>>> }
>>>>>> ...
>>>>>> }
>>>>>>
>>>>>>
>>>>>> public class MyDialogFragment extends DialogFragment{
>>>>>> //ProgressDialog for FragmentA
>>>>>> ...
>>>>>> public Dialog onCreateDialog(Bundle savedInstanceState) {
>>>>>> ProgressDialog progressDialog = new ProgressDialog(getActivity(),**
>>>>>> P**rogressDialog.STYLE_SPINNER);
>>>>>> ... //set the dialog attributes
>>>>>> return progressDialog;
>>>>>> }
>>>>>> ...
>>>>>> }
>>>>>> public class MyAsyncTask extends AsyncTask<Void,Void,Void>{ //do
>>>>>> network operation
>>>>>> private Fragment fragment;
>>>>>>
>>>>>> public GetTokenAsyncTask(Fragment fragmentA){
>>>>>> fragment = fragmentA;
>>>>>> }
>>>>>> protected void onPreExecute() {
>>>>>> fragment.showProgressDialog(****); //show progess dialog for users
>>>>>> }
>>>>>> protected String doInBackground(Void... arg0) {
>>>>>> ...
>>>>>> }
>>>>>> protected void onPostExecute() { //dismiss the dialog
>>>>>> fragment.**dismissProgressDial**og();
>>>>>> }
>>>>>> }
>>>>>> In a nutshell, fragment A triggers AsyncTask and AsyncTask call
>>>>>> methods of FragmentA to show/dismiss dialog. Fragment A use
>>>>>> MyDialogFragment to show the progress dialog.
>>>>>>
>>>>>> The code (method) above works if there is no rotataion occurs while
>>>>>> doInBackground() is executing. Nevertheless, if the rotation happens
>>>>>> before
>>>>>> onPostExecute() is called,
>>>>>> the rotation is fine and the progress dialog is retained. Sadly, it
>>>>>> crashes when onPostExecute() finally be called when dismissing the
>>>>>> dialog.
>>>>>>
>>>>>> E/AndroidRuntime(27493): FATAL EXCEPTION: main
>>>>>> E/AndroidRuntime(27493): java.lang.NullPointerException
>>>>>> E/AndroidRuntime(27493): at android.support.v4.app.**DialogF**
>>>>>> ragment.**dismissInternal(**Dialog**Fragment.java:184)
>>>>>> E/AndroidRuntime(27493): at android.support.v4.app.**DialogF**
>>>>>> ragment.dismiss(**DialogFragment**.java:155)
>>>>>> E/AndroidRuntime(27493): at com.example.FragmentA.**dismissP**
>>>>>> rogressDialog(**FragmentA.java:**105)
>>>>>> E/AndroidRuntime(27493): at com.example.FragmentA.access$**1**
>>>>>> (FragmentA.java:103)
>>>>>> E/AndroidRuntime(27493): at com.example.FragmentA$**GetToken**
>>>>>> AsyncTask.**onPostExecute(**FragmentA.java:**40)
>>>>>> E/AndroidRuntime(27493): at com.example.FragmentA$**GetToken**
>>>>>> AsyncTask.**onPostExecute(**FragmentA.java:**1)
>>>>>> E/AndroidRuntime(27493): at android.os.AsyncTask.finish(**As**
>>>>>> yncTask.java:631)
>>>>>> E/AndroidRuntime(27493): at android.os.AsyncTask.access$**60**
>>>>>> 0(AsyncTask.java:177)
>>>>>> E/AndroidRuntime(27493): at android.os.AsyncTask$**InternalH**
>>>>>> andler.handleMessage(**AsyncTask**.java:644)
>>>>>> E/AndroidRuntime(27493): at android.os.Handler.**dispatchMes**
>>>>>> sage(Handler.java:**99)
>>>>>> E/AndroidRuntime(27493): at android.os.Looper.loop(Looper.****
>>>>>> java:137)
>>>>>> E/AndroidRuntime(27493): at android.app.ActivityThread.**mai**
>>>>>> n(ActivityThread.java:4875)
>>>>>> E/AndroidRuntime(27493): at
>>>>>> java.lang.reflect.Method.**invok**eNative(Native
>>>>>> Method)
>>>>>> E/AndroidRuntime(27493): at java.lang.reflect.Method.**invok**
>>>>>> e(Method.java:511)
>>>>>> E/AndroidRuntime(27493): at com.android.internal.os.**Zygote**Init$*
>>>>>> *MethodAndArgsCaller.run(**Z**ygoteInit.java:804)
>>>>>> E/AndroidRuntime(27493): at com.android.internal.os.**Zygote**
>>>>>> Init.main(ZygoteInit.**java:571)
>>>>>> E/AndroidRuntime(27493): at dalvik.system.NativeStart.**main**(Native
>>>>>> Method)
>>>>>>
>>>>>> How can I solve the problem so that the dialog can dismiss correctly
>>>>>> after rotation?
>>>>>>
>>>>>
>>>>>
>>>>>
>>>> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Android Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
---
You received this message because you are subscribed to the Google Groups
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.