英文:
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<String> imagesEncodedList;
Uri uri,mImageUri;
String imageEncoded;
ArrayList<Uri> mArrayUri = new ArrayList<>();
RecyclerView recyclerView;
DatabaseReference databaseReference,dbreference;
private ArrayList<Tops> 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<>();
GetDataFromFirebase();
progressDialog = new ProgressDialog(TopActivity.this);
progressDialog.setMessage("Uploading Images Please Wait");
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(intent,PICK_IMAGE);
}
});
}
private void uploadImage(){
urlStrings = new ArrayList<>();
progressDialog.show();
ImageFolder = FirebaseStorage.getInstance().getReference().child("Tops");
for (upload_count = 0; upload_count < mArrayUri.size(); upload_count++) {
Uri IndividualImage = (Uri) mArrayUri.get(upload_count);
final StorageReference ImageName = ImageFolder.child("Top_" + IndividualImage.getLastPathSegment());
ImageName.putFile(IndividualImage).addOnSuccessListener(
new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
ImageName.getDownloadUrl().addOnSuccessListener(
new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
urlStrings.add(String.valueOf(uri));
if (urlStrings.size() == mArrayUri.size()) {
storeLink(urlStrings);
}
}
}
);
}
}
);
}
}
private void storeLink(ArrayList<String> urlStrings) {
HashMap<String,String > hashMap = new HashMap<>();
for (int i = 0; i <urlStrings.size() ; i++) {
hashMap.put("Top "+i, urlStrings.get(i));
}
databaseReference = FirebaseDatabase.getInstance().getReference("TopsFolder");
databaseReference.push().setValue(hashMap)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(TopActivity.this, "Successfully Uploaded", Toast.LENGTH_SHORT).show();
}
}
}
).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(TopActivity.this, "" + 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 && resultCode == RESULT_OK
&& null != data) {
imagesEncodedList = new ArrayList<String>();
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 < 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("LOG_TAG", "Selected Images" + mArrayUri.size());
uploadImage();
}
}
} else {
Toast.makeText(this, "You haven't picked Image",
Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
.show();
}
super.onActivityResult(requestCode, resultCode, data);
}
private void GetDataFromFirebase(){
//Query query=databaseReference.child("TopsFolder/Tops");
//query.addValueEventListener(new ValueEventListener() {
databaseReference = FirebaseDatabase.getInstance().getReference();
dbreference=databaseReference.child("TopsFolder");
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange( DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
Tops tops=ds.child("TopsFolder").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<TopsAdapter.ViewHolder> {
private static final String Tag="RecyclerView";
private Context mContext;
private ArrayList<Tops> topslist;
public TopsAdapter(Context mContext, ArrayList<Tops> 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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_height="150dp"
android:layout_width="150dp"
android:padding="10dp"
android:id="@+id/ivTopGallery"
android:scaleType="fitXY"
/>
</LinearLayout>
Here's my database structure.
Update
so I changed my code to fit the data structure
Firebase-root
|
--- TopsFolder
|
--- pushedId
| |
| --- top: "https://..."
|
--- pushedId
|
--- top: "https://..."
Here is the change I made in my TopsActivity.java
private void storeLink(ArrayList<String> urlStrings) {
HashMap<String, String> hashMap = new HashMap<>();
databaseReference = FirebaseDatabase.getInstance().getReference("TopsFolder");
for (int i = 1; i <urlStrings.size() ; i++) {
hashMap.put("Top "+i, urlStrings.get(i));
databaseReference.push().setValue(hashMap);
}
progressDialog.dismiss();
Toast.makeText(TopActivity.this, "Successfully Uploaded", 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?
答案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("TopsFolder").getValue(Tops[].class);
if (topList != null) toplist.clear(); // Clear the list if there'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 'com.squareup.picasso:picasso:2.5.2'
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("-MIPf9A2H_.....").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: "https://..."
|
--- pushedId
|
--- top: "https://..."
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's anything already in the list
topslist.add(url);
}
topsAdapter= new TopsAdapter(getApplicationContext(), topslist);
recyclerView.setAdapter(topsAdapter);
topsAdapter.notifyDataSetChanged();
}
Edit:
Tops tops = new Tops("https://...");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference topFolderRef = rootRef.child("TopsFolder");
topFolderRef.push().setValue(tops);
Please also don't forget to make the top
property private in your Tops
class.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论