Firestore data doesn't show up in RecyclerView - android

I'm trying to put my firestore data within a recyclerview in Android. The app comes up with no errors, however no data shows up.
public class Diseaselist extends AppCompatActivity {
private TextView textView;
private FirebaseFirestore mDatabaseRef;
private Query mChartsQuery;
private RecyclerView mRecycler;
private FirebaseAuth mAuth;
private FirestoreRecyclerAdapter<Upload, ProductViewHolder> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_diseaselist);
RecyclerView recyclerView = findViewById(R.id.goodmeme);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
mAuth = FirebaseAuth.getInstance();
FirebaseUser currentUser = mAuth.getCurrentUser();
String useruid = currentUser.getUid();
Query query = rootRef.collection("users").document(useruid).collection("diagnoses")
.orderBy("disease", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Upload> options = new FirestoreRecyclerOptions.Builder<Upload>()
.setQuery(query, Upload.class)
.build();
adapter = new FirestoreRecyclerAdapter<Upload, ProductViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull ProductViewHolder holder, int position, #NonNull Upload productModel) {
holder.setProductName(productModel.getDisease());
}
#NonNull
#Override
public ProductViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
android.view.View views = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_diseaselist, parent, false);
return new ProductViewHolder(views);
}
};
recyclerView.setAdapter(adapter);
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if (adapter != null) {
adapter.stopListening();
}
}
private class ProductViewHolder extends RecyclerView.ViewHolder {
private android.view.View view;
ProductViewHolder(android.view.View itemView) {
super(itemView);
view = itemView;
}
void setProductName(final String productName) {
CardView cview =view.findViewById(R.id.cardview);
textView = view.findViewById(R.id.texty);
textView.setText(productName);
cview.setOnClickListener(new android.view.View.OnClickListener() {
#Override
public void onClick(android.view.View view) {
Toast.makeText(getApplicationContext(), productName, Toast.LENGTH_SHORT).show();
}
});
}
}
Layout File:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".Diseaselist"
tools:orientation="vertical">
<TextView
android:id="#+id/texty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="30sp"/>
<android.support.v7.widget.CardView
android:id="#+id/cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<ImageView
android:id="#+id/person_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp" />
<TextView
android:id="#+id/person_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/person_photo"
android:textSize="30sp" />
<TextView
android:id="#+id/person_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/person_name"
android:layout_toRightOf="#+id/person_photo" />
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/goodmeme"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Firestore structure Firestore Structure Screenshot 2
Upload Class code:
package com.Provendor.Provendor;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
import java.util.Calendar;
public class Upload implements Parcelable {
private String mName;
private String mImageUrl;
private String mdisease;
private String mdate;
private float mconfidence;
#Override
public int describeContents() {
return 0;
}
// write your object's data to the passed-in Parcel
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeFloat(mconfidence);
out.writeString(mName);
out.writeString(mImageUrl);
out.writeString(mdisease);
out.writeString(mdate);
}
// this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
public static final Parcelable.Creator<Upload> CREATOR = new Parcelable.Creator<Upload>() {
public Upload createFromParcel(Parcel in) {
return new Upload(in);
}
public Upload[] newArray(int size) {
return new Upload[size];
}
};
// example constructor that takes a Parcel and gives you an object populated with it's values
private Upload(Parcel in) {
mconfidence = in.readInt();
mName = in.readString();
mImageUrl = in.readString();
mdisease = in.readString();
mdate = in.readString();
}
public Upload() {
mName= ""; //empty constructor needed
}
public Upload(String name, String imageUrl, String disease, float confidence) {
if (name.trim().equals("")) {
name = "No Name";
}
mdisease=disease;
mdate=java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
mName = name;
mImageUrl = imageUrl;
mconfidence=confidence;
}
public String getName() {
return mName;
}
public String getDisease() {
return mdisease;
}
public float getConfidence() {
return mconfidence;
}
public String getDate() {
return mdate;
}
public void setName(String name) {
mName = name;
}
public void setdate() {
mdate=java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
}
public void setDisease(String disease) {
mdisease = disease;
}
public void setConfidence(float confidence) {
mconfidence = confidence;
}
public String getImageUrl() {
return mImageUrl;
}
public void setImageUrl(String imageUrl) {
mImageUrl = imageUrl;
}
}
I expect the output to produce a list of diseases based on the firestore collection, however the recyclerview is left empty. When attached to debug, no errors come up! Thanks for looking this over!

