Handler我們經常使用,handler的消息機制更是差不多面試時的必問考點,今天我們來討論一下handler的內存泄露等問題,這個問題也算是老生常談了。不多說了,直接代碼,全部註釋裏面了
public class MainActivity extends Activity {
//定義爲final虛擬機會使用內聯機制提升性能
private final MyHandler myHandler=new MyHandler(this);
private int i=0;
private TextView textView;
private final MyAsyncTask myAsyncTask=new MyAsyncTask();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView)findViewById(R.id.content);
}
//asyncTask的用法
private class MyAsyncTask extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
//模擬耗時任務
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if(MainActivity.this.isFinishing()){
return;
}
initViews();
}
}
//防止handler內存泄露的標準寫法
private static class MyHandler extends Handler
{
//弱引用 GC想回收隨時回收
private WeakReference<MainActivity> weakReference;
public MyHandler(MainActivity activity) {
weakReference=new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
if(weakReference.get()!=null){
weakReference.get().initViews();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacksAndMessages(null);//移除所有待處理message
//取消任務
if (myAsyncTask!=null&&myAsyncTask.getStatus()!= AsyncTask.Status.FINISHED) {
myAsyncTask.cancel(true);
}
}
private void initViews(){
textView.setText(i + "");
}
//想到的計時器
//計時器方式1
private void timer1(){
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i = (int) (Math.random() * 1000);
myHandler.sendEmptyMessage(0x11);
}
}
}).start();
}
//計時器方式2
private void timer2(){
Timer timer=new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
//子線程
i = (int) (Math.random() * 1000);
myHandler.sendEmptyMessage(0x11);
}
}, 1000, 1000);
}
//計時器方式3
private void timer3(){
final Handler handler=new Handler();
Runnable runnable=new Runnable() {
@Override
public void run() {
//主線程
i = (int) (Math.random() * 1000);
initViews();
handler.postDelayed(this,1000);
}
};
handler.postDelayed(runnable,1000);
}
}
其他
/**
* 內部也是調用handler的post(Runnable runnable) 最後調用handler的sentMessage方法
*/
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
看源碼
//如果當前線程不是ui線程,調用在ui線程中創建的handler的post方法,否則立即執行run方法
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}