将图像从 Firestore 加载到 RecyclerView 中:图像未显示

Load Images from Firestore into RecyclerView : Images not showing

我是新手,我正在尝试将图像从 Firestore 加载到网格布局回收视图中,Firestore 中的 Toast onSuccess 方法显示 "Success" 消息,但图像没有显示,我不是确定我哪里做错了。我使用了从 Firebase Storage 保存在 Firestore 中的图像 Url。

有人可以帮忙吗?提前谢谢你。

Firestore 结构:

PhotoActivity:

public class PhotoActivity extends AppCompatActivity {

    private static final int PICK_IMAGE_REQUEST = 1;
    private LinearLayout confirmLayout;
    private ImageView pickedImageView;
    private EditText titleEditText, photoDescriptionEditText;
    private ProgressBar progressBar;

    private String title, photoDescription;
    private Date datePhoto;
    private Uri pickedImageUrl;

    private FirebaseFirestore db;
    private FirebaseAuth mAuth;
    private String userId;
    private CollectionReference collectionReference;
    private StorageReference storageReference;
    private FloatingActionButton fab;
    private RecyclerView recyclerView;

    private List<Photo> photoList;
    private PhotoAdapter photoAdapter;
    private ProgressBar circularProgressbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo);

        confirmLayout = (LinearLayout) findViewById(R.id.confirmPhotoUploadLayout);
        pickedImageView = (ImageView) findViewById(R.id.pickedImage);
        titleEditText = (EditText) findViewById(R.id.photoTitle);
        photoDescriptionEditText = (EditText) findViewById(R.id.photoDescription);
        progressBar = (ProgressBar) findViewById(R.id.progressbarPhoto);
        recyclerView = (RecyclerView) findViewById(R.id.recyclerViewPhoto);
        circularProgressbar = (ProgressBar) findViewById(R.id.progress_circularPhoto);

        db = FirebaseFirestore.getInstance();
        mAuth = FirebaseAuth.getInstance();

        userId = mAuth.getCurrentUser().getUid();

        storageReference = FirebaseStorage.getInstance().getReference(userId);
        collectionReference = FirebaseFirestore.getInstance().collection("main").document(userId).collection("photo");

        fab = (FloatingActionButton) findViewById(R.id.fabPhoto);
        circularProgressbar.setVisibility(View.VISIBLE);

        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));

        photoList = new ArrayList<>();
        photoAdapter = new PhotoAdapter(this, photoList);
        recyclerView.setAdapter(photoAdapter);

        showPhotoGrid();

    }

    private void showPhotoGrid() {
        collectionReference
                .orderBy("datePhoto", Query.Direction.DESCENDING)
                .get()
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                assert queryDocumentSnapshots != null;

                if (!queryDocumentSnapshots.isEmpty()){
                    //if contains photos
                    circularProgressbar.setVisibility(View.GONE);
                    Toast.makeText(PhotoActivity.this, "Success", Toast.LENGTH_SHORT).show();
                    List<DocumentSnapshot> list = queryDocumentSnapshots.getDocuments();
                    for (DocumentSnapshot documentSnapshot : list){
                        Photo photo = documentSnapshot.toObject(Photo.class);
                        assert photo != null;
                        photo.setID(documentSnapshot.getId());
                        photoList.add(photo);
                    }
                    photoAdapter.notifyDataSetChanged();

                } else {
                    //show no photos
                    circularProgressbar.setVisibility(View.GONE);
                    Toast.makeText(PhotoActivity.this, "No photos added yet", Toast.LENGTH_SHORT).show();
                }
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                circularProgressbar.setVisibility(View.GONE);
                Toast.makeText(PhotoActivity.this, "Error in showing images: " + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }

    public void addPhoto(View view) {
        showImageChooser();
    }

    private void showImageChooser() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, PICK_IMAGE_REQUEST);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            pickedImageUrl = data.getData();

            Picasso.with(this).load(pickedImageUrl).into(pickedImageView);
            confirmLayout.setVisibility(View.VISIBLE);
            fab.setVisibility(View.GONE);
            photoAdapter.notifyDataSetChanged();
        }
    }

    public void hideConfirmLayout(View view) {
        pickedImageView.setImageDrawable(null);
        confirmLayout.setVisibility(View.GONE);
        fab.setVisibility(View.VISIBLE);
    }

    public void uploadPhoto(View view) {
        title = titleEditText.getText().toString().trim();
        photoDescription = photoDescriptionEditText.getText().toString().trim();

        if (title.isEmpty()) {
            titleEditText.setError("Please give a title");
        } else if (photoDescription.isEmpty()) {
            photoDescription = "No description for this photo";
        }

        if (pickedImageUrl != null) {
            if (title.isEmpty()) {
                titleEditText.setError("Required");
            } else {
                StorageReference imageReference = storageReference.child(title + "." + getFileExtension(pickedImageUrl));
                imageReference.putFile(pickedImageUrl).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                progressBar.setProgress(0);
                            }
                        }, 1000);

                        String thatImageUrl = taskSnapshot.getStorage().getDownloadUrl().toString();

                        Photo photo = new Photo(userId, title, photoDescription, thatImageUrl, datePhoto);

                        collectionReference.add(photo).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                            @Override
                            public void onSuccess(DocumentReference documentReference) {
                                Toast.makeText(PhotoActivity.this, "Saved to gallery", Toast.LENGTH_SHORT).show();
                                confirmLayout.setVisibility(View.GONE);
                                pickedImageView.setImageDrawable(null);
                                titleEditText.setText(null);
                                photoDescriptionEditText.setText(null);
                                fab.setVisibility(View.VISIBLE);
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(PhotoActivity.this, "Firestore error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                            }
                        });

                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(PhotoActivity.this, "Storage error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                    }
                }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onProgress(@NonNull UploadTask.TaskSnapshot taskSnapshot) {
                        progressBar.setVisibility(View.VISIBLE);
                        double progress = 100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount();
                        progressBar.setProgress((int) progress);
                    }
                });
            }
        } else {
            Toast.makeText(this, "No photo is selected", Toast.LENGTH_LONG).show();
        }
    }

    private String getFileExtension(Uri uri) {
        //get photo type: jpeg, png
        ContentResolver contentResolver = getContentResolver();
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri));
    }
}

