`
chroya
  • 浏览: 659763 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Android系统事件的recycle原理

阅读更多

    最近封装一些功能性的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,同样的回收原理,使得事件触发频繁的时候,大大的节约了内存的使用。

2
0
分享到:
评论

相关推荐

    安卓Android源码——防止内存溢出浅析.zip

    Android系统使用Java虚拟机(Dalvik或ART)进行内存分配和管理,但如果不妥善处理,很容易引发内存溢出(Out Of Memory,简称OOM)。本篇文章将深入浅析Android源码中的内存管理机制,以及如何预防和处理内存溢出...

    基于Android模拟系统截屏【100012419】

    Android系统并没有直接提供一个用于截取整个屏幕的API,但可以通过组合使用不同的方法来实现。例如,我们可以利用`WindowManager`服务获取当前顶级窗口,然后通过`View`对象的`draw()`方法将屏幕内容绘制到一个`...

    Recycle Bitmap In Layout

    在Android系统中,Bitmap对象是非常消耗内存的,特别是对于高清或者大量的图片。如果不正确地管理这些对象,可能会导致内存溢出(Out Of Memory,OOM)错误,使应用崩溃。因此,适时地释放不再使用的Bitmap是非常...

    android 屏幕截屏源码分享

    在Android系统中,屏幕截屏是一项常见的功能,用于捕捉设备屏幕上显示的内容。本文将深入探讨Android屏幕截屏的实现原理,并分享相关的源码分析。在Android开发中,我们可以使用多种方式来实现屏幕截屏,包括系统...

    android大位图二次采样处理三

    1. 内存限制:Android系统对每个应用分配了一定量的内存,当加载大位图时,如果超过分配的内存限制,可能会引发OutOfMemoryError。 2. 图片解码:大位图在内存中解码时会占用大量空间,即使图片在磁盘上的大小并不大...

    Android 自定义TimePicker组件

    总之,Android的TimePicker组件虽然简单,但通过深入理解其工作原理并进行自定义,我们可以创造出满足各种设计需求的时钟选择器。自定义组件不仅可以提高用户体验,还能增强应用的个性化和差异化,是提升产品品质的...

    android优化技术详解

    2. 避免内存泄漏:资源对象没关闭、构造 Adapter 时不习惯使用缓存的 convertView、没有及时释放对象的引用、不再使用 Bitmap 对象时调用 recycle() 释放内存。 3. 使用 application 的 context 来替代 activity 的 ...

    通过java实现Android截图源码

    Android系统提供了SurfaceComposerClient和DisplayContent类,它们允许我们访问设备的显示内容。通过创建一个SurfaceComposerClient实例,我们可以获取到Display的引用,然后读取其内容,将其保存为图像文件。以下是...

    Android简单实现自定义控件

    在Android开发中,自定义控件是提升应用独特性和用户体验的有效方式。本教程将引导初学者如何简单地创建一个自定义控件,该控件基于`...随着你对Android系统理解的深入,你将能够创造出更多富有创意的自定义UI元素。

    Android view构造方法第3个参数详解 demo

    了解View的构造方法及其参数对于优化布局加载和理解Android系统的工作原理至关重要。本文将深入解析`Android view构造方法第3个参数详解 demo`,并提供相关的实践示例。 首先,我们来看一下View类的主要构造方法: ...

    初中级Android开发社招面试之Bitmap.pdf

    调用recycle()后,还需将Bitmap对象置空,最后通过System.gc()提示系统进行垃圾回收,但无法保证立即回收。 3. 如何计算一张Bitmap所占内存大小? - Bitmap所占内存大小可以通过宽度像素乘以高度像素再乘以单个...

    android ImageView动态设置尺寸、圆角(绝对好用)

    Android系统并未内置网络图片加载功能,因此通常我们会借助第三方库,如Glide、Picasso或 Fresco。以Glide为例,加载网络图片非常简单: ```java Glide.with(this) .load("http://example.com/image.jpg") .into...

    android图片墙lrucache oom

    在Android中,每个应用都有自己的Dalvik虚拟机实例,其内存限制由Android系统决定。如果图片加载不当,尤其是在滚动列表时一次性加载过多图片,可能导致内存占用过高,进而引发OOM。 二、LRUCache原理 LRUCache...

    android 自定义Editext

    在Android开发中,自定义`EditText`是一种常见的需求,它允许开发者根据应用的特定需求来扩展或修改系统提供的默认编辑框功能。自定义`EditText`可以实现诸如输入格式验证、特殊样式显示、交互效果增强等多种功能。...

    Android高级应用源码-(Android平台)可以根据手势简单缩放图片.zip

    - `GestureDetector`:Android系统提供的类,用于识别基本的手势,如单击、双击、滑动等。在`DragImageView`中,可能通过`GestureDetector`监听用户的缩放和平移手势。 - `ScaleGestureDetector`:另一个关键类,...

    android 重写控件添加自定义属性

    在Android开发中,有时我们需要对系统提供的控件进行扩展,以满足特定的需求,这就涉及到控件的重写和自定义属性的添加。本篇将详细讲解如何在Android中实现这一功能。 首先,我们要理解Android控件重写的基本原理...

    Android bitmap

    Bitmap类是Android系统提供的用于处理图像的主要类,但需要注意的是,Bitmap对象本身并不直接创建,而是通过BitmapFactory类来解析并创建。BitmapFactory提供了多种从不同来源解码图像的方法,如从资源、文件路径或...

    android 面试题集

    - **Android操作系统**: 基于Linux内核,属于软实时操作系统,不适用于对实时性有极高要求的应用场景。 #### 5. 最长短信的字节数 - **中文短信**: 最长约为70字符(包括标点),约等于160字节。 - **英文短信**: ...

    Android图片压缩源代码

    本资源提供了一个基于Eclipse的Android图片压缩的Demo,通过分析和实践这个Demo,开发者可以了解并掌握Android图片压缩的基本原理和技术。 首先,我们来看图片压缩的基本方法。Android提供了多种图片处理库,如...

    Android放大镜

    首先,Android放大镜功能的核心是利用Android系统的触控事件(Touch Events)和自定义View来实现。当用户在屏幕上滑动手指时,系统会接收到一系列的MotionEvent,这些事件包含了手指在屏幕上的位置信息。通过监听...

Global site tag (gtag.js) - Google Analytics