Android中Handler机制(二) 防止内存泄露的Handler封装

1、Handler内存泄露分析

handler导致的内存泄露问题一般有handler匿名类以及Runnable匿名类导致,

Handler匿名类

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };

Runnable匿名类

handler.post(new Runnable() {
    @Override
    public void run() {
        Log.d("run", "执行run方法");
    }
});

匿名类handler以及匿名Runnable类持有Activity对象,Activity结束后,重写的handleMessage方法以及run方法有可能还会再运行,导致Activity不被回收。

2、防止内存泄露的handler

(1)单纯防止内存泄露

针对handler.post方法,可以创建WeakRunnable,弱引用持有Runnable对象,实现Runnable接口

    private static class WeakRunnable extends WeakReference<Runnable> implements Runnable {
        public WeakRunnable(Runnable runnable) {
            super(runnable);
        }

        @Override
        public void run() {
            Runnable runnable = get();
            if (runnable != null) {
                try {
                    runnable.run();
                } catch (Exception e) {
                    e.printStackTrace();
                } 
            }
        }
    }

然后再进行post

    public boolean post(@NonNull Runnable runnable) {
        return postDelayed(runnable, 0);
    }

    public boolean postDelayed(@NonNull Runnable runnable, long delayMillis) {
        WeakRunnable weakRunnable = new WeakRunnable(runnable);
        return handler.postDelayed(weakRunnable, delayMillis);
    }

(2) 根据Activity是否结束来判断是否应该执行

定义一个接口ILive,用来判断Activty或者Fragment是否结束

    public interface ILive {
        boolean isAlive();
    }

Activity重写该方法

    @Override
    public boolean isAlive() {
        return !isDestroyed();
    }

