2014-12-14 13 views
5

Kann jemand beantworten Sie diese Frage für mich:Android-Aktivitätszustand Verlust

Für Testzwecke I mit einer eine Aktivität erstellt haben für Schleife, in der ich 10 AlertDialogs oder 10 DialogFragments bin zu schaffen. Sofort nachdem die Aktivität gestartet wurde, drücke ich die Home-Taste, um die App im Hintergrund zu senden. Wenn ich die Showdialog() -Methode ausgeführt wird, um die DialogFragments zu erstellen die App stürzt mit:

IllegalStateException: Can not perform this action after onSaveInstanceState 

dies ist das erwartete Verhalten.

Aber wenn ich die ShowAlert() - Methode zum Erstellen der AlertDialogs und das gleiche wie zuvor ich die App in den Hintergrund senden, stürzt die App nicht ab. Wenn ich zur Aktivität zurückkehre, kann ich alle 10 AlertDialogs sehen.

Die Frage ist, warum der Aktivitätsstatusverlust mit DialogFragment und nicht mit AlertDialog auftritt?

Ich ändere immer noch die Benutzeroberfläche, nachdem der Status der Aktivität gespeichert wurde. Die Plattform, auf die ich getestet habe, ist 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; 
    } 
} 

Antwort

1

Die Antwort ist sehr einfach, wenn auch ein wenig berauschend.

Die oft gesehen java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState Ausnahme wird tatsächlich von der FragmentManager Klasse geworfen. Der Grund dafür erklärt sich sehr gut in this post by Alex Lockwood.

DialogFragments sind Fragmente (und somit verwaltet von FragmentManager). Daher kann das Anzeigen von Dialogen auf diese Weise die Ausnahme auslösen. Die Implementierung von AlertDialog ist jedoch völlig anders: Es verwendet überhaupt keine Fragmente (tatsächlich ist es tatsächlich älter als Fragmente). Daher keine Ausnahmen.