Android进阶之路

解决安卓倒计时 CountDownTimer类 内存泄漏

2020-03-25  本文已影响0人  唐小鹏

项目集成了leakCanary在进入开户页面总是报内存泄漏,找了找,原来是CountDownTimer导致
现在直接给出修改后的方案

    CountDownTimerUtils mCountDownTimerUtils = null;  //写到外面,全局变量方便退出的时候销毁

点击控件的地方

if (mCountDownTimerUtils == null) {
mCountDownTimerUtils = new CountDownTimerUtils(tvGetVeri, 60000, 1000);
}
mCountDownTimerUtils.start();

其实不难发现,CountDownTimer的原理还是用到了Handler,所以很容易造成内存泄漏问题,当Activity或者Fragment关闭而倒计时还未结束的时候,会在后台一直执行,而很多时候我们用倒计时会有更新UI的操作,而控件都持有activity的引用,长期得不到释放的话就会造成内存泄漏,不仅需要控件执有弱引用,也需要在activity或fragment销毁的时候调用cancle方法。


    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
                    long delay;

                    if (millisLeft < mCountdownInterval) {
                        // just delay until done
                        delay = millisLeft - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, trigger onFinish without delay
                        if (delay < 0) delay = 0;
                    } else {
                        delay = mCountdownInterval - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, skip to next interval
                        while (delay < 0) delay += mCountdownInterval;
                    }

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };

写一个工具类继承CountDownTimer,注意textview需要弱引用

    public class CountDownTimerUtils extends CountDownTimer {
        private WeakReference<TextView> mTextView;//显示倒计时的文字  用弱引用 防止内存泄漏

        public CountDownTimerUtils(TextView textView, long millisInFuture, long countDownInterval) {
            //countDownInterval:每次的间隔时间  单位都是毫秒
            super(millisInFuture, countDownInterval);
            this.mTextView = new WeakReference(textView);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            //用弱引用 先判空 避免崩溃
            if (mTextView.get() == null) {
                cancle();
                return;
            }
            mTextView.get().setClickable(false); //设置不可点击
            mTextView.get().setText(millisUntilFinished / 1000 + getResources().getString(R.string.get_code_s));  //设置倒计时时间
            mTextView.get().setTextColor(getResources().getColor(R.color.color_common_normal));
        }

        @Override
        public void onFinish() {
            //用软引用 先判空 避免崩溃
            if (mTextView.get() == null) {
                cancle();
                return;
            }
            mTextView.get().setText(getResources().getString(R.string.restart_get_code));
            mTextView.get().setClickable(true);//重新获得点击
            mTextView.get().setTextColor(getResources().getColor(R.color.color_4D8CF5));
        }

        public void cancle() {
            if (this != null) {
                this.cancel();
            }
        }
    }
@Override
    protected void onDestroy() {  
        super.onDestroy();
        // 写为全局变量是为了这里用
        if (mCountDownTimerUtils != null) {
            mCountDownTimerUtils.cancel();
            mCountDownTimerUtils = null;
        }
    }
上一篇下一篇

猜你喜欢

热点阅读