在Android开发中巧妙使用观察者模式避免内存泄露

来源:互联网 发布:windows更新失败 编辑:程序博客网 时间:2024/06/06 20:16

发生内存泄露的场景:
场景1:静态变量引用Activity对象
场景2:静态View
场景3:内部类和匿名类
场景4:Handler
场景5:Threads和TimerTask
场景6:监听器
场景7:静态集合对象引起的泄漏
场景8:资源对象未关闭
场景9:使用对象池避免频繁创建对象
场景10:Back键退出引起的泄漏

现在有这么一个场景(场景3|场景6):在Activity里定义了一个Listener,这个Listener的实例需要以参数的形式传递到SDK里,SDK执行完耗时的操作(比如扫描蓝牙),然后执行该Listener的回调方法。这样一来,在扫描的过程中,如果我们按了返回键,Activity并不能正常销毁,因为SDK拥有Listener的强引用,这样就发生了内存泄露。
解决方法:
1. SDK提供了停止耗时操作的接口,那么在销毁Actiivity的时候调用该接口停止耗时操作即可。
2. 假设没有提供相关接口,可使用观察者模式解决:
①编写一个被观察者接口:

/** * Created by zhanzc on 2017/7/18. * 被观察者 */public interface IObservable {    void update();}

②编写一个观察者:

/** * Created by zhanzc on 2017/7/18. * 观察者类 */public class DataWatcher {    private static DataWatcher dataWatcher;    private DataWatcher(){}    public static DataWatcher getInstance() {        if (dataWatcher == null) {            initWatcher();        }        return dataWatcher;    }    private static synchronized void initWatcher() {        if (dataWatcher == null) {            dataWatcher = new DataWatcher();        }    }    // 一般来说,这应该是一个集合,但我这里只监听可能发生内存泄露的Activity,所以只用了一个observable    private IObservable observable;    /**     * 添加被观察者     * @param observable     */    public void register(IObservable observable) {        this.observable = observable;    }    /**     * 解除监听     */    public void unregister(IObservable ob) {        this.observable = null;    }    /**     * 通知被观察者更新数据     */    public void notifyObservable() {        if (this.observable != null) {            this.observable.update();        }    }}

③Activity实现接口成为被观察者,实现相关方法:

@Overridepublic void update() {    // 更新UI}

④onCreate()方法执行

// 观察者观察被观察者DataWatcher.getInstance().register(this);

⑤Linstener的class定义为static

⑥Listener的回调里调用:

// 通知被观察者更新数据DataWatcher.getInstance().notifyObservable();

⑦onDestroy()执行:

// 解除观察DataWatcher.getInstance().unregister(this);

如果你的项目引入了EventBus或RxJava等有订阅/被订阅关系的框架,也可以直接使用,操作都一样。

原创粉丝点击