My Android FirebaseUI Recycler view is responding well with String class datatype. But is not populating view when I use my POJO class as datatype.
I have taken time to ensure the names in my POJO matches the names in JSON file. Below are my codes:
public class MainActivity extends AppCompatActivity {
public static class MessageViewHolder extends RecyclerView.ViewHolder {
TextView messageTextView;
public MessageViewHolder(View view) {
super(view);
messageTextView =(TextView) messageTextView.findViewById(android.R.id.text1);
}
}
android.support.v7.widget.RecyclerView recyclerView;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart()
{
super.onStart();
//Recycler
recyclerView=(android.support.v7.widget.RecyclerView)findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//Adapter
FirebaseRecyclerAdapter<User, MessageViewHolder> mFirebaseAdapter=
new FirebaseRecyclerAdapter<User, MessageViewHolder>(User.class,
R.layout.layout,
MessageViewHolder.class,
myRef.child("User")
) {
#Override
protected void populateViewHolder(MessageViewHolder viewHolder, User model, int position) {
viewHolder.messageTextView.setText(model.getName());
}
};
recyclerView.setAdapter(mFirebaseAdapter);
}
}
POJO:
public class User {
public User(){
}
String Name;
String email;
public User(String Name){
this.Name=Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getName() {
return Name;
}
}
Error From Firebase
Exception com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.projectgenuis.eneanews.User
EDIT(JSON)
{
"User" : {
"Name" : "Zion",
}
The FirebaseUI adapters are designed to show lists of items, in your case a list of users. In your current data model, there is only a single user under the /User node. That means there is no way to show it in a list view.
The simplest way to fix this is to change your JSON to have a list of users under a Users node:
{
"Users" : {
"User1": {
"Name" : "Zion"
}
"User2": {
"Name" : "puf"
}
}
}
And then attach the adapter to this collection:
mFirebaseAdapter= new FirebaseRecyclerAdapter<User, MessageViewHolder>(
User.class,
R.layout.layout,
MessageViewHolder.class,
myRef.child("Users")
) {
Related
everyone, I was trying to make a music app, and for this, I Created a Horizontal RecyclerView in my HomeFragment and my horizontal RecyclerView is getting an image with artist name.
But after clicking I load another Activity. In my other activity, I was trying to load SongsData from firebase in a listView with RecyclerView.
But the problem is I am not getting data from Firebase and it is returning null data. I provided my code below and here is the screenshot of my Firebase database:- ScreenShot
My List Class:-
public class TestUploads
{
private String songName;
private String songImageUri;
private String songUrl;
private String artistName;
public TestUploads() {
}
public String getSongName() {
return songName;
}
public void setSongName(String SongName) {
this.songName = SongName;
}
public String getSongImageUri() {
return songImageUri;
}
public void setSongImageUri(String SongImageUri) {
this.songImageUri = SongImageUri;
}
public String getSongUrl() {
return songUrl;
}
public void setSongUrl(String SongUrl) {
this.songUrl = songUrl;
}
public TestUploads(String SongImageUri, String SongName, String SongUrl ) {
this.songName = SongName;
this.artistName = SongImageUri;
this.songUrl = SongUrl;
}
}
My Adapter Class:-
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.TestViewHolder>{
private Context mContext;
private List<TestUploads> mUploads;
public TestAdapter(Context context , List<TestUploads> uploads) {
mContext = context;
mUploads = uploads;
}
#NonNull
#Override
public TestViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.test_package_layout , parent ,false);
return new TestViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull TestViewHolder holder, int position) {
TestUploads uploadcurrent = mUploads.get(position);
holder.name.setText(uploadcurrent.getSongName());
Glide.with(mContext)
.load(uploadcurrent.getSongImageUri())
.into(holder.image_view);
}
#Override
public int getItemCount() {
return mUploads
.size();
}
public class TestViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView artist_name;
public CircleImageView image_view;
public TestViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.test_package_song_name);
artist_name = itemView.findViewById(R.id.test_package_artist_name);
image_view = itemView.findViewById(R.id.test_package_image_name);
}
}
}
My Activity:-
public class TestActivity extends AppCompatActivity {
private ValueEventListener listener;
private DatabaseReference reference;
private List<TestUploads> mUploads;
private RecyclerView mRecyclerView;
private TestAdapter adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_package_activity);
reference = FirebaseDatabase.getInstance().getReference("ArtistView").child(getIntent().getStringExtra("Artist"))
.child("Songs");
Toast.makeText(this, "" + getIntent().getStringExtra("Artist"), Toast.LENGTH_SHORT).show();
mUploads = new ArrayList<>();
mRecyclerView = findViewById(R.id.test_pacakge_recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.smoothScrollToPosition(0);
adapter = new TestAdapter(this , mUploads);
mRecyclerView.setAdapter(adapter);
listener = reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUploads.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
TestUploads uploads =postSnapshot.getValue(TestUploads.class);
mUploads.add(uploads);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Sorry for so much code but this is not hard to solve. If you find the solution please reply to me. Thanks for reading this.
The problem in your code lies in the fact that the names of the fields in your TestUploads class are different than the name of the properties in your database. You have in your TestUploads class a field named songName but in your database, I see it as SongName and this is not correct. The names must match. When you are using a getter named getSongName(), Firebase is looking in the database for a field named songName and not SongName. See the lowercase s letter vs. capital letter S?
There are two ways in which you can solve this problem. The first one would be to remove the data in your database and add it again using field names that start with lowercase, as exist in your TestUploads class.
If you are not allowed to use the first solution, then the second approach will be to use annotations. So you should use the PropertyName annotation in front of the getters. So in your TestUploads class, a getter should look like this:
#PropertyName("SongName")
public String getSongName() {
return songName;
}
I am using retrofit2 for fetching data from the server and after fetching saving data in room database and then showing in recycler view.Whenever app runs its fetches data from the server and save it in room database.I have successfully fetched JSON data from server and saved in room database and from room it is properly showing in recycler view.
Problem: Whenever data fetches from the server it inserts the same old data in room again due to which same data shows multiple times in recycler view.
What I want: I don't want recycler view to show same data multiple times.I don't want to copy same data again in room database.
This is what I have done so far:
UserDao.java
#Dao
public interface UserDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void Insert(User... users);
#Query("SELECT * FROM Users")
LiveData<List<User>> getRoomUsers();
}
User.java
#Entity(tableName = "Users")
public class User {
#PrimaryKey
private String id;
#ColumnInfo(name = "name")
#SerializedName("name")
#Expose
private String name;
#ColumnInfo(name = "age")
#SerializedName("age")
#Expose
private String age;
public User(String id,String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
UserRepository.java
public class UserRepository {
private Context context;
private UserDb userDb;
private LiveData<List<User>> listLiveData;
public UserRepository(Context context) {
this.context = context;
userDb = UserDb.getInstance(context);
listLiveData = userDb.userDao().getRoomUsers();
}
public void getUserList(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<User>> userList = apiService.getUser();
userList.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, final Response<List<User>> response) {
Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
if(response.body() != null) {
List<User> list = response.body();
for (int i = 0; i < list.size(); i++) {
String names = list.get(i).getName();
String age = list.get(i).getAge();
String id = UUID.randomUUID().toString();
User user = new User(id,names,age);
userDb.userDao().Insert(user);
}
}
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onComplete() {
Toast.makeText(context,"Data inserted",Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Throwable e) {
Toast.makeText(context,e.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Toast.makeText(context,t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
public LiveData<List<User>> getRoomUsers(){
return listLiveData;
}
}
UserViewModel.java
public class UserViewModel extends AndroidViewModel {
private UserRepository repo;
private LiveData<List<User>> listLiveData;
public UserViewModel(#NonNull Application application) {
super(application);
repo = new UserRepository(application);
listLiveData = repo.getRoomUsers();
}
public LiveData<List<User>> getListLiveData() {
return listLiveData;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
UserRepository userRepository;
RecyclerView recyclerView;
UserViewModel userModel;
List<User> userList;
UserAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
userRepository = new UserRepository(this);
userModel = ViewModelProviders.of(this).get(UserViewModel.class);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
userList = new ArrayList<>();
adapter = new UserAdapter(userList,this);
recyclerView.setAdapter(adapter);
userModel.getListLiveData().observe(this, new Observer<List<User>>() {
#Override
public void onChanged(List<User> users) {
adapter.setUserList(users);
}
});
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this,AddUser.class);
startActivity(i);
}
});
userRepository.getUserList();
}
UserAdapter.java
public class UserAdapter extends
RecyclerView.Adapter<UserAdapter.ViewHolder> {
List<User> userList;
Context context;
public UserAdapter(List<User> userList, Context context) {
this.userList = userList;
this.context = context;
}
#NonNull
#Override
public UserAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_row_layout,parent,false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull UserAdapter.ViewHolder holder, int position) {
User users = userList.get(position);
holder.row_name.setText(users.getName());
holder.row_age.setText(users.getAge());
}
#Override
public int getItemCount() {
return userList.size();
}
public void setUserList(List<User> userList) {
this.userList = userList;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView row_name,row_age;
public ViewHolder(#NonNull View itemView) {
super(itemView);
row_name = itemView.findViewById(R.id.row_name);
row_age = itemView.findViewById(R.id.row_age);
}
}
}
Someone please let me know how can I achieve desired result. Any help would be appreciated.
THANKS
The answer is quite simple, you do not have a unique primary key. You're generating a key yourself using
String id = UUID.randomUUID().toString();
In your first request, you might have this:
User("mdkasdkasjkdjakjdkasd", "Zun", 22);
and in your second request you get
User("djei3ujf493j9fj49dj9", "Zun", 22);
as such, you'll always have duplicate entries in your database since room considers the user with name 'Zun" to NOT be the same.
In order to solve this, create a unique primary key that's unique to a User class. Do not use a random text generator.
Okay you should do it like this,
check if user is exist in db or not,
#Query("SELECT * FROM user WHERE id = :userId")
public User idUserExists(int userId);
if it does than add update query
#Update
public void updateUser(User user); // keep the model with same user id
else insert the new record
#Insert
public void insertUser(User user); // Model with new user Id
I am using recyclerView and Adapter to fetch the data in profileActivity
here is my
public class studentDetailsRecyclerActivity extends AppCompatActivity {
//recyclerview to set the details for UI in the student profile activity
private RecyclerView mRecyclerView;
private storeDetailsAdapter mStoreDetailsAdapter;
private List<storeStudentDetails> studentDetailsList;
private FirebaseFirestore dbReference;
private ProgressBar mProgressBar;
private String TAG = studentDetailsRecyclerActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
dbReference = FirebaseFirestore.getInstance();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_details);
mProgressBar = findViewById(R.id.progressbar);
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView_products);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
studentDetailsList = new ArrayList<>();
mStoreDetailsAdapter = new storeDetailsAdapter(this,studentDetailsList);
mRecyclerView.setAdapter(mStoreDetailsAdapter);
//to get the "details" this is our collection from firestore so we must fetch them
//by calling the addOnSuccessListener
dbReference.collection("details").get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) { //we must have to hide the progress bar when the data gets loaded
//here queryDocumentsSnapshot will hold all the "details" which is your collection in firestore
if(!queryDocumentSnapshots.isEmpty()){
//we must have to create empty list so that to store all
//details from DocumentsSnapshots
List<DocumentSnapshot> list = queryDocumentSnapshots.getDocuments();
//enhanced for loop because we have to give every index documentSnapShot
for(DocumentSnapshot d: list){
storeStudentDetails sd = d.toObject(storeStudentDetails.class);
studentDetailsList.add(sd);
Log.d(TAG, "onSuccess: " + sd.toString());
}
//to refresh and sync we must have to use notifyDataSetChanged
mStoreDetailsAdapter.notifyDataSetChanged();
}
}
}) .addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(), "Error getting data!!!", Toast.LENGTH_LONG).show();
}
});
}
}
and here is my storeDetailsAdapter
import java.util.List;
public class storeDetailsAdapter extends RecyclerView.Adapter<storeDetailsAdapter.StudentViewHolder>{
private Context context;
private List<storeStudentDetails> studentDetailsList;
public storeDetailsAdapter(Context context, List<storeStudentDetails> studentDetailsList) {
this.context = context;
this.studentDetailsList = studentDetailsList;
}
#NonNull
#Override
public StudentViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new StudentViewHolder(
LayoutInflater.from(context).inflate(R.layout.profile_activity, parent, false)
);
}
#Override
public void onBindViewHolder(#NonNull StudentViewHolder holder, int position) {
storeStudentDetails mStoreDetails = studentDetailsList.get(position);
holder.studName.setText(mStoreDetails.getStudentName());
holder.rollNum.setText(mStoreDetails.getRollNo());
holder.bookName.setText( mStoreDetails.getBook());
holder.fine.setText("Fine:" + mStoreDetails.getFine());
holder.dept.setText(mStoreDetails.getDept());
}
#Override
public int getItemCount() {
return studentDetailsList.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studName,rollNum,bookName,dept,fine;
public StudentViewHolder(View itemView) {
super(itemView);
studName=itemView.findViewById(R.id.studentName_prof);
rollNum = itemView.findViewById(R.id.rollNumber_prof);
bookName = itemView.findViewById(R.id.bookName_prof);
fine = itemView.findViewById(R.id.fineAmt_prof);
dept = itemView.findViewById(R.id.department_prof);
}
}
}
and here is my StoreStudentDetails class:
public class storeStudentDetails implements Serializable {
private String studentName;
private String rollNo;
private String book;
private Double fine;
private String dept;
#Exclude private String id;
public storeStudentDetails() {
}
public storeStudentDetails(String studentName, String rollNo,String book, double fine ,String dept) {
this.studentName = studentName;
this.rollNo = rollNo;
this.book = book;
this.fine = fine;
this.dept = dept;
}
public void setId(String id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public String getRollNo() {
return rollNo;
}
public String getBook() {
return book;
}
public Double getFine() {
return fine;
}
public String getDept() {
return dept;
}
public String getId() {
return id;
}
}
To solve this, please move the following lines of code:
mStoreDetailsAdapter = new storeDetailsAdapter(this,studentDetailsList);
mRecyclerView.setAdapter(mStoreDetailsAdapter);
Right before the following line of code:
mStoreDetailsAdapter.notifyDataSetChanged();
And this is because onSuccess() method has an asynchronous behavior and by the time you are setting the adapter outside the callback your list is empty.
As you can see, the easiest solution for this problem is to move those lines of code inside the callback. but if you want to use the value of your studentDetailsList outside the onSuccess() method, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.
I have this DB structure:
{
"customers" : {
"-L-OcgJ0kwTNSm6HoSvG" : {
"address" : "Test Alamat",
"birthday" : "1990-12-03",
"email" : "Dodi#gmail.com",
"name" : "Dodi",
"outletID" : "2673",
"phone" : "09888777111"
}
}
}
Now i want to load all data of "customers" into ListView using FirebaseUI-Android library. And here is the codes:
Query query = FirebaseDatabase.getInstance().getReference().child("customers").limitToLast(50);
FirebaseListOptions<Customers> options = new FirebaseListOptions.Builder<Customers>()
.setLayout(R.layout.row_customer)
.setQuery(query, Customers.class)
.build();
FirebaseListAdapter<Customers> adapter = new FirebaseListAdapter<Customers>(options) {
#Override
protected void populateView(View view, Customers customer, int position) {
((TextView) view.findViewById(R.id.txtCustomerName)).setText(customer.name);
((TextView) view.findViewById(R.id.txtCustomerAddress)).setText(customer.address);
((TextView) view.findViewById(R.id.txtCustomerPhone)).setText(customer.phone);
//and i've set the adapter into ListView
((ListView)layout.findViewById(R.id.lvCustomerList)).setAdapter(adapter);
And here is Customers.java:
#IgnoreExtraProperties
public class Customers {
public String name, outletID, address, phone, birthday, email;
public Customers() {
}
public Customers(String name, String outletID, String address, String phone, String birthday, String email) {
this.name = name;
this.outletID = outletID;
this.address = address;
this.phone = phone;
this.birthday = birthday;
this.email = email;
}
}
Please help me what is the problem with my source code?
i've run it and the data failed to display (only blank on my listview). There's no errors on my Android Studio logs.
I recommend to you to create custom Adapter and to use a RecyclerView (it is faster and better than a ListView )
Something like this:
public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.MessageViewHolder> {
private List<Customer> customerList;
private Context context;
public CustomerAdapter(List<Customer> customerList, Context context) {
this.customerList= customerList;
this.context = context;
}
#Override
public CustomerAdapter.MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.your_layout, parent, false);
return new CustomerAdapter.MessageViewHolder(v);
}
public class CustomerViewHolder extends RecyclerView.ViewHolder {
public TextView customername, customeraddress, customerphone;
public CustomerViewHolder(View view) {
super(view);
customername = view.findViewById(R.id.txtCustomerName);
customeraddress = view.findViewById(R.id.txtCustomerAddress);
customerphone = view.findViewById(R.id.txtCustomerPhone);
}
}
#Override
public int getItemCount() {
return customerList.size();
}
#Override
public void onBindViewHolder(final CustomerAdapter.MessageViewHolder holder, final int position) {
holder.customername.setText(customerList.get(position).getName;
holder.customeraddress.setText(customerList.get(position).getAddress;
holder.customerphone.setText(customerList.get(position).getPhone;
}
And you can get the data like this:
FirebaseDatabase.getInstance().getReference().child("customers").addValueEventListener(new ValueEventlistener{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<Customer> custoemrList = new ArrayList<>();
for (final DataSnapshot snapshot : dataSnapshot.getChildren()) {
Customer customer = new Customer();
customer.setName(snapshot.child("name").getValue().toString();
...
...
customerList.add(customer);
}
customerAdapter= new customerAdapter(customerList, YourActivity.this);
recyclerView.setAdapter(chatsAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
});
And in your Customer class you have to add getters and setters.
Press Alt + Insert -> Getters and Setters -> Select All -> Enter
This should be it
Change this line of code:
Query query = FirebaseDatabase.getInstance().getReference().child("customers").limitToLast(50)
with
Query query = FirebaseDatabase.getInstance().getReference()
.child("customers")
.orderByChild("name")
.limitToLast(50);
For this I am using Firebase as the database and Picasso to load the images on screen. After I login I am unable to see the images and the names of each category.
I have used a model name "Category" with setters and getters but these messages keep on coming up on my logcat:
My model looks like this at the moment:
public class Category {
private String name, image;
public Category() {
}
public Category(String name, String image) {
this.name = name;
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
This is a sample of my database. it shows the category image link and the name of it.
The list of categories are supposed to show in a fragment. This is my fragment class.
public class CategoryFragment extends Fragment {
View myFragment;
RecyclerView categoryList;
RecyclerView.LayoutManager layoutManager;
FirebaseRecyclerAdapter<Category, CategoryViewHolder> adapter;
// Firebase Tings
FirebaseDatabase database;
DatabaseReference categories;
public static CategoryFragment newInstance() {
CategoryFragment categoryFragment = new CategoryFragment();
return categoryFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = FirebaseDatabase.getInstance();
categories = database.getReference("Category");
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
myFragment = inflater.inflate(R.layout.fragment_category, container, false);
categoryList = (RecyclerView) myFragment.findViewById(R.id.categoryList);
categoryList.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(container.getContext());
categoryList.setLayoutManager(layoutManager);
loadCategories();
return myFragment;
}
private void loadCategories() {
adapter = new FirebaseRecyclerAdapter<Category, CategoryViewHolder>(
Category.class,
R.layout.category_item,
CategoryViewHolder.class,
categories
) {
#Override
protected void populateViewHolder(CategoryViewHolder viewHolder, final Category model, int position) {
viewHolder.tvCategoryName.setText(model.getName());
Picasso.with(getActivity())
.load(model.getImage())
.into(viewHolder.ivCategoryImage);
viewHolder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Toast.makeText(getActivity(), String.format("%s | %s", adapter.getRef(position).getKey(), model.getName()), Toast.LENGTH_SHORT).show();
}
});
}
};
adapter.notifyDataSetChanged();
categoryList.setAdapter(adapter);
}
}
This is my CategoryViewHolder class
public class CategoryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvCategoryName;
public ImageView ivCategoryImage;
private ItemClickListener itemClickListener;
public CategoryViewHolder(View itemView) {
super(itemView);
ivCategoryImage = (ImageView) itemView.findViewById(R.id.ivCategoryImage);
tvCategoryName = (TextView) itemView.findViewById(R.id.tvCategoryName);
itemView.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
#Override
public void onClick(View view) {
itemClickListener.onClick(view, getAdapterPosition(), false);
}
}
I have looked for different solutions view the category image and names, but no luck.
UPDATE:
I have updated the database to this structure
I have tried using these 2 ways of showing the data on device
categories=FirebaseDatabase.getInstance().getReference().child("Category");
/*database = FirebaseDatabase.getInstance();
categories = database.getReference("Category");*/
But still no success.
Instead it shows the same errors. I have not changed my model in any way
Thanks for the help in advance.
P.S thanks for the solutions mentioned before, too bad it did work.
Any more help would be suffice.
The database structure from your link seems to be like this
category
|-category
|01
-------name
-------image
you should refer to the second category node to be able to reach your data
but you don't seem to do that.
So instead of using these 2 lines of code
database = FirebaseDatabase.getInstance();
categories = database.getReference("Category");
try to use this
DatabaseReference categories;
//and refer to your database like that
categories=FirebaseDatabase.getInstance().getReference().child("Category").child("Category");
according to the link you added this should be the correct way to refer to your database
Your current database structure has Category objects nested under the /Category/Category node, but the reference you are using for your FirebaseRecyclerAdapter is pointing to the parent /Category node.
This is causing the errors in your logs - the FirebaseRecyclerAdapter is trying to marshal the children of the /Category node into the Category class, but there are no matching direct children at that location.
To fix this, you can adjust the reference that the FirebaseRecyclerAdapter is using:
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = FirebaseDatabase.getInstance();
categories = database.getReference("Category").child("Category");
}
Or, change your database structure so that categories are listed as direct children of the /Category node:
{
"Category" : {
"01" : {
"Name" : "Animals",
"image" : "..."
},
"02" : {
...
}
}
}