Handlerで発生する可能性のあるメモリの漏洩
2406 ワード
前の記事でHandlerを使う方法はこうです.
どのようにokを見ると、実際には潜在的な危険があり、メモリの漏洩を引き起こす可能性があります.mHandlerはHandlerの非静的匿名内部クラスのインスタンスであるため、外部クラスActivityの参照を持っています.メッセージキューはLooperスレッドでメッセージをポーリングし続けていることを知っています.では、このActivityが終了すると、メッセージキューには未処理のメッセージやメッセージが処理されているが、メッセージキューのMessageはmHandlerインスタンスの参照を持ち、mHandlerはActivityの参照を持っているため、このActivityのメモリリソースがタイムリーに回収されず、メモリ漏洩を引き起こす.ここでは弱い引用を導入する必要があります.規範的な書き方は以下の通りです.
まとめ
Handlerによるメモリ漏洩を回避:静的内部クラスは外部クラスへの参照を保持しません.したがって,静的内部クラスを用いることで漏洩を回避できる.また、handler内部で存在する外部クラスActivityを呼び出す場合は、handler内部で弱い参照を使用して存在するActivityを指すことができます.
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
// Handler,
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
/*sendMessage UI handler handleMessage */
mTextView.setText(new_str);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
new_str = "sendMessage UI";
/*sendMessage UI handler( handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
どのようにokを見ると、実際には潜在的な危険があり、メモリの漏洩を引き起こす可能性があります.mHandlerはHandlerの非静的匿名内部クラスのインスタンスであるため、外部クラスActivityの参照を持っています.メッセージキューはLooperスレッドでメッセージをポーリングし続けていることを知っています.では、このActivityが終了すると、メッセージキューには未処理のメッセージやメッセージが処理されているが、メッセージキューのMessageはmHandlerインスタンスの参照を持ち、mHandlerはActivityの参照を持っているため、このActivityのメモリリソースがタイムリーに回収されず、メモリ漏洩を引き起こす.ここでは弱い引用を導入する必要があります.規範的な書き方は以下の通りです.
public class MainActivity extends AppCompatActivity {
private TextView mTextView;
private String new_str = "";
// Handler, , Handler Activity
Handler mHandler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
new_str = "sendMessage UI";
/*sendMessage UI handler( handler)*/
mHandler.sendEmptyMessage(0);
}
}).start();
}
static class MyHandler extends Handler{
WeakReference mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) { mTextView.setText(new_str);
}
}
}
まとめ
Handlerによるメモリ漏洩を回避:静的内部クラスは外部クラスへの参照を保持しません.したがって,静的内部クラスを用いることで漏洩を回避できる.また、handler内部で存在する外部クラスActivityを呼び出す場合は、handler内部で弱い参照を使用して存在するActivityを指すことができます.