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.

Reply via email to