最近在做相册,但是发现当手机图片过多时,直接卡到ANR,这个问题困扰了我很久。
我怀疑了Glide缓存的问题。设置了Glide的缓存,内存等。
也怀疑了是一次性读取图片过多的问题。为此我做了读取分页加载,一次加载30张图片。但是当我图片加载到了300+的时候,又开始卡顿了。
这时我看到了我的xml里是用的:NestedScrollView+RecyclerView
我把RecyclerView单独拿出来,不用NestedScrollView进行包裹。这个时候,加载3000+图片,丝滑无比!
如果有和我一样用NestedScrollView+RecyclerView来做大量图片加载的同学,你尝试将RecyclerView单独拿出进行加载。
至于这其中的缘由,等我空了再进行分析,先做个避坑记录。
分页加载代码:
//监听RecyclerView滑动到底部,触发加载
//loadAllMediaData2(page);
//loadSourceFolder();
/*RecyclerView mView= mAlbumAllView.getAlbumRecyclerView();
mView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == SCROLL_STATE_IDLE) {
if (!mView.canScrollVertically(1)) { // 到达底部
page += 1;
loadAllMediaData2(page);
} else if (!mView.canScrollVertically(-1)) { // 到达顶部
}
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});*/
异步读取相片
/**
* 分页加载读取
*/
int page=1;
@SuppressLint("CheckResult")
private void loadAllMediaData2(int page){
int pagesize = 30;
List<AbstractBaseLocalFile> videoList = new ArrayList<>();
Observable.just("")
.subscribeOn(Schedulers.io())
.map(new Function<String, List<AbstractBaseLocalFile>>() {
@Override
public List<AbstractBaseLocalFile> apply(@NonNull String s) {
Cursor mCursor = null;
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] proj = {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DATE_MODIFIED,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.MIME_TYPE
};
mCursor =
mContext
.getContentResolver()
.query(
mImageUri,
proj,
MediaStore.Images.Media.MIME_TYPE
+ "=? or "
+ MediaStore.Images.Media.MIME_TYPE
+ "=? or "
+ MediaStore.Images.Media.MIME_TYPE
+ "=?",
new String[] {"image/jpeg", "image/png", "image/jpg"},
null);
if (mCursor != null) {
int position = (page - 1) * pagesize + 1;
//int position = (mCursor.getCount() - 1) / pagesize + 1;
mCursor.moveToPosition(position);
Log.i("tang","page ======"+page);
Log.i("tang","position1 ======"+position);
Log.i("tang","count ======"+mCursor.getCount());
while (mCursor.moveToNext()) {
long modifiedData = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED));
int imgId = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media._ID));
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));
long size = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Images.Media.SIZE)) / 1024;
long data = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_TAKEN));
// String mimiType =
// mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.ImageColumns.MIME_TYPE));
if (size < 0) {
// 某些设备获取size<0,直接计算
size = new File(path).length();
}
// 获取该视频的父路径名
File file = new File(path);
if (!file.exists()) {
continue;
}
File parentFile = file.getParentFile();
if (parentFile == null || !parentFile.exists()) {
continue;
}
String dirPath = parentFile.getAbsolutePath();
LocalImageInfo itemBean = new LocalImageInfo();
itemBean.setId(imgId);
itemBean.setPath(path);
itemBean.setParentPath(dirPath);
itemBean.setSize(size);
MediaFile.MediaFileType fileType = MediaFile.getFileType(path);
if (fileType != null) {
itemBean.setMimeType(fileType.mimeType);
}
if (modifiedData == 0) {
itemBean.setModifyDate(data);
} else {
itemBean.setModifyDate(modifiedData);
}
videoList.add(itemBean);
if (page == 1 && mCursor.getPosition() == pagesize){
break;
}
if (mCursor.getPosition() >= pagesize * page){
break;
}
Log.i("tang","position2 ======"+mCursor.getPosition());
}
}
sortMediaDate(videoList);
return videoList;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<AbstractBaseLocalFile>>() {
@Override
public void accept(List<AbstractBaseLocalFile> list) {
mAlbumAllView.showAlbumRecyclerView();
// 只有图片类型,不存在多种Type
if (mAlbumType == 0) {
updateAlbumAdapter(mDataList, mAlbumAllAdapter, TYPE_IMG);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
}
});
}