IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 内存泄漏 -> 正文阅读

[移动开发]Android 内存泄漏

内存泄漏的定义

进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。Activity对象持有其View层以及所有相关的资源,因此Activity内存泄漏会使内存变小许多。

内存泄漏的几种情况及解决方法

  1. 单例模式下传入当前Activity的context,单例一直持有Activity的context直到单例生命周期结束,Activity退出也不会被回收。
public class SingleInstanceClass {
   private static SingleInstanceClass instance;
   private Context mContext;
   //创建单例时,需传入Context
   private SingleInstanceClass(Context context){
       //this.mContext= context;//传入的是Activity的context
       this.mContext= context.getApplicationContext();//传入Application的Context

   }
   //由于单例一直持有Activity的context引用直至单例生命周期的结束,即使Activity退出也不会被回收
   public static SingleInstanceClass getInstance(Context context){
       if(instance==null){
           instance = new SingleInstanceClass(context);
       }
       return instance;
   }

   @Override
   public String toString() {
       return "SingleInstanceClass{" +
               "mContext=" + mContext +
               '}';
   }
}

解决方法:用getApplicationContext代替当前Activity的context。

  1. 采用了非静态的内部类,由于非静态的内部类的对象隐含保存了一个引用,指向它的外部对象,因此在回收时无法回收外部类。销毁重建后并没有被回收,会存在两个实例。
public class InnerClassMemoryLeak extends AppCompatActivity {
    private static final String TAG = "InnerClassMemoryLeak";
    //尽量使用静态内部类,令内部类变为外部类相关,而非实例相关。
    // 一个非静态内部类的生命周期不受控制容易导致内存泄漏。
    private TextView view;
    //普通的内部类对象隐含地保存了一个引用,指向创建它的外围类对象。
    //mDemo会一直持有InnerClassActivity的引用,因此无法回收。InnerClassActivity销毁后重建会存在两个实例。
    static Demo mDemo;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        view = new TextView(InnerClassMemoryLeak.this);
        view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        view.setText("启动一个持有本对象的线程");
        view.setTextSize(40);
        view.setTextColor(Color.parseColor("#0000ff"));
        setContentView(view);
        mDemo = new Demo();
        mDemo.run();
    }
    class Demo{
        void run(){
            Log.i(TAG, "run: ");
        }
    }
}
  1. 线程引起内存泄漏

    启动线程的匿名内部类会隐式持有外部Activity的引用,当线程仍在运行而外部的Activity已经被销毁时会造成内存泄漏。
    解决方法:尽量不使用匿名内部类,将内部类改为静态内部类,并使用弱引用WeakReference来保存Activity实例。

public class ThreadMomeryLeak extends AppCompatActivity {
    private static final String TAG = "ThreadMomeryLeak";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread_momery_leak);
        new Mythread().start();

    }
/*    private class Mythread extends Thread{
        @Override
        public void run() {
            super.run();
            try {
                Thread.sleep(1000000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }*/
    //加上static关键字
    private static class Mythread extends Thread{
        @Override
        public void run() {
            super.run();
            try {
                while(true){
                    Log.i(TAG, "running...");
                    Thread.sleep(1000L);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
  1. Handler引起的内存泄漏,若MessageQueue中一个Message长时间未被取出,Message有Handler的引用,Handler有Activity的引用,若Activity退出时Handler还有Message需要处理,那么Activity不会被回收。

    解决方法:弱引用Activity,将Handler设置为静态内部类。

public class HandlerMemoryLeak extends AppCompatActivity {

    private Handler mHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_memory_leak);
        mHandler=new MyHandler(this);
        mHandler.sendEmptyMessage(0);
    }
    static class MyHandler extends Handler{
        //弱引用Activity
        private WeakReference<HandlerMemoryLeak> mActivityRef;
        public MyHandler(HandlerMemoryLeak activity){
            mActivityRef = new WeakReference<HandlerMemoryLeak>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            HandlerMemoryLeak mla = mActivityRef == null ? null : mActivityRef.get();
            if(mla == null || mla.isFinishing()){
                return;
            }


        }
    }
  1. 资源未及时关闭

    解决方法:及时在onDestroy中close();

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:19:37  更:2021-08-25 12:21:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年2日历 -2025/2/25 12:18:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码