Handler多線程內部實現機制
在Android開發中,我們經常會遇到這樣一種情況:在UI界面上進行某項操作後要執行一段很耗時的代碼,比如我們在界面上點擊了一個”下載“按鈕,那麼我們需要執行網絡請求,這是一個耗時操作,因爲不知道什麼時候才能完成。爲了保證不影響UI線程,所以我們會創建一個新的線程去執行我們的耗時的代碼。當我們的耗時操作完成時,我們需要更新UI界面以告知用戶操作完成了。
注意一下的Handler寫法會導致內存泄漏!!!!!!!!!!:
package com.example.kaifaceshi;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.tv);
}
//handler登場!!!
Handler h=new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 100:
tv.setText("下載完成!");
break;
}
}
};
public void button1(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//注意:不能再非主線程內調用UI控件
//發送一個空消息
h.sendEmptyMessage(100);
//獲取一個消息對象
Message msg=h.obtainMessage();
msg.obj="hello";
msg.what=100;
h.sendMessage(msg);
//在指定時間發送
h.sendEmptyMessageAtTime(100,System.currentTimeMillis()+300);
//延遲發送
h.sendEmptyMessageDelayed(100,200);
}
}).start();
}
}
正確標準的寫法應該是:!!!!!!!!!!!!!!!
package com.example.kaifaceshi;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
/*
* 總之Handler導致內存泄漏的原因就是:
* 主Activity已經退出了,Handler依然引用着主Activity的資源,以導致內存泄漏
*/
public class MainActivity extends Activity {
private static TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.tv);
}
myHandler myHandler=new myHandler(this);
//**************************
static class myHandler extends Handler{
WeakReference<MainActivity> weak;
public myHandler (MainActivity Activity) {
weak=new WeakReference<MainActivity>(Activity);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
MainActivity activity=weak.get();
if(activity!=null) {
TextView v=(TextView) activity.findViewById(R.id.tv);
v.setText("下載完成!");
}
}
}
//**************************
}