媒体不会显示在 recyclerview android studio 上
Media wont display on recyclerview android studio
我现在遇到了这个问题,我想在 android 工作室的 recyclerview
中将我所有的图片从画廊显示到缩略图视图。但问题是;没有图像显示,我寻找可能的解决方案但没有解决我的问题。
主要activity:
package com.example.swiftpinx.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.CursorLoader;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.swiftpinx.Adapters.GalleryImageAdapter;
import com.example.swiftpinx.R;
public class UploadProfilePhotoActivity extends AppCompatActivity implements View.OnClickListener,
LoaderManager.LoaderCallbacks<Cursor> {
/*
Set up's
*/
private static final String TAG = "UploadProfilePhotoActiv";
private final static int READ_EXTERNAL_STORAGE_CODE = 0;
private final static int MEDIASTORE_LOADER_ID = 0;
private GalleryImageAdapter gallery;
Intent intent;
/*
Pallete
*/
RecyclerView rvGalleryImages;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload_profile_photo);
rvGalleryImages = (RecyclerView) findViewById(R.id.rvGalleryImages);
rvGalleryImages.setLayoutManager(new GridLayoutManager(this, 3));
gallery = new GalleryImageAdapter(this);
rvGalleryImages.setAdapter(gallery);
checkExternalReadStoragePermission();
}
@Override
public void onClick(View v) {
}
@NonNull
@Override
public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE
};
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE + " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
return new CursorLoader(
this,
MediaStore.Files.getContentUri("external"),
projection,
selection,
null,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
);
}
@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
gallery.changeCursor(data);
}
@Override
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
gallery.changeCursor(null);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode) {
case READ_EXTERNAL_STORAGE_CODE:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Call cursor loader
Log.i(TAG, "onRequestPermissionsResult: permission granted.");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void checkExternalReadStoragePermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// Start cursor loader
Log.i(TAG, "checkExternalReadStoragePermission: Granted");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
// put reasons why we need to access storage
Toast.makeText(this, "App needs to view thumbnails.", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, READ_EXTERNAL_STORAGE_CODE);
}
} else {
// Start cursor loader
Log.i(TAG, "checkExternalReadStoragePermission: Granted");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
}
}
}
RecyclerView class:
package com.example.swiftpinx.Adapters;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.swiftpinx.R;
public class GalleryImageAdapter extends RecyclerView.Adapter<GalleryImageAdapter.ViewHolder> {
private Cursor mediaCursor;
private Context context;
public GalleryImageAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_gallery_upload_images, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Bitmap bitmap = getBitmapFromMediaStorage(position);
if(bitmap != null) {
holder.ivImage.setImageBitmap(bitmap);
}
}
@Override
public int getItemCount() {
return (mediaCursor == null) ? 0 : mediaCursor.getCount();
}
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == null) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
public void changeCursor(Cursor cursor) {
Cursor oldCursor = swapCursor(cursor);
if(oldCursor != null) {
oldCursor.close();
}
}
private Bitmap getBitmapFromMediaStorage(int position) {
int idIndex = mediaCursor.getColumnIndex(MediaStore.Files.FileColumns._ID);
int mediaTypeIndex = mediaCursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE);
mediaCursor.moveToPosition(position);
switch(mediaCursor.getInt(mediaTypeIndex)) {
case MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE:
return MediaStore.Images.Thumbnails.getThumbnail(
this.context.getContentResolver(),
mediaCursor.getLong(idIndex),
MediaStore.Images.Thumbnails.MICRO_KIND,
null
);
case MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO:
return MediaStore.Video.Thumbnails.getThumbnail(
this.context.getContentResolver(),
mediaCursor.getLong(idIndex),
MediaStore.Video.Thumbnails.MICRO_KIND,
null
);
default:
return null;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView ivImage;
public ViewHolder(@NonNull View itemView) {
super(itemView);
ivImage = (ImageView) itemView.findViewById(R.id.ivImage);
}
}
}
布局图像处理程序xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/ivImage"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
布局recyclerview xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context=".Activity.UploadProfilePhotoActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="20dp"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:elevation="0dp"
app:cardBackgroundColor="@color/colorAccent"
android:layout_gravity="center_horizontal"
app:cardCornerRadius="100dp">
<ImageView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@mipmap/ic_man_foreground"
tools:ignore="VectorDrawableCompat"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/errorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_gravity="center_horizontal"
android:textColor="@color/colorDanger"
android:layout_marginTop="5dp"
android:layout_marginBottom="15dp"/>
<Button
android:id="@+id/btnUpload"
android:layout_width="250dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:background="@color/colorPrimaryDark"
android:textColor="@color/colorAccent"
android:text="upload" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvGalleryImages"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
所以这里的解决方案是 swapCursor
方法我设置条件如果 mediaCursor 为 null 然后我 return 它为 null,这是错误的。
所以从这个:
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == null) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
我改成这样:
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == cursor) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
我现在遇到了这个问题,我想在 android 工作室的 recyclerview
中将我所有的图片从画廊显示到缩略图视图。但问题是;没有图像显示,我寻找可能的解决方案但没有解决我的问题。
主要activity:
package com.example.swiftpinx.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.CursorLoader;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.swiftpinx.Adapters.GalleryImageAdapter;
import com.example.swiftpinx.R;
public class UploadProfilePhotoActivity extends AppCompatActivity implements View.OnClickListener,
LoaderManager.LoaderCallbacks<Cursor> {
/*
Set up's
*/
private static final String TAG = "UploadProfilePhotoActiv";
private final static int READ_EXTERNAL_STORAGE_CODE = 0;
private final static int MEDIASTORE_LOADER_ID = 0;
private GalleryImageAdapter gallery;
Intent intent;
/*
Pallete
*/
RecyclerView rvGalleryImages;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload_profile_photo);
rvGalleryImages = (RecyclerView) findViewById(R.id.rvGalleryImages);
rvGalleryImages.setLayoutManager(new GridLayoutManager(this, 3));
gallery = new GalleryImageAdapter(this);
rvGalleryImages.setAdapter(gallery);
checkExternalReadStoragePermission();
}
@Override
public void onClick(View v) {
}
@NonNull
@Override
public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE
};
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE + " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
return new CursorLoader(
this,
MediaStore.Files.getContentUri("external"),
projection,
selection,
null,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
);
}
@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
gallery.changeCursor(data);
}
@Override
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
gallery.changeCursor(null);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode) {
case READ_EXTERNAL_STORAGE_CODE:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Call cursor loader
Log.i(TAG, "onRequestPermissionsResult: permission granted.");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void checkExternalReadStoragePermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// Start cursor loader
Log.i(TAG, "checkExternalReadStoragePermission: Granted");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
// put reasons why we need to access storage
Toast.makeText(this, "App needs to view thumbnails.", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, READ_EXTERNAL_STORAGE_CODE);
}
} else {
// Start cursor loader
Log.i(TAG, "checkExternalReadStoragePermission: Granted");
LoaderManager.getInstance(this).initLoader(MEDIASTORE_LOADER_ID, null, this);
}
}
}
RecyclerView class:
package com.example.swiftpinx.Adapters;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.swiftpinx.R;
public class GalleryImageAdapter extends RecyclerView.Adapter<GalleryImageAdapter.ViewHolder> {
private Cursor mediaCursor;
private Context context;
public GalleryImageAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_gallery_upload_images, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Bitmap bitmap = getBitmapFromMediaStorage(position);
if(bitmap != null) {
holder.ivImage.setImageBitmap(bitmap);
}
}
@Override
public int getItemCount() {
return (mediaCursor == null) ? 0 : mediaCursor.getCount();
}
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == null) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
public void changeCursor(Cursor cursor) {
Cursor oldCursor = swapCursor(cursor);
if(oldCursor != null) {
oldCursor.close();
}
}
private Bitmap getBitmapFromMediaStorage(int position) {
int idIndex = mediaCursor.getColumnIndex(MediaStore.Files.FileColumns._ID);
int mediaTypeIndex = mediaCursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE);
mediaCursor.moveToPosition(position);
switch(mediaCursor.getInt(mediaTypeIndex)) {
case MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE:
return MediaStore.Images.Thumbnails.getThumbnail(
this.context.getContentResolver(),
mediaCursor.getLong(idIndex),
MediaStore.Images.Thumbnails.MICRO_KIND,
null
);
case MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO:
return MediaStore.Video.Thumbnails.getThumbnail(
this.context.getContentResolver(),
mediaCursor.getLong(idIndex),
MediaStore.Video.Thumbnails.MICRO_KIND,
null
);
default:
return null;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView ivImage;
public ViewHolder(@NonNull View itemView) {
super(itemView);
ivImage = (ImageView) itemView.findViewById(R.id.ivImage);
}
}
}
布局图像处理程序xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/ivImage"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
布局recyclerview xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context=".Activity.UploadProfilePhotoActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="20dp"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:elevation="0dp"
app:cardBackgroundColor="@color/colorAccent"
android:layout_gravity="center_horizontal"
app:cardCornerRadius="100dp">
<ImageView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@mipmap/ic_man_foreground"
tools:ignore="VectorDrawableCompat"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/errorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_gravity="center_horizontal"
android:textColor="@color/colorDanger"
android:layout_marginTop="5dp"
android:layout_marginBottom="15dp"/>
<Button
android:id="@+id/btnUpload"
android:layout_width="250dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:background="@color/colorPrimaryDark"
android:textColor="@color/colorAccent"
android:text="upload" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvGalleryImages"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
所以这里的解决方案是 swapCursor
方法我设置条件如果 mediaCursor 为 null 然后我 return 它为 null,这是错误的。
所以从这个:
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == null) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}
我改成这样:
private Cursor swapCursor(Cursor cursor) {
if(mediaCursor == cursor) {
return null;
}
Cursor oldCursor = mediaCursor;
this.mediaCursor = cursor;
if(cursor != null) {
this.notifyDataSetChanged();
}
return oldCursor;
}