2016-9-5

本文探讨了Android中导致内存溢出的多种原因,并提出了预防措施。包括避免静态成员对象和内部类对Activity的强引用,正确使用HandlerThread,以及在Android 5.0及以上版本实现按钮水波纹效果的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2016-9-5

1.Android内存溢出的几种情况

Android中的内存溢出基本发生在以下三种情况:
    1.成员或全局静态对象或单例对象对activity的强引用
    2.不在activity生命周期内的线程对activity的强引用
    3.activity中生命周期不可控的内部类或匿名类对activity的隐式引用
  在activity中引用着大量的view和其他资源,如果在ondestory()后没能把activity回收,则会造成内存溢出
以下是几种场景:
    1. activity内的静态成员对象引用运行状态的activity(如把activity以参数的形式传给静态成员对象,并且在此对象中对其持续引用), 静态对象会在内存中一直保持加载状态,这个对象持有了对activity的引用,就不会被GC回收, 如果在activity生命周期结束时没有清除引用则会引起activity泄漏
    2. 在单例模式的类中不能持有activity的context,即不能把activity传给单例类来构造对象
    2. activity中的view被实例成静态的, 在activity中的view会持有对它的context的引用, 如果必须使用静态view要确保activity完成前把View从视图层级中分离出去
    3. 在activity中的内部类的静态变量引用了activity的context, 这时可以使用WeakReference包裹,在使用时先判空再使用
    4. 匿名类持有包含它的类的引用, 如在activity中匿名地声明并且实例化一个AsyncTask, 在activity销毁后它仍在后台工作的话, 对activity的引用会持续到后台工作完成才进行GC
    5. 注意在activity中创建(非静态)内部类或匿名类, 都会对包含它的类有隐式的应用,不要在activity中创建生命周期不可控的内部类或匿名类如(AsyncTask) 
    5. Handler的后台任务, 定义的Runnable对象被Handler加入了执行队列,Runnable会引用定义它的activity并持有到Handler的消息队列中,只要在activity销毁前消息还没被处理,activity就会被保留在内存中,要注意在activity销毁时从Hanlder移除Runnable对象
    6. Thread或TimerTask持有activity的引用, 在activity销毁时注意移除
    7. 在单例类中持有activity的context
在activity中初始化对象时,要留心潜在的引用, 对activity的引用要是WeakReference, 并及时观测程序运行时内存的释放情况
在需要传入Context的时候尽量考虑使用Application的Context,而不是Activity的
在Activity中尽量避免使用生命周期不受控制的非静态类型的内部类(如匿名类),可以使用静态类型的内部类加上弱引用的方式实现

2.HandlerThread使用

1.创建并启动 mHandlerThread = new HandlerThread("HandlerThread");
    mhandlerThread.start();
2.使用HanlderThread中的Looper创建Hanlder
    Handler handler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {// 非UI线程

            }
        };
3.在任意线程发送消息
4.onDestory()中退出 
    mHandlerThread.quit();
    或mHandlerThread.quitSafely();//是针对在消息队列中还有消息或者是延迟发送的消息没有处理的情况,调用这个方法后都会被停止掉
HandlerThread继承Thread其内部维护了一个Looper,使用HandlerThread不用手动去调用Looper.prepare()和Looper.loop()等方法,Handler依赖Looper来维护发出的消息,在一个线程中创建Handler必须为其指定Looper,在UI线程Android已创建好了Looper,使用Context.getMainLooper();可以获得

3.android5.0按钮水波纹(ripple)效果使用

<?xml version="1.0" encoding="utf-8"?>  
<ripple xmlns:android="http://schemas.android.com/apk/res/android"  
    android:color="#FFEEEEEE">  

    <item android:id="@id/mask" android:drawable="@color/white" />  

</ripple> 
ripple相当于layer-list层叠效果,ripple元素的color属性即指定了波纹效果的颜色,但必须是8位颜色代码值,前两位指定了波纹的透明度,后六位即波纹颜色,以黑色000000及白色FFFFFF效果最为明显
<item android:id="@id/mask" android:drawable="@color/white" />即指定了按钮的正常状态的显示效果
必须在5.0以上有效果, 可以新建drawable-v21文件夹, 在drawable和drawable-v21放两套同名的文件,drawable-v21为5.0以上使用, drawable为5.0以下使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值