然后对Runnable进行包装,定义成LiveRunnable,弱引用持有ILive对象以及Runnable对象,再进行post。 LiveRunnable的run方法中根据生命周期判断是否应该执行。

    public boolean post(ILive iLive, @NonNull Runnable runnable) {
        return postDelayed(iLive, runnable, 0);
    }

    public boolean postDelayed(ILive iLive, @NonNull Runnable runnable, long delayMillis) {
        LiveRunnable liveRunnable = new LiveRunnable(iLive, runnable);
        return handler.postDelayed(liveRunnable, delayMillis);
    }

    private static class LiveRunnable implements Runnable {
        private WeakReference<ILive> iLiveWeakReference;
        private WeakReference<Runnable> runnable;

        public LiveRunnable(ILive context, Runnable runnable) {
            this.iLiveWeakReference = new WeakReference<>(context);
            this.runnable = new WeakReference<>(runnable);
        }

        @Override
        public void run() {
            ILive iLive = this.iLiveWeakReference.get();
            Runnable runnable = this.runnable.get();
            if (runnable != null) {
                try {
                    if (iLive != null && iLive.isAlive()) {
                        runnable.run();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

(3)  每个消息自带处理方法

如果每个消息都需要有处理方法,可以通过如下方法实现

    public boolean sendMessage(@NonNull Message message, Callback callback) {
        return sendMessageDelayed(message, 0, callback);
    }

    public boolean sendMessageDelayed(@NonNull Message message, long delayMillis, Callback callback) {
        CallbackMessageObject runnable = new CallbackMessageObject(message, callback);
        return handler.postDelayed(runnable, delayMillis);
    }

    private static class CallbackMessageObject extends Pair<Message, WeakReference<Callback>> implements Runnable {

        public CallbackMessageObject(Message first, Callback second) {
            super(first, new WeakReference<>(second));
        }

        @Override
        public void run() {
            Callback callback = second.get();
            if (first != null) {
                try {
                    if (callback != null) {
                        callback.handleMessage(first);
                    }
                    first.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public interface Callback {
        void handleMessage(Message message);
    }

最终消息都会交给对应的callback去处理。

3、封装的Handler,为了防止其他方法被调用,这里使用装饰者模式对handler封装, (移除消息可能需要优化下:Message复用问题需要考虑

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Pair;

import androidx.annotation.NonNull;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;

/*
* @Author ymz0427
*/
public class MainHandler {

    private final static ArrayList<Runnable> list = new ArrayList<>();
    private final static Object lock = new Object();

    private Handler handler;

    private MainHandler(@NonNull Looper looper) {
        handler = new Handler(looper);
    }

    private static MainHandler myHandler;

    public static MainHandler getInstance() {
        if (myHandler == null) {
            synchronized (MainHandler.class) {
                if (myHandler == null) {
                    myHandler = new MainHandler(Looper.getMainLooper());
                }
            }
        }
        return myHandler;
    }

    public boolean post(@NonNull Runnable runnable) {
        return postDelayed(runnable, 0);
    }

    public boolean postDelayed(@NonNull Runnable runnable, long delayMillis) {
        WeakRunnable weakRunnable = new WeakRunnable(runnable);
        synchronized (lock) {
            list.add(weakRunnable);
        }
        return handler.postDelayed(weakRunnable, delayMillis);
    }

    public boolean post(ILive iLive, @NonNull Runnable runnable) {
        return postDelayed(iLive, runnable, 0);
    }

    public boolean postDelayed(ILive iLive, @NonNull Runnable runnable, long delayMillis) {
        LiveRunnable liveRunnable = new LiveRunnable(iLive, runnable);
        synchronized (lock) {
            list.add(liveRunnable);
        }
        return handler.postDelayed(liveRunnable, delayMillis);
    }

    public void remove(Runnable runnable) {
        synchronized (lock) {
            Iterator<Runnable> iterator = list.iterator();
            while (iterator.hasNext()) {
                Runnable temp = iterator.next();
                if (temp instanceof WeakRunnable) {
                    Runnable value = ((WeakRunnable) temp).get();
                    if (value == runnable) {
                        iterator.remove();
                        handler.removeCallbacks(temp);
                        break;
                    }
                } else if (temp instanceof LiveRunnable) {
                    Runnable value = ((LiveRunnable) temp).runnable.get();
                    if (value == runnable) {
                        iterator.remove();
                        handler.removeCallbacks(temp);
                        break;
                    }
                }
            }
        }
    }

    public boolean sendMessage(@NonNull Message message, Callback callback) {
        return sendMessageDelayed(message, 0, callback);
    }

    public boolean sendMessageDelayed(@NonNull Message message, long delayMillis, Callback callback) {
        CallbackMessageObject runnable = new CallbackMessageObject(message, callback);
        synchronized (lock) {
            list.add(runnable);
        }
        return handler.postDelayed(runnable, delayMillis);
    }

    public void removeMessage(Message message) {
        synchronized (lock) {
            Iterator<Runnable> iterator = list.iterator();
            while (iterator.hasNext()) {
                Runnable value = iterator.next();
                if (value instanceof CallbackMessageObject && ((CallbackMessageObject) value).first == message) {
                    handler.removeCallbacks(value);
                    iterator.remove();
                    break;
                }
            }
        }
    }

    private static class WeakRunnable extends WeakReference<Runnable> implements Runnable {
        public WeakRunnable(Runnable runnable) {
            super(runnable);
        }

        @Override
        public void run() {
            Runnable runnable = get();
            if (runnable != null) {
                try {
                    runnable.run();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    synchronized (lock) {
                        list.remove(this);
                    }
                }
            }
        }
    }

    private static class LiveRunnable implements Runnable {
        private WeakReference<ILive> iLiveWeakReference;
        private WeakReference<Runnable> runnable;

        public LiveRunnable(ILive context, Runnable runnable) {
            this.iLiveWeakReference = new WeakReference<>(context);
            this.runnable = new WeakReference<>(runnable);
        }

        @Override
        public void run() {
            ILive iLive = this.iLiveWeakReference.get();
            Runnable runnable = this.runnable.get();
            if (runnable != null) {
                try {
                    if (iLive != null && iLive.isAlive()) {
                        runnable.run();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    synchronized (lock) {
                        list.remove(this);
                    }
                }
            }
        }
    }

    private static class CallbackMessageObject extends Pair<Message, WeakReference<Callback>> implements Runnable {

        public CallbackMessageObject(Message first, Callback second) {
            super(first, new WeakReference<>(second));
        }

        @Override
        public void run() {
            Callback callback = second.get();
            if (first != null) {
                try {
                    if (callback != null) {
                        callback.handleMessage(first);
                    }
                    first.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    synchronized (lock) {
                        list.remove(this);
                    }
                }
            }
        }
    }

    public interface Callback {
        void handleMessage(Message message);
    }

    public interface ILive {
        boolean isAlive();
    }
}

 

 

 


Android中Handler机制(二) 防止内存泄露的Handler封装

上一篇:安卓Activity用户注册界面


下一篇:smarty学习——基本概念