2013-08-14 7 views
6

私の静的ハンドラはWeakReferenceからActivityになりました。これはよく文書化されたメモリリークの問題を防ぐためです。Androidハンドラの変更WeakReference

私は長い遅延メッセージを投稿し、このメッセージを自分のアクティビティ(フォアグラウンドにあるはずです)に配信します。

オリエンテーションを変更すると、自分のアクティビティが破棄され、ハンドラは破棄されたはずの古いアクティビティへの参照を持っています。

これを回避するには、私のonCreateでこれを行います。

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

そして、私のハンドラは、静的なグローバル変数として宣言されています。私が知りたいことならば

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); 
     } 
    } 
} 

があります:

private static LoginHandler  mHandler   = null; 

と実装クラスは以下のようにも静的ですWeakReferenceをonCreateに変更すると何かが間違っているのですか、それともこの方法に間違いがありますか?

おかげで、

+0

は、この上の任意の意見を@CommonsWare:リンク以下

は、より多くの詳細を持っていますか? – Ali

答えて

5

は、だから、私は正しい考えを持っていたかどうかを把握するために、次のテストを書いて、Mのアプローチが正しいと思われます。 onCreateではWeakReferenceが変更され、投稿されたメッセージは常にフォアグラウンドにあるアクティビティに配信されます。 onCreateに常に新しいハンドラを作成するようにこのコードを変更すると、更新メッセージが配信されないことがわかります。

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

アクティブオブジェクトを保持したい場合は、アクティビティの破棄と作成のライフサイクルを回避するための解決策は、「Retent Fragments」を使用することです。

アイデアはシンプルで、関連するアクティビティが破棄され再作成されているときに、フラグメントを「保持」するようにAndroidシステムに指示しています。また、フラグメントのonAttach()呼び出し可能コード内の現在のアクティビティのコンテキストを取得して、正しいアクティビティを常に更新していることを確認してください。 http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

関連する問題