2013-08-14 7 views
6

Il mio gestore statico ha un WeakReference sul mio Activity (questo per evitare il problema di perdita di memoria ben documentato).Gestore Android che modifica WeakReference

Inserisco un messaggio ritardato e desidero inviare questo messaggio alla mia attività (che dovrebbe essere in primo piano).

La mia preoccupazione è che il cambiamento di orientamento, la mia attività è distrutta e il gestore ha un riferimento alla vecchia attività che avrebbe dovuto essere distrutto.

Al fine di aggirare questo nel mio onCreate per l'attività faccio questo.

if(mHandler == null) 
     mHandler = new LoginHandler(this); 
    else { 
     mHandler.setTarget(this); 
    } 

E il mio gestore viene dichiarata come variabile globale statica:

private static LoginHandler  mHandler   = null; 

e la classe che implementa è anche statica, come di seguito:

private static class LoginHandler extends Handler { 

    private WeakReference<LoginActivity> mTarget; 

    LoginHandler(LoginActivity target) { 
     mTarget = new WeakReference<LoginActivity>(target); 
    } 

    public void setTarget(LoginActivity target) { 
     mTarget = new WeakReference<LoginActivity>(target); 
    } 

    @Override 
    public void handleMessage(Message msg) { 
     // process incoming messages here 
     LoginActivity activity = mTarget.get(); 
     switch (msg.what) { 
      case Constants.SUCCESS: 
       activity.doSomething(); 
       break; 

      default: 
       activity.setStatusMessage("failed " + msg.obj, STATUS_TYPE_DONE); 
     } 
    } 
} 

Quello che voglio sapere è se ci c'è qualcosa di sbagliato nel cambiare WeakReference su onCreate o c'è qualcos'altro che non va in questo approccio?

Grazie,

+0

@CommonsWare alcuna opinione su questo? – Ali

risposta

5

Così ho scritto il seguente test per capire se ho avuto l'idea giusta o no e sembra che l'approccio m è corretto. Nello onCreate cambiamo lo WeakReference e il messaggio inviato verrà sempre consegnato all'attività che si trova in primo piano. Se modifichi questo codice per creare sempre un nuovo gestore in onCreate noterai che i messaggi di aggiornamento non vengono recapitati.

public class MainActivity extends Activity { 

    private static int COUNT = 0; 

    static LoginHandler mHandler; 

    private static class LoginHandler extends Handler { 

     private WeakReference<MainActivity> mTarget; 

     LoginHandler(MainActivity target) { 
      mTarget = new WeakReference<MainActivity>(target); 
     } 

     public void setTarget(MainActivity target) { 
      mTarget.clear(); 
      mTarget = new WeakReference<MainActivity>(target); 
     } 

     @Override 
     public void handleMessage(Message msg) { 
      // int duration = Toast.LENGTH_LONG; 
      // process incoming messages here 
      MainActivity activity = mTarget.get(); 
      activity.update(msg.arg1); 
     } 
    } 

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

     if(mHandler == null) 
      mHandler = new LoginHandler(this); 
     else 
      mHandler.setTarget(this); 

     ((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       Message msg = new Message(); 
       msg.arg1 = COUNT++; 
       mHandler.sendMessageDelayed(msg, 3000); 

      } 
     }); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    private void update(int count) { 
     ((TextView) findViewById(R.id.hello_world)).setText("Hello World @ "+ count); 
    } 

} 
0

Una soluzione ad allontanarsi con l'attività di distruggere-e-creare il ciclo di vita, se si desidera mantenere gli oggetti attivi è quello di rendere l'uso dei "frammenti" di ritenzione.

L'idea è semplice, stai dicendo al sistema Android di "conservare" il tuo frammento, quando l'attività associata viene distrutta e ricreata. E assicurati di afferrare il contesto dell'attività corrente nel richiamo di onAttach() del frammento, in modo da aggiornare sempre l'attività corretta.

Sotto Link ha maggiori dettagli: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html