Switch from contentUris to fileUris in the media gallery.

Android Q encounters massive slowdown when using contentUris for media.
Switching to fileUris (which we're already doing for the folder
thumbnail) gets us back to the expected performance level.
This commit is contained in:
Greyson Parrelli 2019-07-30 16:10:58 -04:00
parent a6890fc8dd
commit a46e7541d0
3 changed files with 14 additions and 7 deletions

View File

@ -23,6 +23,7 @@ import android.widget.ImageView;
import com.bumptech.glide.load.Key; import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.signature.MediaStoreSignature; import com.bumptech.glide.signature.MediaStoreSignature;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
@ -31,6 +32,8 @@ import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.File;
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> { public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
@NonNull private final RecyclerView recyclerView; @NonNull private final RecyclerView recyclerView;
@ -103,7 +106,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
public void onBindItemViewHolder(RecentPhotoViewHolder viewHolder, @NonNull Cursor cursor) { public void onBindItemViewHolder(RecentPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
viewHolder.imageView.setImageDrawable(null); viewHolder.imageView.setImageDrawable(null);
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID)); String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN)); long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
long dateModified = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_MODIFIED)); long dateModified = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_MODIFIED));
String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE)); String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE));
@ -113,7 +116,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation))); int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation))); int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
final Uri uri = Uri.withAppendedPath(baseUri, Long.toString(id)); final Uri uri = Uri.fromFile(new File(path));
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation); Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
@ -121,6 +124,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
.load(uri) .load(uri)
.signature(signature) .signature(signature)
.diskCacheStrategy(DiskCacheStrategy.NONE) .diskCacheStrategy(DiskCacheStrategy.NONE)
.transition(DrawableTransitionOptions.withCrossFade())
.into(viewHolder.imageView); .into(viewHolder.imageView);
viewHolder.imageView.setOnClickListener(v -> { viewHolder.imageView.setOnClickListener(v -> {

View File

@ -15,7 +15,7 @@ public class RecentPhotosLoader extends CursorLoader {
public static Uri BASE_URL = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; public static Uri BASE_URL = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
private static final String[] PROJECTION = new String[] { private static final String[] PROJECTION = new String[] {
MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DATE_TAKEN, MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATE_MODIFIED, MediaStore.Images.ImageColumns.DATE_MODIFIED,
MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.Images.ImageColumns.ORIENTATION,
@ -26,6 +26,8 @@ public class RecentPhotosLoader extends CursorLoader {
MediaStore.Images.ImageColumns.HEIGHT MediaStore.Images.ImageColumns.HEIGHT
}; };
private static final String SELECTION = MediaStore.Images.Media.DATA + " NOT NULL";
private final Context context; private final Context context;
public RecentPhotosLoader(Context context) { public RecentPhotosLoader(Context context) {
@ -37,7 +39,7 @@ public class RecentPhotosLoader extends CursorLoader {
public Cursor loadInBackground() { public Cursor loadInBackground() {
if (Permissions.hasAll(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (Permissions.hasAll(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
return context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, return context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
PROJECTION, null, null, PROJECTION, SELECTION, null,
MediaStore.Images.ImageColumns.DATE_MODIFIED + " DESC"); MediaStore.Images.ImageColumns.DATE_MODIFIED + " DESC");
} else { } else {
return null; return null;

View File

@ -182,9 +182,9 @@ class MediaRepository {
String[] projection; String[] projection;
if (hasOrientation) { if (hasOrientation) {
projection = new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE}; projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
} else { } else {
projection = new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE}; projection = new String[]{Images.Media.DATA, Images.Media.MIME_TYPE, Images.Media.DATE_TAKEN, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
} }
if (Media.ALL_MEDIA_BUCKET_ID.equals(bucketId)) { if (Media.ALL_MEDIA_BUCKET_ID.equals(bucketId)) {
@ -194,7 +194,8 @@ class MediaRepository {
try (Cursor cursor = context.getContentResolver().query(contentUri, projection, selection, selectionArgs, sortBy)) { try (Cursor cursor = context.getContentResolver().query(contentUri, projection, selection, selectionArgs, sortBy)) {
while (cursor != null && cursor.moveToNext()) { while (cursor != null && cursor.moveToNext()) {
Uri uri = Uri.withAppendedPath(contentUri, cursor.getString(cursor.getColumnIndexOrThrow(Images.Media._ID))); String path = cursor.getString(cursor.getColumnIndexOrThrow(projection[0]));
Uri uri = Uri.fromFile(new File(path));
String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE)); String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.DATE_TAKEN)); long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.DATE_TAKEN));
int orientation = hasOrientation ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0; int orientation = hasOrientation ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0;