You aren't getting anything from the database because the name of your fields inside the Upload class are different than the name of the fields that exist in the database. Both should match. To solve this, you either change all the name of your fields inside your Upload class to match the properties that exist in the database or your can use annotations. Because I see that you are using private fields and public getters, you should use the PropertyName annotation only in front of the getter, for instance your getName() getter should look like this:
#PropertyName("name")
public String getName() {
return mName;
}

Related

I am trying to search user by name, and load some data to Recycleview. But the code is not working. Can somebody help me please [duplicate]

This question already has an answer here:
Firebase Android ListView not being displayed
(1 answer)
Closed 2 years ago.
I have pasted all the code below Please someone check it out and tell me what changes should I make.
And I think the problem is with the Child name in firebase. they are by name: Full_Name, Status, profileimage the third one is quite correct but the rest of two are making trouble please check the image at the end of post and my "model" "class", I think the problem is somewhere there.
Below is the xml design I created for layout which I inflate in adapter Class:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:background="#color/colorProfile"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/all_user_post_image"
android:layout_width="85dp"
android:layout_height="85dp"
android:layout_marginLeft="10dp"
android:src="#drawable/profile"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical">
<TextView
android:id="#+id/all_user_profile_full_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="User Full Name"
android:textAlignment="textStart"
android:textColor="#android:color/background_light"
android:textSize="18sp"
android:textStyle="bold"
/>
<TextView
android:id="#+id/all_user_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status"
android:textAlignment="textStart"
android:textColor="#android:color/background_light"
android:textSize="16sp"
/>
</LinearLayout>
</LinearLayout>
My model class:
package com.example.sociapp;
public class FindFriends
{
private String profileimage, Full_Name, Status;
public FindFriends ( )
{
}
public FindFriends(String profileimage, String Full_Name, String Status)
{
this.profileimage = profileimage;
this.Full_Name = Full_Name;
this.Status = Status;
}
public String getProfileimage() {
return profileimage;
}
public void setProfileimage(String profileimage) {
this.profileimage = profileimage;
}
public String getFull_Name() {
return Full_Name;
}
public void setFull_Name(String Full_Name) {
this.Full_Name = Full_Name;
}
public String getStatus() {
return Status;
}
public void setStatus(String Status) {
this.Status = Status;
}
}
My Adapter Class:
package com.example.sociapp;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import java.util.List;
import de.hdodenhof.circleimageview.CircleImageView;
public class FindFriendsAdapter extends RecyclerView.Adapter<FindFriendsAdapter.FindFriendsviewHolder> {
List<FindFriends> List;
Context context;
public FindFriendsAdapter(java.util.List<FindFriends> list, Context context) {
List = list;
this.context = context;
}
#NonNull
#Override
public FindFriendsviewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.all_user_display_layout, parent, false);
return new FindFriendsviewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull FindFriendsviewHolder holder, int position) {
FindFriends findFriends = List.get(position);
Picasso.get().load(findFriends.getProfileimage()).placeholder(R.drawable.profile).into(holder.AllUserProfilePic);
holder.AllUserFullName.setText(findFriends.getFull_Name());
holder.Status.setText(findFriends.getStatus());
}
#Override
public int getItemCount() {
return List.size();
}
public class FindFriendsviewHolder extends RecyclerView.ViewHolder {
CircleImageView AllUserProfilePic;
TextView AllUserFullName;
TextView Status;
public FindFriendsviewHolder(#NonNull View itemView) {
super(itemView);
AllUserProfilePic = itemView.findViewById(R.id.all_user_post_image);
AllUserFullName = itemView.findViewById(R.id.all_user_profile_full_name);
Status = itemView.findViewById(R.id.all_user_status);
}
}
}
The Activity in which I am calling the adapter and model class:
public class FindFriendsActivity extends AppCompatActivity {
private Toolbar mtoolbar;
private List<FindFriends> AllUserSearchResult;
private ImageButton SearchButton;
private EditText SearchInputText;
private RecyclerView SearchResultList;
private DatabaseReference AllUserDatabaseRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_friends);
mtoolbar = (Toolbar) findViewById(R.id.find_friends_appbar_layout);
setSupportActionBar(mtoolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Update Post");
AllUserDatabaseRef = FirebaseDatabase.getInstance().getReference().child("Users");
SearchResultList = (RecyclerView) findViewById(R.id.search_result_list);
SearchResultList.setHasFixedSize(true);
SearchResultList.setLayoutManager(new LinearLayoutManager(this));
SearchButton = (ImageButton) findViewById(R.id.search_friend_button);
SearchInputText = (EditText) findViewById(R.id.search_box_input);
AllUserSearchResult = new ArrayList<>();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
SearchResultList.setHasFixedSize(true);
SearchResultList.setLayoutManager(linearLayoutManager);
SearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
String SearchBoxInput = SearchInputText.getText().toString();
SearchPeopleAndFriends(SearchBoxInput);
}
});
}
private void SearchPeopleAndFriends(String searchBoxInput)
{
Toast.makeText(this, "Searching", Toast.LENGTH_SHORT).show();
Query searchFriendQuery = AllUserDatabaseRef.orderByChild("Full_Name")
.startAt(searchBoxInput).endAt(searchBoxInput +"\uf8ff");
searchFriendQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists())
{
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
FindFriends findFriends = dataSnapshot1.getValue(FindFriends.class);
AllUserSearchResult.add(findFriends);
}
FindFriendsAdapter findFriendsAdapter = new FindFriendsAdapter(AllUserSearchResult,FindFriendsActivity.this);
SearchResultList.setAdapter(findFriendsAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
The Firebase node where the Names of my fields I am retrieving is encircle with yellow color:
The ReyclerView is simply cast and I call the adapter on recyclerview, that's why didn't include the code where I defined recyclerview.
I am seeing that item getItemCount() dont count list size so please change this code
#Override
public int getItemCount() {
return 0;
}
to below code
#Override
public int getItemCount() {
return list.size();
}
FindFriendsAdapter.class
#Override
public int getItemCount() {
return 0;
}
to
#Override
public int getItemCount() {
if(List != null) {
return List.size();
}
return 0;
}
By the way,Member variables‘s initials should not be capitalized.
If anyone is facing the same issue,there for I am gonna answer the question cause I solve it myself.
There are Two Problems:
First: To include.
#Override
public int getItemCount() {
return list.size();
}
Second: To make the following changes, as you guys can see I am using Capital letter in start of parameter inside getter and setter changing them to small did my work.
package com.example.sociapp;
public class FindFriends
{
private String profileimage, Full_Name, Status;
public FindFriends ( )
{
}
public FindFriends(String profileimage, String fullName, String status)
{
this.profileimage = profileimage;
Full_Name = fullName;
Status = status;
}
public String getProfileimage() {
return profileimage;
}
public void setProfileimage(String profileimage) {
this.profileimage = profileimage;
}
public String getFull_Name() {
return Full_Name;
}
public void setFull_Name(String fullName) {
Full_Name = fullName;
}
public String getStatus() {
return Status;
}
public void setStatus(String status) {
Status = status;
}
}

ArrayList of custom objects from Firestore added to Spinner

New to all this....I have created the following code:
Custom Class Object
public class Category {
private String documentID;
private int id;
private String description;
private boolean active;
private int sort;
public Category(){
//public no-arg constructor needed
}
public Category(int id, String description, boolean active, int sort) {
this.id = id;
this.description = description;
this.active = active;
this.sort = sort;
}
#Exclude
public String getDocumentID() {
return documentID;
}
public void setDocumentID(String documentID) {
this.documentID = documentID;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
#Override
public String toString() {
return description;
}
}
MainActivity Class
public class MainActivity extends AppCompatActivity {
// Local XML obect declarations...
private Spinner spinner_Category;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Load the CATEGORY spinner with the ACTIVE categories from the Firestore
spinner_Category = (Spinner)findViewById(R.id.spinner_category);
populateCategories();
spinner_Category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Category category = (Category) parent.getSelectedItem();
displayCategoryData(category);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
String message = "Nothing selected";
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
private void populateCategories(){
// DBHelper dbHelper = DBHelper.getInstance(this);
DBHelper dbHelper = new DBHelper(this);
ArrayList<Category> categoryList = dbHelper.getAllCategories();
ArrayAdapter<Category> adapterCategories = new ArrayAdapter<Category>(this,
android.R.layout.simple_spinner_item, categoryList);
adapterCategories.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_Category.setAdapter(adapterCategories);
}
private void displayCategoryData(Category category) {
String description = category.getDescription();
int sort = category.getSort();
boolean active = category.isActive();
String userData = "Description: " + description + "\nSort: " + sort + "\nActive: " + active;
Toast.makeText(this, userData, Toast.LENGTH_LONG).show();
}
}
Method from my DBHelper class (a general class object to read/write to the Firestore dBase)
/* Function: getAllCategories
* Return a collection of ACTIVE cattegories from the Firestore */
public ArrayList<Category> getAllCategories() {
final ArrayList<Category> categoryList = new ArrayList<>();
CollectionReference colref = db.collection(COLLECTION_CATEGORIES);
colref.whereEqualTo(CATEGORY_ACTIVE, true)
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot dcSnapshot: queryDocumentSnapshots) {
Category c = dcSnapshot.toObject(Category.class);
c.setDocumentID(dcSnapshot.getId());
categoryList.add(c);
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, e.toString());
}
});
return categoryList;
}
And finally the activity_main XML
<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"
tools:context=".MainActivity">
<TextView
android:id="#+id/text_view_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="10sp"
android:text="App Title"
android:textColor="#color/cardview_dark_background"
android:textSize="18sp" />
<Spinner
android:id="#+id/spinner_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:padding="16dp" />
The issue is this code may populate the Spinner with Category objects but it doesn't display, initially select or trigger a OnItemSelected event. As this code is practically identical to other code I have used reading records from an SQLite database rather than a Firestore database then I am assuming it's the QueryDocumentSnapshot.toObject() method that alters the collection in some way.
Any advise will be greatly appreciated...
After populating the list,and adding the list to the adapter, run this command:
adapterCategories.notifyDataSetChanged();
Instead of using the default layout resource for the adapter, create a custom one and use it. So in your layout folder, create a layout such as this:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/black"
android:textSize="15sp"
android:textStyle="bold"
/>
and name it spinner_textbox.xml. Then in your activity, instead of this:
ArrayAdapter<Category> adapterCategories = new ArrayAdapter<Category>(this,
android.R.layout.simple_spinner_item, categoryList);
adapterCategories.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
do this:
ArrayAdapter<Category> adapterCategories = new ArrayAdapter<Category>(this,
R.layout.spinner_textbox, categoryList);
adapterCategories.setDropDownViewResource(R.layout.spinner_textbox);
Remember to remove the 'android' so that it finds your custom layout from R.

