软引用和弱引用在安卓开发中的使用

用处一:解决Handler可能造成的内存泄露。

原因分析:为什么Handler可能造成内存泄露。

当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用,不然你怎么可能通过Handler来操作Activity中的View。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。

然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。

解决办法:使用弱引用来解决,模板性代码如下:

package com.crs.demo.ui.widget;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

import java.lang.ref.WeakReference;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:软引用和弱引用在android中的使用
 */
public class TestReferenceActivity extends BaseActivity {
    static class MyHandler extends Handler {
        private WeakReference reference;

        public MyHandler(Activity activity) {
            //使用弱引用包裹当前的activity
            reference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            TestReferenceActivity activity = reference.get();
            //当前Activity不存在或者页面正在关闭的时候,不在进行消息处理
            if (activity != null && !activity.isFinishing()) {
                switch (msg.what) {
                    //此时再进行消息的处理
                }
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_reference);

        //案例一,解决Handler可能造成的内存泄露
        //通过弱引用实现,如果当前activity需要被回收了,而且Handle持有的activity是被弱引用包装的,则垃圾回收器可以释放掉此activity。
        MyHandler myHandler = new MyHandler(this);
    }
}

用处二:解决图片存储时,可能造成的内存不足问题

package com.crs.demo.ui.widget;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.util.LruCache;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

import java.lang.ref.SoftReference;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:软引用和弱引用在android中的使用
 */
public class TestReferenceActivity extends BaseActivity {

    //使用LruCache进行替换,参数为使用多大的内存去存储图片
    //花费虚拟机八分之一的空间去存储图片
    //使用LruCache比软引用更好,因为里面有一套算法,根据图片的使用频率去销毁图片。
    int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
    private LruCache lruCacheMap = new LruCache(maxSize) {
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getRowBytes() * value.getHeight();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_reference);

        String imageUrl=null;
        Bitmap bitmap = null;
        //使用软引用包裹获取到的bitmap
        SoftReference softReference = new SoftReference<>(bitmap);
        lruCacheMap.put(imageUrl, bitmap);

        //通过url获取缓存
        Bitmap bit= lruCacheMap.get(imageUrl);
    }
}


用处三:java中引用类型的原理

Java语言的一个重要特性是引入了自动的内存管理机制,使得开发人员不用自己来管理应用中的内存。自动的内存管理则是把管理内存的任务交给编程语言的运行环境来完成。开发人员并不需要关心内存的分配和回收的底层细节。Java平台通过垃圾回收器来进行自动的内存管理
 
Java垃圾回收机制:
Java的垃圾回收器要负责完成3件任务:分配内存确保被引用的对象的内存不被错误回收以及回收不再被引用的对象的内存空间
垃圾回收是一个复杂而且耗时的操作。如果JVM花费过多的时间在垃圾回收上,则势必会影响应用的运行性能。一般情况下,当垃圾回收器在进行回收操作的时候,整个应用的执行是被暂时中止(stop-the-world)的。对于与用户交互的应用来说,则可能希望所垃圾回收所带来的应用停顿的时间间隔越小越好。对于这种情况,JVM中提供了多种垃圾回收方法以及对应的性能调优参数,应用可以根据需要来进行定制。
 
Java引用类型:
如果一个内存中的对象没有任何引用的话,就说明这个对象已经不再被使用了,从而可以成为被垃圾回收的候选。不过由于垃圾回收器的运行时间不确定,可被垃圾回收的对象的实际被回收时间是不确定的。对于一个对象来说,只要有引用的存在,它就会一直存在于内存中。如果这样的对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误。虽然垃圾回收的具体运行是由JVM来控制的,但是开发人员仍然可以在一定程度上与垃圾回收器进行交互,其目的在于更好的帮助垃圾回收器管理好应用的内存。

强引用(一般垃圾回收器不回收被强引用的对象
在一般的Java程序中,见到最多的就是强引用(strong reference)。如Date date = new Date(),date就是一个对象的强引用。对象的强引用可以在程序中到处传递。很多情况下,会同时有多个引用指向同一个对象。强引用的存在限制了对象在内存中的存活时间。假如对象A中包含了一个对象B的强引用,那么一般情况下,对象B的存活时间就不会短于对象A。如果对象A没有显式的把对象B的引用设为null的话,就只有当对象A被垃圾回收之后,对象B才不再有引用指向它,才可能获得被垃圾回收的机会。

软引用 (内存不足的时候,对象被回收)
软引用(soft reference)在强度上弱于强引用,通过类SoftReference来表示。它的作用是告诉垃圾回收器,程序中的哪些对象是不那么重要,当内存不足的时候是可以被暂时回收的。当JVM中的内存不足的时候,垃圾回收器会释放那些只被软引用所指向的对象。如果全部释放完这些对象之后,内存还不足,才会抛出OutOfMemory错误。软引用非常适合于创建缓存。当系统内存不足的时候,缓存中的内容是可以被释放的。

弱引用  (回收器只要发现一个对象的引用是全部是弱引用,就会回收此对象、释放内存)
弱引用(weak reference)在强度上弱于软引用,通过类WeakReference来表示。它的作用是引用一个对象,但是并不阻止该对象被回收。如果使用一个强引用的话,只要该引用存在,那么被引用的对象是不能被回收的。弱引用则没有这个问题。在垃圾回收器运行的时候,如果一个对象的所有引用都是弱引用的话,该对象会被回收。


你可能感兴趣的:(软引用和弱引用在安卓开发中的使用)