Firebase实时数据库在Recyclerview中未显示图像。

huangapple go评论77阅读模式
英文:

Firebase Realtime Database not displaying images in Recyclerview

问题

public class TopActivity extends AppCompatActivity {
    // ... (rest of the code remains the same)
    
    private void storeLink(ArrayList<String> urlStrings) {
        databaseReference = FirebaseDatabase.getInstance().getReference("TopsFolder");

        for (int i = 0; i < urlStrings.size(); i++) {
            String url = urlStrings.get(i);
            DatabaseReference pushRef = databaseReference.push();
            pushRef.child("top").setValue(url);
        }

        progressDialog.dismiss();
        Toast.makeText(TopActivity.this, "Successfully Uploaded", Toast.LENGTH_SHORT).show();

        ImageList.clear();
    }
    
    // ... (rest of the code remains the same)
    
    private void GetDataFromFirebase() {
        dbreference = databaseReference;
        ValueEventListener eventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                topslist.clear();  // Clear the list before adding new data
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    String topUrl = ds.child("top").getValue(String.class);
                    topslist.add(new Tops(topUrl));
                }

                topsAdapter = new TopsAdapter(getApplicationContext(), topslist);
                recyclerView.setAdapter(topsAdapter);
                topsAdapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                // Handle onCancelled if needed
            }
        };
        dbreference.addListenerForSingleValueEvent(eventListener);
    }
}
public class TopsAdapter extends RecyclerView.Adapter<TopsAdapter.ViewHolder> {
    // ... (rest of the code remains the same)
    
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Glide.with(mContext)
                .load(topslist.get(position).getTop())
                .into(holder.ivTopGallery);
    }

    // ... (rest of the code remains the same)
}

These code snippets reflect the changes required to adapt your code to the data structure you've described.

英文:

I am new at Android and I am making an app that displays the user's uploaded images of clothes. I can upload the pictures perfectly but for some reason I cannot display the images from firebase realtime database into the RecyclerView. I have been searching for a solution for weeks.

Please help me out. Thank you so much for your time.

TopActivity.java

