媒体不会显示在 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;
}