原博客地址:https://blog.csdn.net/weixin_40400031/article/details/96324854
使用Handler來解決通訊問題,是開發必備技能,但就是這家喻戶曉的Handler,卻偏偏最容易造成內存泄漏。
接下來我列出幾種使用Handler的方式,以及各自的問題:
關於內存泄漏,請參考:Android 關於內存泄露,你必須瞭解的東西
關於JAVA引用類型,請參考:你真的懂 Java 的內存管理和引用類型嗎?
第一種(公開靜態handler):
寫法:在Activiy中創建公開靜態handler (public static Handler handler),並在onCreate()中實例化,以給其他類使用。
優點:這樣創建handler,可以隨意實現Activity與Activity/Service進行通訊,只要在需要的地方,使用目的Activity的handler調用sendMessage()即可。
缺點:必會造成內存泄漏 (因爲static變量本身不持有Activity的引用,但是在onCreate()中實例化就給handler加上了對Activity的強引用。當Activity銷燬的時候,由於handler的強引用,導致Activity無法被GC回收)
解決辦法:無藥可救,被static變量持有了強引用,那就完了
第二種(非靜態handler):
寫法:在Activity創建一個非靜態匿名內部類對象handler (private Handler handler ) ,並在onCreate()中實例化
優點:相比於第一種,非靜態handler不能被其他類隨意使用,但依舊可以用於網絡等耗時操作,用作結束時的通知(在調用耗時操作時將handler作爲參數傳遞過去,之後等耗時操作結束,再使用該handler調用sendMessage()即可)。但是不會像第一種那樣百分百造成內存泄漏。
缺點:1.只有Activity主動給予handler的地方纔可以使用,無法實現Activity與Activity之間的通訊。
2.如果Activity銷燬時,Handler有未處理或處理中的Message,則Message持有handler,handler持有Activity,導致Activity無法回收
解決辦法:在Activity的onDestroy()中調用handler.removeCallbacksAndMessages()切斷Handler與Activity之間的引用。
第三種(自定義Handler,內部對Activity進行弱引用)
寫法:
//創建子類,採用弱引用:
public abstract class MyHandler extends Handler {
private Activity activity ;
private WeakReference<Activity> weakReference ;
public MyHandler(Activity activity) {
weakReference = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(weakReference.get() == null){
return;
}else{
handle(msg); //處理message
}
}
public abstract void handle(Message msg);
}
//在Activit中創建實例
public class HandlerActivity extends BaseActivity {
public MyHandler handler ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
handler = new MyHandler(context){
@Override
public void handle(Message msg) {
//do something...
}
};
}
}
優點:由於使用了弱引用(WeakReference),所以Activity銷燬時,即使Handler還有message要處理,Activity也依舊會被GC回收。其他功能同第二種。
缺點:沒啥缺點,就是要單獨寫個子類
最後:大家不要搞這麼蛋疼的Handler了,在通訊這塊還是使用EventBus這類成熟框架吧!
如果嫌EventBus書寫分類繁瑣,可以參考小弟的框架EventBox
以上若有不對的,還望指教,謝謝