2014-12-14 5 views
5

Czy ktoś może odpowiedzieć na to pytanie dla mnie:Android aktywny State Loss

Dla celów testowych Stworzyłem działalność z pętli for, w którym tworzę 10 AlertDialogs lub 10 DialogFragments. Natychmiast po rozpoczęciu działania naciskam przycisk strony głównej, aby wysłać aplikację w tle. Jeśli biegnę metody ShowDialog(), aby utworzyć DialogFragments aplikacja padnie z:

IllegalStateException: Can not perform this action after onSaveInstanceState 

Jest to oczekiwane zachowanie.

Ale jeśli uruchomię metodę showAlert(), aby utworzyć AlertDialogs i tak samo jak poprzednio, wysyłam aplikację na miejsce, aplikacja się nie psuje. Po powrocie do działania widzę wszystkie 10 AlertDialogów.

Pytanie brzmi, dlaczego utrata aktywności występuje w DialogFragment, a nie w AlertDialog?

Nadal zmieniam interfejs użytkownika po zapisaniu stanu działania. Platforma, na której ja testowałem to Android 4.4.2

public class Main extends FragmentActivity 
{ 
    private FragmentActivity activity = this; 
    private MyAsynk myAsynk; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.layout_main); 

     myAsynk = new MyAsynk(); 
     myAsynk.execute(); 
    } 

    private class MyAsynk extends AsyncTask<Void, Void, Void> 
    { 
     private boolean run = false; 

     public MyAsynk() 
     { 
      run = true; 
     } 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      for(int i = 0; i < 10 && run; i++) 
      { 
       try 
       { 
        Thread.sleep(1000); 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 

//    showAlert("loop " + i); 
       showDialog("loop " + i); 
      } 

      return null; 
     } 

     public void stop() 
     { 
      run = false; 
     } 
    } 


    @Override 
    public void onBackPressed() 
    { 
     super.onBackPressed(); 

     if(null != myAsynk) 
     { 
      myAsynk.stop(); 
      myAsynk = null; 
     } 
    } 


    private void showAlert(final String txt) 
    { 
     try 
     { 
      Main.this.runOnUiThread(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        new AlertDialog.Builder(activity).setMessage(txt) 
        .setPositiveButton("Ok", new DialogInterface.OnClickListener() 
        { 
         @Override 
         public void onClick(DialogInterface dialog, int which) 
         { 
          try 
          { 
           if(null != dialog) 
           { 
            dialog.dismiss(); 
           } 
          } 
          catch(Exception e) 
          { 
           e.printStackTrace(); 
          } 
         } 
        }) 
        .show(); 
       } 
      }); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 


    private void showDialog(final String txt) 
    { 
     try 
     { 
      Main.this.runOnUiThread(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        MyDialogFragment newFragment = MyDialogFragment.newInstance(txt); 
        FragmentTransaction ft = Main.this.getSupportFragmentManager().beginTransaction(); 

        newFragment.show(ft, "newFragment"); 
       } 
      }); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

MyDialogFragment.java:

public class MyDialogFragment extends DialogFragment 
{ 
    private MyDialogFragment instance; 

    public static MyDialogFragment newInstance(String text) 
    { 
     MyDialogFragment f = new MyDialogFragment(); 

     Bundle args = new Bundle(); 
     args.putString("text", text); 
     f.setArguments(args); 

     return f; 
    } 

    public MyDialogFragment() 
    { 
     instance = this; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     View v = inflater.inflate(R.layout.my_dialog_fragment, container, false); 
     TextView tv = (TextView) v.findViewById(R.id.tv); 
     Button bu = (Button) v.findViewById(R.id.bu); 

     bu.setOnClickListener(new View.OnClickListener() 
     { 
      @Override 
      public void onClick(View v) 
      { 
       try 
       { 
        if(null != instance && instance.isVisible()) 
        { 
         instance.dismiss(); 
        } 
       } 
       catch(Exception e) 
       { 
        e.printStackTrace(); 
       } 
      } 
     }); 

     tv.setText(getArguments().getString("text")); 

     return v; 
    } 
} 

Odpowiedz

1

Odpowiedź jest bardzo prosta, choć nieco rozczarowująca.

Często zgłaszany wyjątek java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState jest zgłaszany przez klasę FragmentManager. Powód jest bardzo dobrze wyjaśniony w this post by Alex Lockwood.

DialogFragments są Fragmenty (i tym samym zarządzane przez FragmentManager). Dlatego wyświetlanie okien dialogowych w ten sposób może spowodować wyjątek. Jednak implementacja AlertDialog jest zupełnie inna: w ogóle nie korzysta z Fragmentów (w rzeczywistości jest to wcześniejsze Fragmenty). Dlatego nie ma wyjątków.