Android音乐播放器4.0(Android中的GC垃圾回收机制、图片优化)

160 阅读3分钟

这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战

GC 垃圾回收机制

tt.png

当main()方法执行完,main()方法中的局部变量都会弹栈,从栈当中销毁 当左侧栈中的e2和e销毁后,右侧中的两个对象就是垃圾 java底层有一种GC垃圾回收机制,在java程序运行时,GC线程会不断找寻垃圾,是的话会清除掉

【GC垃圾回收机制】 垃圾回收是一种自动的存储管理机制。 当一些被占用的内存不再需要时,就应该予以释放,以让出空间,这种存储资源管理,称为垃圾回收(Garbage Collection)。

Java 语言提供了自动的 GC 机制,系统会经常检查内存,采用对象引用计数的方式,将引用次数为 0 的对象回收。这样可以防止两个危险:(1)防止无用对象占用内存资源 (2)防止有用对象被释放,引起内存非法引用。

当 Java 程序在运行时,GC垃圾回收机制也将会在适当的时候执行,GC将会把内存中的垃圾对象所占用的内存自动释放掉

【什么时候将会执行垃圾回收机制】 (1)应用进程空闲的时候,GC会回收空闲进程的内存资源。 (2)应用进程繁忙的时候,当需要的内存资源不足的时候, GC会强制执行回收优先级比较低的进程资源,如果还是不足,则再回收两次,还是不足则会报OOM

【GC的特点】 GC 在执行的过程中,所有线程暂停。等 GC 执行完毕后,所有线程再继续执行。 所以我们需要减少 GC 的执行频率

当我们点击模拟机的返回键时,发生了什么

9.png

当GC想回收Activity时,发现被Adapter引用

在这里插入图片描述

当GC想回收Adapter时,发现有一条阻塞的线程

在这里插入图片描述

当我们点击手机的返回键时,Activity并不会被销毁,当再打开时,我们观察运行的线程,会增加一条。返回再打开,又会增加线程...... 如何查看工作的线程

在这里插入图片描述

在这里插入图片描述

解决办法如下: 在NewMusicListFragment中重写onDestroy()方法

  @Override
    public void onDestroy() {
        //把adapter中的线程销毁
        adapter.stopThread();
        super.onDestroy();
    }

MusicAdapter中增加stopThread()方法

    public void stopThread() {
        //isLoop为false,循环停止
        isLoop = false;
        //当我们按返回键时,线程在wait(),应先唤醒
        synchronized (workThread) {
            workThread.notify();
        }
    }

重复刚才操作,不会新增线程

在这里插入图片描述

android 垃圾回收机制

Java 中的引用

1、强引用 Strong Reference 就算出现 OOM,GC 也不会销毁任何强引用。 2、软引用 Soft Reference 当 Java 所管理的内存趋于阈值时,GC 将会销毁部分软引用释放内存 3、弱引用 Weak Reference 引用强度弱于软引用 4、虚引用......

如何使用软引用实现内存缓存

HashMap<path,SoftReference<Bitmap>> cache;
存:
cache.put(url,new SoftReference(bitmap));
取
SoftReference ref = cache.get(url);
if(ref!=null){
	Bitmap bitmap = ref.get();
	if(bitmap != null){
		//设置 ImageView
	}
}

修改 MusicAdapter

/**
 * 音乐列表适配器
 */
public class MusicAdapter extends BaseAdapter {
   ......
    private ListView listView;
    private HashMap<String,SoftReference<Bitmap>> cache = new HashMap<>();
	......

    /**
     * 通过url地址 发送http请求 获取图片
     * @param url
     * @return
     */
    private Bitmap loadBitmap(String url){
        try {
            InputStream is = HttpUtils.getInputStream(url);
            //执行压缩算法,获取合适尺寸的图片
            Bitmap bitmap = BitmapUtils.loadBitmap(is,50,50);
            //Bitmap bitmap = BitmapFactory.decodeStream(is);
            //把bitmap放入内存缓存
            cache.put(url,new SoftReference<Bitmap>(bitmap));
            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
......

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder = null;
        ......
        //给holder.imgPic设置图片
        //先去内存缓存中看有没有
        SoftReference<Bitmap> ref = cache.get(music.getPic_small());
        if(ref!=null){//以前存过
            Bitmap bitmap = ref.get();
            if(bitmap!=null){//以前存的还没有被清掉
                holder.imgPic.setImageBitmap(bitmap);
                return view;
            }
        }
        //向任务集合中一个图片下载任务
        holder.imgPic.setTag(music.getPic_small());
       ......
        return view;
    }
......
}