Android系统事件的recycle原理 博客分类: Android Android

    最近封装一些功能性的jar包,因为需要产生一些动作,然后给调用者一些回调,所以用到了事件和监听器。     举个例子,比如DragListener和DragEvent,最开始写的时候,每次Drag动作都触发一个DragEvent事件,然后就得new一个DragEvent对象。后来感觉这样太浪费内存了,然后就研究了一下系统的MotionEvent这个类,找到了好的 解决方案。

    MotionEvent的构造方法是匿名的,不能直接创建,对外提供的获取对象的接口是静态的obtain方法,可以从一个MotionEvent对象获取,也可以从一些变量获取。为什么说它是个好的解决方案呢,因为它提供了一个recycle方法 ,可以将当前的对象回收,下次要用的时候就不用重新再new一个新的对象了,直接从它的回收池里面拿就行。

下面讲解一下,MotionEvent里面有几个比较重要的变量,如下 :

        //变量
	private MotionEvent mNext; //指向回收栈的下一个对象
	private boolean mRecycled; //标志是否是被回收掉的对象
	//静态变量
	static private final int MAX_RECYCLED = 10;//最大可回收的数目
	static private Object gRecyclerLock = new Object();//锁定整个类用的
	static private int gRecyclerUsed = 0;//回收栈中回收的对象数目
	static private MotionEvent gRecyclerTop = null;//回收栈的栈顶对象

然后有一个静态的obtain方法:

static private MotionEvent obtain() {
        synchronized (gRecyclerLock) { //锁住整个类
            if (gRecyclerTop == null) {//栈顶不存在,就new一个新的
                return new MotionEvent();
            }
            MotionEvent ev = gRecyclerTop;//栈顶存在,就用一个引用ev指向它
            gRecyclerTop = ev.mNext;//然后把栈顶的下一个对象提到栈顶
            gRecyclerUsed--;//回收栈中的对象数目减少一个
            ev.mRecycledLocation = null;//是一个异常,作用未知
            ev.mRecycled = false;//当前对象标志为未回收状态
            return ev;
        }
    }

其它几个obtain方法都首先调用obtain()方法从回收栈中获取对象,然后赋值。

它的recycle方法如下:

public void recycle() {
        // 确保recycle方法只调用一次
        if (TRACK_RECYCLED_LOCATION) {
            if (mRecycledLocation != null) {
                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
            }
            mRecycledLocation = new RuntimeException("Last recycled here");
        } else if (mRecycled) {
            throw new RuntimeException(toString() + " recycled twice!");
        }

        synchronized (gRecyclerLock) {//锁住类
            if (gRecyclerUsed < MAX_RECYCLED) { //如果回收栈中的对象还没达到最大值
                gRecyclerUsed++;	//回收栈中元素数目增加1
                mNumHistory = 0;	
	//这两句是把当前对象的next指向以前的栈顶,然后把当前对象放到栈顶
                mNext = gRecyclerTop;	
                gRecyclerTop = this;
            }
        }
    }

根据这个思路,我也做了一个Event,同样的回收原理,使得事件触发频繁的时候,大大的节约了内存的使用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏androidBlog

java 源码系列 - 带你读懂 Reference 和 ReferenceQueue

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

12110
来自专栏Ryan Miao

java基础面试题

参考:http://blog.csdn.net/jackfrued/article/details/44921941 说未经允许不转载,我只好参考了。 1.面向...

38150
来自专栏向治洪

Kotlin之Elvis 操作符

Elvis 操作符的优先级 首先要注意到,Elvis 操作符的优先级是比较低的,特别是比加减乘除的运算符低,混合运算时一定要记得加上括号。比如: fun <T>...

248100
来自专栏Android 研究

Retrofit解析8之核心解析——ServiceMethod及注解2

这个方法内部很简单,主要就是通过遍历annotations,内部调用parseParameterAnnotation来获取ParameterHandler对象并...

11320
来自专栏MasiMaro 的技术博文

C++ 调用Python3

作为一种胶水语言,Python 能够很容易地调用 C 、 C++ 等语言,也能够通过其他语言调用 Python 的模块。

65850
来自专栏Java学习网

Android性能优化篇:使用软引用和弱引用

Android性能优化篇:使用软引用和弱引用 Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别...

28960
来自专栏大内老A

ASP.NET MVC三个重要的描述对象:ControllerDescriptor

ASP.NET MVC应用的请求都是针对某个Controller的某个Action方法,所以对请求的处理最终体现在对目标Action方法的执行。而Action方...

19270
来自专栏积累沉淀

Java设计模式(二十三)----解释器模式

解释器模式 定义:解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个...

20950
来自专栏信安之路

php 不用字母,数字和下划线写 shell

还有这个师傅的 《记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)》

55110
来自专栏恰童鞋骚年

.NET基础拾遗(1)类型语法基础和内存管理基础

在.NET中所有的内建类型都继承自System.Object类型。在C#中,不需要显示地定义类型继承自System.Object,编译器将自动地自动地为类型添...

12520

扫码关注云+社区

领取腾讯云代金券