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(); } }