Android相册解决加载大量图片卡顿问题

Android开发中加载相册是很常用的功能,但相册图片过多正常加载会产生卡顿,即便使用线程异步加载图片卡顿问题依然得不到改善。
正常代码:

public class AlbumAdapter extends ?{
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if(bitmap!=null){
            线程加载图片
        }
        else
            读取缓存
    }
}

卡顿原因是无论怎样优化读取IO都是费时的工作,adapter又会一次实例多个子项,导致加载的图片过多,内存占用率过高产生了卡顿。
优化代码:

public class AlbumActivity extends AppCompatActivity{
    private RecyclerView mRecyclerView;
    private List<PhotoItem> photoItemList;
    private List<PhotoItem> selectItemList;
    private int[] photoLayout;
    private AlbumAdapter mAdapter;
    private Handler handler;
    private Button submit;
    private GridLayoutManager gridLayoutManager;
    private static final String[] STORE_IMAGES = {
            MediaStore.Images.Media.DISPLAY_NAME, // 显示的名字
            MediaStore.Images.Media.LATITUDE, // 维度
            MediaStore.Images.Media.LONGITUDE, // 经度
            MediaStore.Images.Media._ID, // id
            MediaStore.Images.Media.BUCKET_ID, // dir id 目录
            MediaStore.Images.Media.BUCKET_DISPLAY_NAME, // dir name 目录名字
            MediaStore.Images.Media.DATA//路径
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_album);
        submit = (Button)findViewById(R.id.submit);
        mRecyclerView = (RecyclerView)findViewById(R.id.list);
        gridLayoutManager = new GridLayoutManager(this, 3);
        mRecyclerView.setLayoutManager(gridLayoutManager);
        mRecyclerView.setHasFixedSize(true);
        photoLayout = new int[2];
        photoLayout[0]=(ScreenHelper.getScreenWidth(this) - ScreenHelper.dp2px(this, 20)) / 3 - ScreenHelper.dp2px(this, 10);
        photoLayout[1] = ScreenHelper.dp2px(this, 110);
        gridLayoutManager.findFirstCompletelyVisibleItemPosition();
        initPhoto();
        notifySubmit();
        mAdapter = new AlbumAdapter(mRecyclerView,photoItemList,selectItemList);
        mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(RecyclerView.ViewHolder viewHolder, int position) {
                notifySubmit();
            }
        });

        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                //停止滑动后缓存当前屏幕图片
                if(newState == 0){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for(int i=gridLayoutManager.findFirstVisibleItemPosition();i<gridLayoutManager.findLastVisibleItemPosition();i++){
                                cacheBitmap(i);
                            }
                        }
                    }).start();
                }
            }
        });

        mRecyclerView.setAdapter(mAdapter);

        handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                mAdapter.notifyImage((int)msg.obj);
                return false;
            }
        });
    }

    private void initPhoto(){
        photoItemList = new ArrayList<>();
        selectItemList = (List<PhotoItem>)getIntent().getSerializableExtra(FinalHelper.IMAGE_PATH);
        if(selectItemList == null)
            selectItemList = new ArrayList<>();
        String path="";
        for(int i=0;i<selectItemList.size();i++){
            path += selectItemList.get(i).getPath()+",";
        }
        Cursor cursor = MediaStore.Images.Media.query(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, STORE_IMAGES,"width >0","date_modified desc");
        cursor.moveToNext();
        for (int i = 0; i < cursor.getCount(); i++) {
            PhotoItem photoItem = new PhotoItem(cursor.getInt(3),path.indexOf(cursor.getString(6))!=-1?true:false,cursor.getString(0),cursor.getString(6));
            photoItemList.add(photoItem);
            cursor.moveToNext();
        }

        //从前往后存缓存缩略图  单线程轮播减少内存消耗确保屏幕不卡顿
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<photoItemList.size();i++){
                    cacheBitmap(i);
                }
            }
        }).start();
    }

    //缓存bitmap
    public void cacheBitmap(int position){
        if(CacheManager.get(photoItemList.get(position).getPath())==null){
            Bitmap bitmap = ImageHelper.getSmallCropBitmap(photoItemList.get(position).getPath(), photoLayout[0], photoLayout[1]);
            CacheManager.put(photoItemList.get(position).getPath(),bitmap);
            Message message = new Message();
            message.obj=position;
            handler.sendMessage(message);
        }
    }

    public void notifySubmit(){
        if(selectItemList.size()>0){
            submit.setBackgroundResource(R.drawable.bg_album_submit_enable);
            submit.setText(getString(R.string.submit) + "(" + selectItemList.size() + ")");
            submit.setTextColor(ContextCompat.getColor(this, R.color.white));
            submit.setAlpha(1f);
            submit.setClickable(true);
        }
        else {
            submit.setBackgroundResource(R.drawable.bg_album_submit);
            submit.setTextColor(ContextCompat.getColor(this, R.color.darkgray));
            submit.setAlpha(.8f);
            submit.setText(getString(R.string.submit));
            submit.setClickable(false);
        }
    }

    public void onSubmit(View view){
        Intent intent = new Intent();
        intent.putExtra(FinalHelper.IMAGE_PATH, (Serializable) selectItemList);
        setResult(Activity.RESULT_OK, intent);
        finish();
    }

    public void onBack(View view){
        finish();
    }

    public void onCancel(View view){
        finish();
    }


}

在读取相册的基本数据后,采用单线程轮播的方式顺序缓存图片缩率图,这样便解决了卡顿问题,在配合缓存类,再次加载相册就可以瞬间全部加载完毕,推荐使用开源的第三方库DiskLruCache实现图片的缩略图缓存。
QQ相册初次加载相册图片也是一张一张的,仿QQ相册实例:http://blog.csdn.net/lishengko/article/details/56495553

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值