描述
在使用handler時,一般我們用于解決跨線程操作的問題,一般開啟線程可能是處理耗時操作,因此很可能導致內存泄漏。這里講解一種方式處理這種內存泄漏的方法(同時擴展一下,可以解決類似這種匿名內部類導致的內存泄漏問題,如Thread等)。
插播一下Handler是如何導致內存泄漏的原因(面試時被問到過):
在我們使用Handler的匿名內部類的形式處理問題時,Handler對象會持有我們所在頁面activity或者fragment的對象,Handler在發送消息時,將消息對象存在消息隊列中,不一定會立刻處理,這時如果頁面關閉,則持有的當前頁面的對象仍被引用,無法銷毀,導致泄漏。(在消息分發回來后進行相應的回調操作,很可能導致崩潰,因為當前頁面已經退出,一些資源可能回收了。)
使用靜態內部類來代替匿名內部類
private static class MyHandler extends Handler();
使用靜態內部類的原因是,其不持有外部類的引用。另外同時保證處理耗時操作的Handler對象的生命周期與當前頁面的生命周期同步。(此法同樣適用于Thread等)
使用簡介
因為Handler是靜態的,因此內部所有的對象都必須是靜態的,同時我們需要經處理后的結果放在UI線程處理。所以我們需要聲明一個回調接口,用來傳遞數據。
interface Listener{
void onSuccess(Message msg);
}
對MyHandler添加構造方法和重寫handlerMessage()方法,這里僅僅是將結果傳遞回來,同時也可以做其他操作,根據情況來定。
private static class MyHandler extends Handler {
Listenerlistener;
MyHandler (Listener listener) {
this.listener = listener;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//TODO do something
listener.onSuccess(msg);
}
}
接下來就是使用,我們需要實例化MyHandler對象,和發送消息。
private MyHandler myHandler = new MyHandler (new Listener() {
@Override
public void onSuccess(Message msg) {
String url = (String) msg.obj;
// 獲取結果處理
}
});
//發送消息一般是在子線程中進行
new Thread(new Runnable() {
@Override
public void run() {
myHandler.sendMessage(msg);
}
}).start();
這里我們會看到我們的數據被成功的傳遞會UI線程,然后做相應的處理即可。
看代碼類似的處理還是很簡單的,在這里做一下筆記。