public class TopActivity extends AppCompatActivity {
FloatingActionButton fab;
//Uploading Images to Firebase
private static final int PICK_IMAGE = 1;
private Uri ImageUri;
ArrayList ImageList = new ArrayList();
private int upload_count = 0;
private ProgressDialog progressDialog;
ArrayList urlStrings;
List&lt;String&gt; imagesEncodedList;
Uri uri,mImageUri;
String imageEncoded;
ArrayList&lt;Uri&gt; mArrayUri = new ArrayList&lt;&gt;();
RecyclerView recyclerView;
DatabaseReference databaseReference,dbreference;
private ArrayList&lt;Tops&gt; topslist;
private TopsAdapter topsAdapter;
private Context mContext;
StorageReference ImageFolder,Folder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top);
fab = findViewById(R.id.fab);
recyclerView=findViewById(R.id.recyclerView);
GridLayoutManager gridLayoutManager=new GridLayoutManager(TopActivity.this,2);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setHasFixedSize(true);
topslist = new ArrayList&lt;&gt;();
GetDataFromFirebase();
progressDialog = new ProgressDialog(TopActivity.this);
progressDialog.setMessage(&quot;Uploading Images Please Wait&quot;);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(&quot;image/*&quot;);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(intent,PICK_IMAGE);
}
});
}
private void uploadImage(){
urlStrings = new ArrayList&lt;&gt;();
progressDialog.show();
ImageFolder = FirebaseStorage.getInstance().getReference().child(&quot;Tops&quot;);
for (upload_count = 0; upload_count &lt; mArrayUri.size(); upload_count++) {
Uri IndividualImage = (Uri) mArrayUri.get(upload_count);
final StorageReference ImageName = ImageFolder.child(&quot;Top_&quot; + IndividualImage.getLastPathSegment());
ImageName.putFile(IndividualImage).addOnSuccessListener(
new OnSuccessListener&lt;UploadTask.TaskSnapshot&gt;() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
ImageName.getDownloadUrl().addOnSuccessListener(
new OnSuccessListener&lt;Uri&gt;() {
@Override
public void onSuccess(Uri uri) {
urlStrings.add(String.valueOf(uri));
if (urlStrings.size() == mArrayUri.size()) {
storeLink(urlStrings);
}
}
}
);
}
}
);
}
}
private void storeLink(ArrayList&lt;String&gt; urlStrings) {
HashMap&lt;String,String &gt; hashMap = new HashMap&lt;&gt;();
for (int i = 0; i &lt;urlStrings.size() ; i++) {
hashMap.put(&quot;Top &quot;+i, urlStrings.get(i));
}
databaseReference = FirebaseDatabase.getInstance().getReference(&quot;TopsFolder&quot;);
databaseReference.push().setValue(hashMap)
.addOnCompleteListener(
new OnCompleteListener&lt;Void&gt;() {
@Override
public void onComplete(@NonNull Task&lt;Void&gt; task) {
if (task.isSuccessful()) {
Toast.makeText(TopActivity.this, &quot;Successfully Uploaded&quot;, Toast.LENGTH_SHORT).show();
}
}
}
).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(TopActivity.this, &quot;&quot; + e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
progressDialog.dismiss();
ImageList.clear();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
try {
if (requestCode == PICK_IMAGE &amp;&amp; resultCode == RESULT_OK
&amp;&amp; null != data) {
imagesEncodedList = new ArrayList&lt;String&gt;();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
if (data.getData() != null) {
mImageUri = data.getData();
// Get the cursor
Cursor cursor = getContentResolver().query(mImageUri,
filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageEncoded = cursor.getString(columnIndex);
cursor.close();
uploadImage();
} else {
if (data.getClipData() != null) {
ClipData mClipData = data.getClipData();
for (int i = 0; i &lt; mClipData.getItemCount(); i++) {
ClipData.Item item = mClipData.getItemAt(i);
uri = item.getUri();
mArrayUri.add(uri);
// Get the cursor
Cursor cursor = getContentResolver().query(uri, filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageEncoded = cursor.getString(columnIndex);
imagesEncodedList.add(imageEncoded);
cursor.close();
}
Log.v(&quot;LOG_TAG&quot;, &quot;Selected Images&quot; + mArrayUri.size());
uploadImage();
}
}
} else {
Toast.makeText(this, &quot;You haven&#39;t picked Image&quot;,
Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, &quot;Something went wrong&quot;, Toast.LENGTH_LONG)
.show();
}
super.onActivityResult(requestCode, resultCode, data);
}
private void GetDataFromFirebase(){
//Query query=databaseReference.child(&quot;TopsFolder/Tops&quot;);
//query.addValueEventListener(new ValueEventListener() {
databaseReference = FirebaseDatabase.getInstance().getReference();
dbreference=databaseReference.child(&quot;TopsFolder&quot;);
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange( DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
Tops tops=ds.child(&quot;TopsFolder&quot;).getValue(Tops.class);
topslist.add(tops);
}
topsAdapter= new TopsAdapter(getApplicationContext(),topslist);
recyclerView.setAdapter(topsAdapter);
topsAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
dbreference.addListenerForSingleValueEvent(eventListener);
}
}

TopsAdapter.java

public class TopsAdapter extends RecyclerView.Adapter&lt;TopsAdapter.ViewHolder&gt; {
private  static  final String Tag=&quot;RecyclerView&quot;;
private Context mContext;
private ArrayList&lt;Tops&gt; topslist;
public TopsAdapter(Context mContext, ArrayList&lt;Tops&gt; topslist) {
this.mContext = mContext;
this.topslist = topslist;
}
@NonNull
@Override
public TopsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext())
.inflate(R.layout.top_rv_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Glide.with(mContext)
.load(topslist.get(position).getTop())
.into(holder.ivTopGallery);
}
@Override
public int getItemCount() {
return topslist.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView ivTopGallery;
public ViewHolder(@NonNull View itemView) {
super(itemView);
ivTopGallery=itemView.findViewById(R.id.ivTopGallery);
}
}
}

Tops.java

public class Tops {
//Model Class
public String top;
//Constructors
public Tops(){}
public Tops(String top) {
this.top = top;
}
public String getTop() {
return top;
}
public void setTop(String top) {
this.top = top;
}
}

top_rv_item.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:orientation=&quot;vertical&quot;&gt;
&lt;ImageView
android:layout_height=&quot;150dp&quot;
android:layout_width=&quot;150dp&quot;
android:padding=&quot;10dp&quot;
android:id=&quot;@+id/ivTopGallery&quot;
android:scaleType=&quot;fitXY&quot;
/&gt;
&lt;/LinearLayout&gt;

Here's my database structure.

Firebase实时数据库在Recyclerview中未显示图像。

Update
so I changed my code to fit the data structure

Firebase-root
|
--- TopsFolder
|
--- pushedId
|     |
|     --- top: &quot;https://...&quot;
|
--- pushedId
|
--- top: &quot;https://...&quot;

Here is the change I made in my TopsActivity.java

private void storeLink(ArrayList&lt;String&gt; urlStrings) {
HashMap&lt;String, String&gt; hashMap = new HashMap&lt;&gt;();
databaseReference = FirebaseDatabase.getInstance().getReference(&quot;TopsFolder&quot;);
for (int i = 1; i &lt;urlStrings.size() ; i++) {
hashMap.put(&quot;Top &quot;+i, urlStrings.get(i));
databaseReference.push().setValue(hashMap);
}
progressDialog.dismiss();
Toast.makeText(TopActivity.this, &quot;Successfully Uploaded&quot;, Toast.LENGTH_SHORT).show();
ImageList.clear();
}

put now I am getting this as my data structure. What do I do to get it in the format mentioned above?
Firebase实时数据库在Recyclerview中未显示图像。

答案1

得分: 1

你的数据库实际上在 TopsFolder 节点下存储了一个 String 列表,你需要将它们作为字符串列表获取。因此,我建议将你在 GetDataFromFirebase 函数内的 onDataChange 实现更改如下。

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot ds : dataSnapshot.getChildren()) {
        // 你应该将元素视为字符串数组。
        String[] tops = ds.child("TopsFolder").getValue(String[].class);
        if (topList != null) topList.clear(); // 如果列表中已经有内容,清空列表
        topList = Arrays.asList(tops); // 将从 Firebase 数据库检索到的数组项分配给列表。
    }

    topsAdapter = new TopsAdapter(getApplicationContext(), topList);
    recyclerView.setAdapter(topsAdapter);
    topsAdapter.notifyDataSetChanged();
}

这应该能解决你的问题。

英文:

Your database actually stores a list of String under TopsFolder node and you need to get those as a list of strings. Hence I would recommend changing your onDataChange implementation inside GetDataFromFirebase function as follows.

@Override
public void onDataChange( DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
// You should have the elements as an array of string. 
Tops[] tops = ds.child(&quot;TopsFolder&quot;).getValue(Tops[].class);
if (topList != null) toplist.clear(); // Clear the list if there&#39;s anything already in the list 
topslist = Arrays.asList(tops);  // Assign the items to the list from the array that you retrieved from firebase database.
}
topsAdapter= new TopsAdapter(getApplicationContext(), topslist);
recyclerView.setAdapter(topsAdapter);
topsAdapter.notifyDataSetChanged();
}

That should solve your problem.

答案2

得分: 0

你可以使用 Picasso 图库 implementation 'com.squareup.picasso:picasso:2.5.2'
这对我很有效。

public static void setUrlImageInView(Context context, String url, ImageView view) {
    // (可选)使用 Picasso 下载并显示图像
    Picasso.with(context).load(url).into(view);
}

另一个需要考虑的事情是,你再次从同一个子项获取数据。在你的示例中,你必须使用文档的 Id:

Tops tops = ds.child("-MIPf9A2H_.....").getValue(Tops.class);
topslist.add(tops);
英文:

you can use Picasso Library implementation &#39;com.squareup.picasso:picasso:2.5.2&#39;
this works for me.

public static void setUrlImageInView(Context context, String url, ImageView view) {
// (optional) use Picasso to download and show to image
Picasso.with(context).load(url).into(view);
}

Another thing to consider is that you are getting data from the same child again. You must use Id of document in your example case

Tops tops=ds.child(&quot;-MIPf9A2H_.....&quot;).getValue(Tops.class);
topslist.add(tops);

答案3

得分: 0

无法将存在于TopsFolder节点下的对象映射为Tops类型的对象,因为这些对象实际上都不代表Tops类型的对象。但是,如果您需要将每个对象映射为Tops对象,您需要重构您的模式,如下所示:

Firebase根节点
|
--- TopsFolder
|
--- pushedId
|     |
|     --- top: "https://..."
|
--- pushedId
|
--- top: "https://..."

这样,TopsFolder下的每个对象都代表一个Tops对象。可以看到,属性的名称是“top”,就像您的Tops类中一样,而“value”则是实际的URL。所需的代码应该如下所示:

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot ds : dataSnapshot.getChildren()) {
        String url = ds.getValue(String.class);
        if (topList != null) topList.clear(); // 如果列表中已有内容,则清空列表
        topList.add(url);
    }
    topsAdapter = new TopsAdapter(getApplicationContext(), topList);
    recyclerView.setAdapter(topsAdapter);
    topsAdapter.notifyDataSetChanged();
}

编辑:

Tops tops = new Tops("https://...");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference topFolderRef = rootRef.child("TopsFolder");
topFolderRef.push().setValue(tops);

请还记得在您的Tops类中将top属性设置为私有。

英文:

You cannot map the objects that exist under the TopsFolder node into objects of type Tops because none of those objects actually represents an object of type Tops. However, if you need to map each object into a Tops object, you need to restructure your schema like so:

Firebase-root
|
--- TopsFolder
|
--- pushedId
|     |
|     --- top: &quot;https://...&quot;
|
--- pushedId
|
--- top: &quot;https://...&quot;

In this way, each object under TopsFolder represents a Tops object. See, the name of the property is "top", as in your Tops class, and the "value" is the actual URL. The code required should look like this:

@Override
public void onDataChange( DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String url = ds.getValue(String.class);
if (topList != null) toplist.clear(); // Clear the list if there&#39;s anything already in the list 
topslist.add(url);
}
topsAdapter= new TopsAdapter(getApplicationContext(), topslist);
recyclerView.setAdapter(topsAdapter);
topsAdapter.notifyDataSetChanged();
}

Edit:

Tops tops = new Tops(&quot;https://...&quot;);
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference topFolderRef = rootRef.child(&quot;TopsFolder&quot;);
topFolderRef.push().setValue(tops);

Please also don't forget to make the top property private in your Tops class.

huangapple
  • 本文由 发表于 2020年9月30日 03:35:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64126459.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定