2014-12-14 15 views
5

Qualcuno può rispondere a questa domanda per me:Android Attività Stato Perdita

A scopo di verifica ho creato un'attività con un ciclo for in cui sto creando 10 AlertDialogs o 10 DialogFragments. Immediatamente dopo l'avvio dell'attività, premo il pulsante Home per inviare l'app in background. Se sto correndo il metodo ShowDialog() per creare le DialogFragments l'applicazione si bloccherà con: comportamento

IllegalStateException: Can not perform this action after onSaveInstanceState 

questo è previsto.

Ma se eseguo il metodo showAlert() per creare AlertDialogs e lo stesso di prima che io invii l'app in background, l'app non si blocca. Quando torno all'attività posso vedere tutti i 10 AlertDialogs.

La domanda è: perché la perdita di stato dell'attività si verifica con DialogFragment e non con AlertDialog?

Sto ancora cambiando l'interfaccia utente dopo che lo stato dell'attività è stato salvato. La piattaforma su cui ho testato è 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; 
    } 
} 

risposta

1

La risposta è molto semplice, anche se un po 'deludente.

L'eccezionale eccezione java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState viene effettivamente generata dalla classe FragmentManager. Il motivo per cui è spiegato molto bene in this post by Alex Lockwood.

DialogFragments sono frammenti (e quindi gestiti da FragmentManager). Pertanto, mostrare finestre di dialogo in questo modo può provocare l'eccezione. Tuttavia, l'implementazione di AlertDialog è completamente diversa: non utilizza affatto Frammenti (anzi, in realtà è precedente ai Frammenti). Quindi, senza eccezioni.