【问题标题】:Load Images from Firestore into RecyclerView : Images not showing将 Firestore 中的图像加载到 RecyclerView 中:图像未显示
【发布时间】:2020-05-12 05:13:30
【问题描述】:

我是新手,我正在尝试将 Firestore 中的图像加载到网格布局 recyclerview 中,Firestore 中的 Toast onSuccess 方法显示“成功”消息,但图像没有显示,我不确定我在哪里错误的。我使用了 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));
    }
}

照片对象类

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>

【问题讨论】:

  • 请发布您的数据库结构
  • 检查您的照片网址。您是如何获取它们并将它们保存到 Firestore 的?
  • @MaratZangiev 是的,我使用了这段代码: String thatImageUrl = taskSnapshot.getStorage().getDownloadUrl().toString();照片 photo = new Photo(userId, title, photoDescription, thatImageUrl, datePhoto); collectionReference.add(photo).addOnSuccessListener
  • @Ashish 刚刚添加了firestore的结构
  • getDownloadUrl() 已弃用。

标签: android google-cloud-firestore google-cloud-storage picasso


【解决方案1】:

我根据这篇帖子找到了解决方案--> How to use getdownloadurl in recent versions?

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

现在图像显示在 recyclerview 中,耶!感谢您的帮助!

【讨论】:

    【解决方案2】:

    您的网址似乎有误。

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

    尝试通过这种方式保存网址:

    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查看这个

    【讨论】:

    • 您好,如何获取文件路径?
    • String url 是你的文件路径
    • 谢谢,但我之前尝试过,并且在 taskSnapshot 之后键入时不推荐使用 getDownloadUrl() :(
    • 不,你这样做是这样的:String thatImageUrl = taskSnapshot.getStorage().getDownloadUrl().toString(); 这是错误的。粘贴答案中的代码。不要调用 taskSnaphot 的getStorage 方法。再次仔细检查答案
    • 我使用了上面的代码,但它显示无法解析“getdownloadUrl()”,感谢您的帮助,我找到了解决方案,在代码后面添加 addOnSuccesslistener 以获取 URL :)
    猜你喜欢
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 2021-02-28
    • 2019-10-06
    • 2017-11-18
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多