java中的引用和GC

java中的引用和GC

  1. 简介:java中有四种引用:强软弱虚
    1. 强引用: strong Reference,=就是强引用方式,即时出现OOM,GC都不会销毁强引用
    2. 软引用: soft Reference,当Java所管理的内存趋于阈值时,GC将会销毁一部分软引用,释放内存。
    3. 弱引用: weak Reference,就算Java所管理的内存没有趋于阈值,GC都有可能销毁部分弱引用。
    4. 虚引用: 按照GC回收优先度,虚引用肯定是最早被回收的,这个基本开发的时候不会用到
  2. GC:Garbage Collection,是java和C++的主要区别之一,这里简单介绍一下,如果有时间再去写详细介绍,
    1. 垃圾回收机制,java程序员不需要去自己回收内存,不想C和C++的程序员,但是电脑去执行回收机制肯定做不到人那样根据需要去回收,所以会造成一定程序的内存浪费,这就是为什么对安卓里面的OOM很重视。
    2. GC在执行的时候模,所有的线程都会被暂停。当Java所管理内存趋于阈值时,GC的执行频率将会加快,这时候就会出现卡顿的感觉,用户体验杀手。
  3. 下面结合一些代码讲一下这个问题
    1. 早期的时候,图片显示是手机的一个大问题,因为早期手机内存过小,后来出现了高压缩率的图片jpg之类的图片问题得到部分改善,后来内存又扩大,这个问题基本得到了解决,但是随着时间,图片的数量越来越多,再结合服务器,考虑到流量问题。下面具体分析listview结合服务器的图片下载问题
    2. 首先,listview采用了viewholder和adapter进行了优化,但是如果涉及到图片,如果单纯的把图片存在RAM部分,那么加载速度会非常慢,而listview的滑动操作是很快的,这时候就会出现图片没有加载完成所显示的view就不需要了,影响用户体验,之前有写过解决这个问题的方法,是采用了异步任务加中断的方式,但是这种情况适用性有限,而且不好用,性能提升不明显

3. 速度慢的原因是需要去ram中读取的图片的速度过慢导致,所以想到一个办法,将图片存入内存,但当图片过多的时候会出现OOM问题,java程序员是没有办法回收不用的图片内存的,GC这个时候也不会去回收强引用,所以要使用软应用甚至弱引用来解决,这其实是一个二级缓存机制,具体请看下面的代码

    package cn.myapp.musicclient.util;

import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;

/**
 * 图片异步批量加载的工具类
 * 提供图片的内存缓存与文件缓存
 */
public class ImageLoader {
    //声明工作线程
    private Thread workThread;
    private boolean isLoop=true;
    //存储缓存图片
    private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
    private Context context;
    //生成任务集合
    private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
    private AbsListView listView;
    //声明handler
    private Handler handler=new  Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case HANDLER_IMAGE_LOAD_SUCCESS:
                //更新ImageView
                ImageLoadTask task=(ImageLoadTask)msg.obj;
                //通过position做的tag 找到相应的ImageView
                ImageView ivAlbum=(ImageView)listView.findViewWithTag(task.position);
                if(ivAlbum!=null){
                    Bitmap bitmap=task.bitmap;
                    if(bitmap!=null){
                        ivAlbum.setImageBitmap(bitmap);
                    }else{
                        ivAlbum.setImageResource(R.drawable.ic_launcher);
                    }
                }
                break;
            }
        }
    };
    public static final int HANDLER_IMAGE_LOAD_SUCCESS=0;



    public ImageLoader(Context context, AbsListView listView) {
        this.listView=listView;
        this.context=context;
        //初始化workThread
        workThread=new Thread(){
            public void run() {
                //不断的查看集合中是否有数据
                while(isLoop){
                    //如果集合中有图片下载任务
                    if(!tasks.isEmpty()){
                        //把第一个图片下载任务获取并执行
                        ImageLoadTask task=tasks.remove(0);
                        //直接下载图片
                        Bitmap bitmap=loadBitmap(task.path);
                        //把bitmap设置到相应的ImageView中
                        //需要在主线程中  (发消息给handler)
                        task.bitmap=bitmap;
                        Message msg=new Message();
                        msg.what=HANDLER_IMAGE_LOAD_SUCCESS;
                        msg.obj=task;
                        handler.sendMessage(msg);
                    }else{
                        //如果任务集合中已经没有任务了 
                        //那么线程等待
                        synchronized (workThread) {
                            try {
                                workThread.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        };
        workThread.start();
    }

    /**
     * 通过path 发送http请求 下载图片
     * @param path 
     * images/junshengjinshi.jpg
     * @return
     * @throws IOException 
     * @throws ClientProtocolException 
     */
    public Bitmap loadBitmap(String path) {
        try {
            String url=GlobalConsts.BASEURL+path;
            HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, url, null);
            //把entity转成Bitmap
            byte[] bytes=EntityUtils.toByteArray(entity);
            Bitmap bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
            //向内存缓存中 缓存图片
            cache.put(path, new SoftReference<Bitmap>(bitmap));
            //向缓存目录中 保存图片
            File targetFile=new File(context.getCacheDir(), path);
            //targetFile:   /data/data/com.xx.xx/cache/images/jsjs.jpg
            BitmapUtils.save(bitmap, targetFile);

            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 显示图片
     * @param imageView  控件
     * @param path 图片路径
     * @param position 图片的位置
     */
    public void displayImage(ImageView imageView, String path, int position){
        imageView.setTag(position);
        //从缓存中获取  如果有 则直接显示
        //不在向任务集合中添加任务了。
        SoftReference<Bitmap> ref=cache.get(path);
        if(ref!=null){
            Bitmap bitmap=ref.get();
            if(bitmap!=null){
                Log.i("info", "这是从内存缓存中读取的图片..");
                imageView.setImageBitmap(bitmap);
                return;
            }
        }
        //内存缓存中没有图片 则去文件缓存中读取
        String filepath=new File(context.getCacheDir(),path).getAbsolutePath();
        Bitmap bitmap=BitmapUtils.loadBitmap(filepath);
        if(bitmap!=null){
            Log.i("info", "从文件缓存中读取的图片..");
            imageView.setImageBitmap(bitmap);
            //存入内存缓存
            cache.put(path, new SoftReference<Bitmap>(bitmap));
            return;
        }

        //向任务集合中添加任务
        ImageLoadTask task=new ImageLoadTask();
        task.path=path;//保存图片路径
        task.position=position;
        tasks.add(task);
        //唤醒工作线程workThread  起来干活
        synchronized (workThread) {
            workThread.notify();
        }
    }

    class ImageLoadTask{
        String path;
        Bitmap bitmap;
        int position;
    }

    public void stopThread() {
        isLoop=false;
        synchronized (workThread) {
            workThread.notify();
        }       
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值