Handler实现倒计时并优化内存

时间:2021-04-07 10:16:27

我们先看一个简单的例子


MainActivity.java

package com.studio.countdowntime;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

public static final int COUNTDOWN_TIME_CODE = 10001;
public static final int DELAY_MILLIS = 1000;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//得到控件
final TextView countdownTimeTextView = (TextView) findViewById(R.id.countdownTimeTextView);

Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg != null && msg.what == COUNTDOWN_TIME_CODE){
countdownTimeTextView.setText(String.valueOf(9));
}
}
};

Message message = Message.obtain();
message.what = COUNTDOWN_TIME_CODE;

handler.sendMessageDelayed(message, DELAY_MILLIS);
}
}

我们这么写程序运行结果是没有问题的,但是我们会发现handler上有一个警告:
Handler实现倒计时并优化内存
大意是这个handler应该是静态的,否则会造成内存泄露。原因是我们看到if语句中的countdownTimeTextView是一个在Mainactivity里面定义的控件对象,假如if语句还没有执行到,而当前的Activity已经被销毁了,这个时候发的消息还有可能过来,过来之后还持有这个控件的引用,还需要处理if语句。这个时候handler还持有Activity,但是该Acitivity垃圾回收的时候就无法回收,这个时候就有可能造成内存的泄露


Java 中强应用和弱引用

package com.studio.countdowntime;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {

/**
* 倒计时标记handler code
*/

public static final int COUNTDOWN_TIME_CODE = 10001;
/**
* 倒计时间隔
*/

public static final int DELAY_MILLIS = 1000;
/**
* 倒计时最大值
*/

public static final int MAX_COUNT = 10;

private TextView countdownTimeTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//得到控件
countdownTimeTextView = (TextView) findViewById(R.id.countdownTimeTextView);

//创建了一个handler
CountdownTileHandler handler = new CountdownTileHandler(this);

//新建了一个message
Message message = Message.obtain();
message.what = COUNTDOWN_TIME_CODE;
message.arg1 = MAX_COUNT;

//第一次发送message
handler.sendMessageDelayed(message, DELAY_MILLIS);
}

public static class CountdownTileHandler extends Handler {
public static final int MIN_COUNT = 0;

final WeakReference<MainActivity> mWeakReference;

CountdownTileHandler(MainActivity activity) {
mWeakReference = new WeakReference<>(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);

MainActivity mainActivity = mWeakReference.get();

switch (msg.what) {
case COUNTDOWN_TIME_CODE:

int value = msg.arg1;

mainActivity.countdownTimeTextView.setText(String.valueOf(value--));

//循环发消息控制
if (value >= MIN_COUNT) {
Message message = Message.obtain();
message.what = COUNTDOWN_TIME_CODE;
message.arg1 = value;
sendMessageDelayed(message, DELAY_MILLIS);
}
break;
}
}
}
}