照片对象class

public class Photo implements Serializable {

    private String ID;

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    private String photoTitle;
    private String photoDescription;
    private String photoUrl;

    @ServerTimestamp
    private Date datePhoto;

    public Date getDatePhoto() {
        return datePhoto;
    }

    public void setDatePhoto(Date datePhoto) {
        this.datePhoto = datePhoto;
    }

    public Photo() {
    }

    public Photo(String ID, String photoTitle, String photoDescription, String photoUrl, Date datePhoto) {
        this.ID = ID;
        this.photoTitle = photoTitle;
        this.photoDescription = photoDescription;
        this.photoUrl = photoUrl;
        this.datePhoto = datePhoto;
    }

    public String getPhotoTitle() {
        return photoTitle;
    }

    public void setPhotoTitle(String photoTitle) {
        this.photoTitle = photoTitle;
    }

    public String getPhotoDescription() {
        return photoDescription;
    }

    public void setPhotoDescription(String photoDescription) {
        this.photoDescription = photoDescription;
    }

    public String getPhotoUrl() {
        return photoUrl;
    }

    public void setPhotoUrl(String photoUrl) {
        this.photoUrl = photoUrl;
    }
}

照片适配器:

public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> {

    private Context context;
    private List<Photo> photoList;

    public PhotoAdapter(Context context, List<Photo> photoList) {
        this.context = context;
        this.photoList = photoList;
    }

    @NonNull
    @Override
    public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new PhotoViewHolder(LayoutInflater.from(context).inflate(R.layout.single_photo_layout, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull PhotoViewHolder holder, int position) {
        Photo photo = photoList.get(position);

        if (photo.getPhotoUrl() != null && !photo.getPhotoUrl().isEmpty()){
            Picasso.with(context).load(photo.getPhotoUrl()).into(holder.showImage);
        }
    }

    @Override
    public int getItemCount() {
        return photoList.size();
    }

    public class PhotoViewHolder extends RecyclerView.ViewHolder {

        ImageView showImage;

        public PhotoViewHolder(View inflate) {
            super(inflate);

            showImage = inflate.findViewById(R.id.singlePhotoImageView);

        }
    }
}

xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="@drawable/gradient0"
    tools:context=".PhotoActivity">

    <TextView
        android:id="@+id/titlePhoto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fontFamily="@font/quicksand_bold"
        android:gravity="center"
        android:padding="@dimen/_20sdp"
        android:text="PHOTO GALLERY"
        android:textColor="@color/white"
        android:textSize="@dimen/_14sdp"
        android:layout_alignParentTop="true"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewPhoto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/titlePhoto"/>

    <LinearLayout
        android:id="@+id/confirmPhotoUploadLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/white_rounded"
        android:gravity="center"
        android:orientation="vertical"
        android:paddingTop="@dimen/_20sdp"
        android:paddingBottom="@dimen/_10sdp"
        android:visibility="gone">

        <EditText
            android:id="@+id/photoTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/_16sdp"
            android:layout_marginTop="@dimen/_16sdp"
            android:background="@null"
            android:hint="Photo title" />

        <EditText
            android:id="@+id/photoDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_16sdp"
            android:layout_marginEnd="@dimen/_16sdp"
            android:layout_marginBottom="@dimen/_16sdp"
            android:background="@null"
            android:hint="Write something about this photo..." />

        <ProgressBar
            android:id="@+id/progressbarPhoto"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="invisible"
            tools:visibility="visible" />

        <ImageView
            android:id="@+id/pickedImage"
            android:layout_width="match_parent"
            android:layout_height="@dimen/_300sdp"
            android:layout_marginBottom="@dimen/_14sdp"
            android:scaleType="centerCrop" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/_10sdp"
            android:gravity="center">

            <Button
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:background="@drawable/red_rounded_bg"
                android:onClick="hideConfirmLayout"
                android:text="cancel"
                android:textColor="@color/white" />

            <Button
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/_10sdp"
                android:background="@drawable/rounded_button"
                android:onClick="uploadPhoto"
                android:text="save to gallery"
                android:textColor="@color/white" />

        </LinearLayout>

    </LinearLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabPhoto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="@dimen/_20sdp"
        android:clickable="true"
        android:focusable="true"
        android:onClick="addPhoto"
        android:src="@drawable/ic_add" />

    <ProgressBar
        android:id="@+id/progress_circularPhoto"
        android:layout_width="@dimen/_100sdp"
        android:layout_height="@dimen/_100sdp"
        android:layout_centerInParent="true"
        android:visibility="gone"
        tools:visibility="visible"/>

</RelativeLayout>

单张照片布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/singlePhotoImageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

您的网址似乎有误。

taskSnapshot.getDownloadUrl returns Task,不是 Uri 或 Url 字符串。您需要添加 OnSuccessListener 回调才能下载 Uri

尝试通过这种方式保存 url:

taskSnapshot.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                    @Override
                    public void onSuccess(Uri uri) {
                        Uri downloadUrl = uri;
                        String url = downloadUrl.toString()
                        // save this url to Firestore
                    }

Official documentation

中检查这个

我找到了基于此的解决方案 post-->

taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                    //get the uri and carry out action here
                                    //uri = correct filepath
}

现在图片显示在回收站视图中,耶!感谢您的帮助!