RecyclerView doesn't display any item view at load

I am retrieving JSON data and parcing it by Retrofit. I want to display it on RecyclerView but can't make it display the views. Where am I doing it wrong? Here MainActivity, Model and ListFlowerAdapter are given
public class MainActivity extends AppCompatActivity {
private ListFlowerAdapter mListFlowerAdapter;
private RecyclerView mRecyclerView;
private RetrofitClient mRetrofitClient;
LinearLayoutManager linearLayoutManager;
//private List<FlowerModel> myFlowers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
configViews();
mRetrofitClient = new RetrofitClient();
Call<List<FlowerModel>> listCall = mRetrofitClient.getFlowerService().getAllFlowers();
listCall.enqueue(new Callback<List<FlowerModel>>() {
#Override
public void onResponse(Call<List<FlowerModel>> call, Response<List<FlowerModel>> response) {
if (response.isSuccessful()) {
List<FlowerModel> flowerList = response.body();
for (int i = 0; i < flowerList.size(); i++) {
FlowerModel flowerModel = flowerList.get(i);
mListFlowerAdapter.addFlower(flowerModel);
}
} else {
int sc = response.code();
switch (sc) {
}
}
}
#Override
public void onFailure(Call<List<FlowerModel>> call, Throwable t) {
}
});
}
private void configViews() {
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
mListFlowerAdapter = new ListFlowerAdapter();
mRecyclerView.setAdapter(mListFlowerAdapter);
//mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false));
//mListFlowerAdapter = new ListFlowerAdapter();
// mRecyclerView.setAdapter(mListFlowerAdapter);
}
}
ListFlowerAdapter class
public class ListFlowerAdapter extends RecyclerView.Adapter<ListFlowerAdapter.MyViewHolder> {
private static final String TAG = ListFlowerAdapter.class.getSimpleName();
private Context context;
private List<FlowerModel> myFlowers;
public ListFlowerAdapter() {
myFlowers = new ArrayList<>();
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item, null, false);
return new MyViewHolder(row);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
FlowerModel currFlower = myFlowers.get(position);
holder.mName.setText(currFlower.getName());
holder.mPrice.setText(Double.toString(currFlower.getPrice()));
Picasso.with(holder.itemView.getContext()).load("http://services.hanselandpetal.com/photos/" + currFlower.getPhoto()).into(holder.mPhoto);
}
#Override
public int getItemCount() {
return myFlowers.size();
}
public void addFlower(FlowerModel flowerModel) {
myFlowers.add(flowerModel);
notifyDataSetChanged();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView mPhoto;
private TextView mName, mPrice;
public MyViewHolder(View itemView) {
super(itemView);
mPhoto = itemView.findViewById(R.id.flower_photo);
mName = itemView.findViewById(R.id.flower_name);
mPrice = itemView.findViewById(R.id.flower_price);
}
}
}
FlowerModel class
public class FlowerModel implements Serializable {
#Expose
private String category;
#Expose
private String price;
#Expose
private String instructions;
#Expose
private String photo;
#Expose
private String name;
#Expose
private int productId;
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public double getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getInstructions() {
return instructions;
}
public void setInstructions(String instructions) {
this.instructions = instructions;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
}
XML
<?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"
android:padding="5dp"
android:orientation="horizontal">
<ImageView
android:id="#+id/flower_photo"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#mipmap/ic_launcher"
android:scaleType="centerCrop" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/flower_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large"
android:text="Large Text" />
<TextView
android:id="#+id/flower_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:text="Medium Text" />
</LinearLayout>
<LinearLayout 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:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Downloading" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:visibility="visible" />
Could you help me with the issue, please? Thank you very much.
Don't notify your adapter recursively,
Your code :
for (int i = 0; i < flowerList.size(); i++) {
FlowerModel flowerModel = flowerList.get(i);
mListFlowerAdapter.addFlower(flowerModel); // Called from here
}
Code from adapter
public void addFlower(FlowerModel flowerModel) {
myFlowers.add(flowerModel);
notifyDataSetChanged(); // Notifying everytime
}
Instead, you should add all data to adapter and notify only once : (Updated code)
for (int i = 0; i < flowerList.size(); i++) {
FlowerModel flowerModel = flowerList.get(i);
mListFlowerAdapter.addFlower(flowerModel);
}
mListFlowerAdapter.notifyDataSetChanged(); // Notify like this
Code from adapter
public void addFlower(FlowerModel flowerModel) {
myFlowers.add(flowerModel);
//notifyDataSetChanged(); Remove from here
}
Pass activity context to the adapter and use that context for populating item on list view.
private Context mContext;
public ListFlowerAdapter(Context context) {
myFlowers = new ArrayList<>();
this.mContext = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View row = LayoutInflater.from(mContext).inflate(R.layout.row_item, parent, false);
return new MyViewHolder(row);
}
From activity send the activity context for initializing the adapter like this
mListFlowerAdapter = new ListFlowerAdapter(this);
And for adding a new item
public void addFlowers(List<FlowerModel> flowerModels) {
for (int i = 0; i < flowerModels.size(); i++) {
FlowerModel flowerModel = flowerModels.get(i);
myFlowers.add(flowerModel);
}
notifyDataSetChanged();
}
And successful response just send the list for updating the adapter
List<FlowerModel> flowerList = response.body();
mListFlowerAdapter.addFlowers(flowerList);
Hope this will help.
Try to remove this line:
mRecyclerView.setHasFixedSize(true);
And add this in the XML file:
android:fillViewport="true"
Without that line, your RecyclerView content initial height is 0 (empty list), and with the fixed size it can't grow although you add items to the adapter.

RecyclerView﹕ No adapter attached; skipping layout in fragment

I have been reading the different answers here on StackOverflow and tried to implement their solutions but I am still getting the error:
RecyclerView﹕ No adapter attached; skipping layout,
So I initialize my recycler view in onCreateView in my fragment like this :
public class StatusFragment extends Fragment {
DatabaseReference databaseStatus;
ProgressDialog progressDialog;
List<ElectricityClass> list = new ArrayList<ElectricityClass>();
RecyclerView recyclerView;
RecyclerView.Adapter adapter;
public StatusFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_status, container, false);
recyclerView = rootView.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Loading Data from Firebase Database");
progressDialog.show();
databaseStatus = FirebaseDatabase.getInstance().getReference().child("Electricity");
databaseStatus.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
ElectricityClass electricityClass = dataSnapshot.getValue(ElectricityClass.class);
list.add(electricityClass);
}
recyclerView.setLayoutManager(new LinearLayoutManager(getContext().getApplicationContext()));
adapter = new RecyclerViewAdapter(getContext().getApplicationContext(), list);
recyclerView.setAdapter(adapter);
progressDialog.dismiss();
}
#Override
public void onCancelled(DatabaseError databaseError) {
progressDialog.dismiss();
}
});
return rootView;
}
}
my RecyclerViewAdapter class :
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
List<ElectricityClass> dataList;
public RecyclerViewAdapter(Context context, List<ElectricityClass> list) {
this.dataList = list;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_items, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ElectricityClass studentDetails = dataList.get(position);
holder.StudentNameTextView.setText(studentDetails.getName());
holder.StudentNumberTextView.setText(studentDetails.getType());
}
#Override
public int getItemCount() {
return dataList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView StudentNameTextView;
public TextView StudentNumberTextView;
public ViewHolder(View itemView) {
super(itemView);
StudentNameTextView = itemView.findViewById(R.id.ShowStudentNameTextView);
StudentNumberTextView = itemView.findViewById(R.id.ShowStudentNumberTextView);
}
}
}
My list Electricity Class :
class ElectricityClass {
private String id;
private String email;
private String name;
private String type;
private String detail;
private String location;
private String date;
private String imgurl;
public ElectricityClass() {
// Required empty public constructor
}
public ElectricityClass(String id, String currentUserString, String imageUrl, String nameString, String typeString, String detailString, String locationString, String dateString){
this.id = id;
this.email = currentUserString;
this.name =nameString;
this.type = typeString;
this.detail = detailString;
this.location = locationString;
this.date = dateString;
this.imgurl = imageUrl;
}
public String getImgurl() {
return imgurl;
}
public void setImgurl(String imgurl) {
this.imgurl = imgurl;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
and here is my The layout in the fragment:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/recyclerView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
And the layout of an item:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardview1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
card_view:cardElevation="5dp"
card_view:contentPadding="5dp"
card_view:cardCornerRadius="5dp"
card_view:cardMaxElevation="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ECEFF1"
android:padding="10dp">
<TextView
android:id="#+id/StudentName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Student Name: "
android:textColor="#000"
android:textSize="20dp" />
<TextView
android:id="#+id/ShowStudentNameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Show Student Name"
android:textColor="#000"
android:textSize="20dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/StudentName"
android:layout_toEndOf="#+id/StudentName"
android:layout_marginLeft="19dp"
android:layout_marginStart="19dp" />
<TextView
android:id="#+id/StudentNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Phone Number: "
android:textColor="#000"
android:textSize="20dp"
android:layout_below="#+id/StudentName"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:id="#+id/ShowStudentNumberTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Show Number"
android:textColor="#000"
android:textSize="20dp"
android:layout_marginLeft="11dp"
android:layout_marginStart="11dp"
android:layout_below="#+id/ShowStudentNameTextView"
android:layout_toRightOf="#+id/StudentNumber"
android:layout_toEndOf="#+id/StudentNumber" />
</RelativeLayout>
</android.support.v7.widget.CardView>
now it shows,
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged()' on a null object reference
here I define my List2
public class StatusFragment extends Fragment {
DatabaseReference databaseStatus;
ProgressDialog progressDialog;
List<ElectricityClass> list2 = new ArrayList<ElectricityClass>();
List<ElectricityClass> list = new ArrayList<ElectricityClass>();
RecyclerView recyclerView;
RecyclerView.Adapter adapter;
and inside onDataChanged(),
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
ElectricityClass electricityClass = dataSnapshot.getValue(ElectricityClass.class);
list2.add(electricityClass);
}
refreshRv((ArrayList<ElectricityClass>) list2);
adapter = new RecyclerViewAdapter(getContext().getApplicationContext(), list);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
progressDialog.dismiss();
}
private void refreshRv(ArrayList<ElectricityClass> list2){
list.clear();
list.addAll(list2);
}
You are doing this wrong setting layout and adapter inside that onDataChange method. Rather create a private function that will instantiate your adapter, will set it to RecyclerView and will set layout manager too. (you may want to define the list from constructor of the adapter also like this list = new ArrayList<>(); )
When you are done with this function, call it in onCreateView method of the fragment, and inside onDataChange just call a refresh function(also private) that will clear your list(or not depending on your behaviour), add all new values and notify your adapter using adapter.notifyDataSetChanged() method.
Hope this will help you :)
EDIT: as someone mentioned in a comment, your error is just telling you that adapter is not set to RecyclerView, probably because onDataChanged() was not called. My explanation from above will solve the problem for sure
EDIT:
Define another list let's say list2, replace list.add(); with list2.add(); inside that for from onDataSetChanged();
Then after for, call this function
private void refreshRv(ArrayList<YourDataType> list2){
list.clear();
list.addAll(list2);
adapter.notifyDataSetChanged();
}
this works for me
#felicity just add this function properly
private void refreshRv(ArrayList<YourDataType> list2)
{
list.clear();
list.addAll(list2);
adapter.notifyDataSetChanged();
}
as lonut J.Bejan said

Data in recycler view not being uploaded to Firebase

So I did some research about this but was unable to solve this problem and every solution online led to me to a new error.
I am currently working on an Events App and relatively new to Android Studio.
I have a RecyclerView in an Admin app that verifies all the Event data uploaded on Firebase by an organizer. The organizer uploads the data such as event_tile, event_desc and event_image. This is stored in Firebase under root "Event". Later the Admin App receives these requests in the form of a recycler view, and has a button to approve them. All the approved events are would be stored in a separate table in Firebase with root "Approved_Events".
I am getting stuck in the approval part. The code is running fine with no errors but no data is being uploaded to my Firebase console.
Here is my Main Activity
public class MainActivity extends AppCompatActivity {
private RecyclerView request_eventList;
private DatabaseReference mRef, aRef;
private Button verify_button;
private TextView request_title, request_desc;
private ImageView request_image;
ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressDialog = new ProgressDialog(this);
mRef = FirebaseDatabase.getInstance().getReference().child("Event");
setContentView(R.layout.activity_main);
request_eventList = (RecyclerView) findViewById(R.id.request_eventList);
request_eventList.setHasFixedSize(true);
request_eventList.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Event, RequestViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Event, RequestViewHolder>(
Event.class,
R.layout.admin_event_row,
RequestViewHolder.class,
mRef
) {
#Override
protected void populateViewHolder(RequestViewHolder viewHolder, Event model, int position) {
viewHolder.setTitle(model.getTitle());
viewHolder.setDesc(model.getDesc());
viewHolder.setImage(getApplicationContext(), model.getImage());
}
};
request_eventList.setAdapter(firebaseRecyclerAdapter);
}
public static class RequestViewHolder extends RecyclerView.ViewHolder {
View mView;
public Button verify_button;
DatabaseReference mRef, aRef;
ProgressDialog progressDialog;
public RequestViewHolder(View itemView) {
super(itemView);
mView = itemView;
progressDialog = new ProgressDialog(mView.getContext());
verify_button = (Button) mView.findViewById(R.id.approve_button);
mRef = FirebaseDatabase.getInstance().getReference().child("Event");
aRef = FirebaseDatabase.getInstance().getReference().child("ApprovedEvents");
verify_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map <String, String> map = (Map<String, String>) dataSnapshot.getValue();
String title_val = map.get("title");
String desc_val = map.get("desc");
String image_val = map.get("image");
aRef.child("approved_title").setValue(title_val);
aRef.child("approved_desc").setValue(desc_val);
aRef.child("approved_image").setValue(image_val);
progressDialog.dismiss();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
public void setTitle(String title) {
TextView request_title = (TextView) mView.findViewById(R.id.request_title);
request_title.setText(title);
}
public void setDesc(String desc) {
TextView request_desc = (TextView) mView.findViewById(R.id.request_desc);
request_desc.setText(desc);
}
public void setImage(Context ctx, String image) {
ImageView request_image = (ImageView) mView.findViewById(R.id.request_image);
Picasso.with(ctx).load(image).into(request_image);
}
}
}
MainActivity XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.admin.admin.MainActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/request_eventList"
android:clickable="true">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Event Java Class
public class Event {
private String title, desc, image;
public Event(String title, String desc, String image) {
this.title = title;
this.desc = desc;
this.image = image;
}
public Event(){
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
admin_event_row XML file that will fill the recyclerView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/request_image"
android:src="#drawable/abc_btn_check_material"
android:adjustViewBounds="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/request_title"
android:text="Title will come here "
android:padding="10dp"
android:textStyle="bold"
android:textSize="15dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/request_desc"
android:text="Desc will come here "
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingBottom="10dp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/approve_button"
android:text="Yeah it's Cool "/>
</LinearLayout>
Final App Look
If your Event has more unapproved child, move verify_button.setOnClickListener from Holder to Adapter-populateViewHolder. You have to connect verify_button.setOnClickListener to row in recycleviewer to get values of title, desc and image from clicked item.
protected void populateViewHolder(RequestViewHolder viewHolder, Event model, int position) {
viewHolder.setTitle(model.getTitle());
viewHolder.setDesc(model.getDesc());
viewHolder.setImage(getApplicationContext(), model.getImage());
final String title = model.getTitle();
final String desc = model.getDesc();
final String image = model.getImage();
final DatabaseReference aRef = FirebaseDatabase.getInstance().getReference();
viewHolder.verify_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
String key = aRef.child("ApprovedEvents").push().getKey();
Event event = new Event(title, desc, image );
Map<String, Object> eventValues = event.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/ApprovedEvents/" + key, eventValues);
aRef.updateChildren(childUpdates);
}
});
}
};

Categories

Resources