How to load firebase data into recyclerview - android

I'm seeking help on how to load a data stored in a Firebase Database into a recyclerview.
The below screenshot indicates how I would like for the data to be structured when loaded into the recyclerview.
I am able to access the data from individual paths such as "Upcoming/Events/03/23" using the addEventListener but unable to load dynamically into a recyclerview in the format above.
See Code below that I have below to load the children under the different nodes, but i'm able to load it into the recyclerview
private ListView mUserList;
private ArrayList<String> mUpcomingList = new ArrayList<>();
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,mUpcomingList);
mUserList.setAdapter(arrayAdapter);
String CurrentString = date.toString().trim();
StringTokenizer tokens = new StringTokenizer(CurrentString, "/");
String first = tokens.nextToken();
String second = tokens.nextToken();
mDatabase = FirebaseDatabase.getInstance().getReference().child("Upcoming/Events").child(first);
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
Public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG,"Listing children");
for (DataSnapshot child: dataSnapshot.getChildren()) {
mUpcomingList.add(child.getKey());
arrayAdapter.notifyDataSetChanged();
}
Your help is appreciated.

when you used then you make recyclerview adatper and bind this adapter into a recycler view . used below code for display firebase all the data and change according your need and make changes.
RecyclerView Adapter::
public class DisplayAllData extends RecyclerView.Adapter<DisplayAllData.ItemViewHolder>{
private List<User> mUserLsit=new ArrayList<>();
private Context mContext;
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout,parent,false);
return new ItemViewHolder(view);
}
public DisplayAllData(Context mContext,List<User> mUserLsit) {
this.mContext=mContext;
this.mUserLsit = mUserLsit;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
User user=mUserLsit.get(position);
holder.mTvName.setText(user.name);
holder.mTvEmail.setText(user.email);
holder.mTvPwd.setText(user.pwd);
}
#Override
public int getItemCount() {
return mUserLsit.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
TextView mTvName,mTvEmail,mTvPwd;
public ItemViewHolder(View itemView) {
super(itemView);
mTvEmail=itemView.findViewById(R.id.rlTvEmail);
mTvName=itemView.findViewById(R.id.rlTvName);
mTvPwd=itemView.findViewById(R.id.rlTvPwd);
}
}
}
In Adapter take a simple layout and make three textview control and bind data into that.
then after take activity layout and define recycler view in xml. then after used below code to read firebase database record and display recyclerview.
public class DisplayActivity extends AppCompatActivity {
private RecyclerView mRvData;
private DisplayAllData allDataAdapter;
private DatabaseReference mDatabase;
private TextView mTvEmpty;
private FirebaseDatabase mFirebaseInstance;
private List<User> mUserList = new ArrayList<>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.display_data);
initView();
}
private void initView() {
mFirebaseInstance = FirebaseDatabase.getInstance();
mDatabase = mFirebaseInstance.getReference("usersDb/UserTable");
mRvData = findViewById(R.id.rvData);
mTvEmpty = findViewById(R.id.dlTvEmpty);
mRvData.setLayoutManager(new LinearLayoutManager(this));
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUserList.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
User user = dataSnapshot1.getValue(User.class);
mUserList.add(user);
}
allDataAdapter = new DisplayAllData(DisplayActivity.this, mUserList);
mRvData.setAdapter(allDataAdapter);
allDataAdapter.notifyDataSetChanged();
if (mUserList.isEmpty())
mTvEmpty.setVisibility(View.VISIBLE);
else
mTvEmpty.setVisibility(View.GONE);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}

You have to use FirebaseRecyclerAdapter,
as
FirebaseRecyclerAdapter<Model, ViewHolder> Adapter = new FirebaseRecyclerAdapter<Model, ViewHolder>(
Model.class, //Name of model class
R.layout.row, //Row layout to show data
viewHolder.class, //Name of viewholder class
mDatabaseRef // Database Refernce
) {
#Override
protected void populateViewHolder(VieHolder viewHolder, Model model, int position) {
//Your Method to load Data
}
};
RecyclerView.setAdapter(Adapter);
For this you have to create two other classes, One is viewholder ( to display data) and second model class ( refers to name of nodes from where you are fetching data ).

final DatabaseReference cartListRef = FirebaseDatabase.getInstance().getReference().child("Cart List");
FirebaseRecyclerOptions<Cart> options = new FirebaseRecyclerOptions.Builder<Cart>()
.setQuery(cartListRef.child("User View")
.child(Prevalent.currentOnlineUser.getPhoneNumber())
.child("Products"), Cart.class).build();
FirebaseRecyclerAdapter<Cart, CartViewHolder> adapter =
new FirebaseRecyclerAdapter<Cart, CartViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull CartViewHolder holder, int position, #NonNull final Cart model) {
holder.txtProductQuantity.setText("Quantity = " + model.getQuantity());
holder.txtProductName.setText(model.getPname());
holder.txtProductPrice.setText("Price = " + model.getPrice() + "৳");
int oneTypeProductPrice = ((Integer.valueOf(model.getPrice()))) * Integer.valueOf(model.getQuantity());
overTotalPrices = overTotalPrices + oneTypeProductPrice;
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CharSequence options[] = new CharSequence[]
{
"Edit",
"Remove"
};
AlertDialog.Builder builder = new AlertDialog.Builder(CartActivity.this);
builder.setTitle("Cart Options");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int i) {
if (i == 0){
Intent intent = new Intent(CartActivity.this, ProductDetailsActivity.class);
intent.putExtra("pid", model.getPid());
startActivity(intent);
}
if (i == 1){
cartListRef.child("User View")
.child(Prevalent.currentOnlineUser.getPhoneNumber())
.child("Products")
.child(model.getPid())
.removeValue()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(CartActivity.this,"Item removed successfully.",Toast.LENGTH_LONG).show();
Intent intent = new Intent(CartActivity.this, HomeActivity.class);
startActivity(intent);
}
}
});
}
}
});
builder.show();
}
});
}
#NonNull
#Override
public CartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cart_items_layout, parent, false);
CartViewHolder holder = new CartViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}

Related

Child recyclerView showing same items for all parent recyclerView (using Firebase Realtime Database)

Basically I want to create a parent recyclerView which shows the categories and the child recyclerView shows the books of that specific category. But the result of my code is giving me the same books for all categories. Below is the necessary code attached.
Java Source Code for home fragment adapter call
private void loadCategories() {
//init arrayList
categoryArrayList = new ArrayList<>();
//get all categories from firebase
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Categories");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
//clear arrayList before adding data to it
categoryArrayList.clear();
for (DataSnapshot ds : snapshot.getChildren()) {
//get data
ModelCategory model = ds.getValue(ModelCategory.class);
//add category to arrayList
categoryArrayList.add(model);
}
//setup adapter
adapterCategoryHome = new AdapterCategoryHome(categoryArrayList);
//set adapter to recyclerView
binding.categoryRv.setAdapter(adapterCategoryHome);
adapterCategoryHome.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
Parent Adapter
public class AdapterCategoryHome extends RecyclerView.Adapter<AdapterCategoryHome.HolderCategory> {
private Context context;
public ArrayList<ModelCategory> categoryArrayList;
public static final String TAG = "CATEGORY_HOME_TAG";
//arrayList to hold data of type ModelPdf
private ArrayList<ModelPdf> pdfArrayList;
private AdapterPdfHome adapterPdfHome;
public AdapterCategoryHome(ArrayList<ModelCategory> categoryArrayList) {
this.categoryArrayList = categoryArrayList;
}
#NonNull
#Override
public HolderCategory onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//bind view of row_category_home.xml
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_category_home, parent, false);
this.context = parent.getContext();
return new HolderCategory(view);
}
#Override
public void onBindViewHolder(#NonNull AdapterCategoryHome.HolderCategory holder, int position) {
//get data
ModelCategory model = categoryArrayList.get(position);
String id = model.getId();
String category = model.getCategory();
String uid = model.getUid();
long timestamp = model.getTimestamp();
Log.d(TAG, "onBindViewHolder: "+category);
//set data
holder.categoryTv.setText(category);
loadPdfList(model, holder);
}
private void loadPdfList(ModelCategory model, HolderCategory holder) {
//init list before adding data
pdfArrayList = new ArrayList<>();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Books");
ref.orderByChild("categoryId").equalTo(model.getId())
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
pdfArrayList.clear();
for (DataSnapshot ds : snapshot.getChildren()) {
//get data
ModelPdf model = ds.getValue(ModelPdf.class);
//add to list
pdfArrayList.add(model);
}
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false);
holder.bookRv.setHasFixedSize(true);
Log.d(TAG, "pdf size: " + pdfArrayList.size() + model.getCategory() + holder.categoryTv.getText()+ holder.categoryTv.getContext());
//setup adapter
adapterPdfHome = new AdapterPdfHome(holder.bookRv.getContext(), pdfArrayList);
holder.bookRv.setLayoutManager(layoutManager);
holder.bookRv.setAdapter(adapterPdfHome);
adapterPdfHome.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
#Override
public int getItemCount() {
return categoryArrayList.size();
}
/*View Holder class to hold UI views for row_category.xml*/
class HolderCategory extends RecyclerView.ViewHolder {
//ui views of row_category.xml
TextView categoryTv;
RecyclerView bookRv;
public HolderCategory(#NonNull View itemView) {
super(itemView);
//init ui views
categoryTv = itemView.findViewById(R.id.categoryTv);
bookRv = itemView.findViewById(R.id.bookRv);
}
}
}
Child Adapter
public class AdapterPdfHome extends RecyclerView.Adapter<AdapterPdfHome.HolderPdfAdmin> {
//context
private Context context;
//arrayList to hold list of data of type modelPdf
public ArrayList<ModelPdf> pdfArrayList;
private FilterPdfAdmin filter;
private static final String TAG = "PDF_ADAPTER_TAG";
//progress dialog
private ProgressDialog progressDialog;
//constructor of above
public AdapterPdfHome(Context context, ArrayList<ModelPdf> pdfArrayList) {
this.context = context;
this.pdfArrayList = pdfArrayList;
Log.d(TAG, "AdapterPdfHome: "+pdfArrayList.size());
//init progress dialog
progressDialog = new ProgressDialog(context);
progressDialog.setTitle("Please Wait");
progressDialog.setCanceledOnTouchOutside(false);
}
#NonNull
#Override
public HolderPdfAdmin onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//bind view of row_pdf_admin.xml
View view = LayoutInflater.from(context).inflate(R.layout.row_pdf_home,parent,false);
return new HolderPdfAdmin(view);
}
#Override
public void onBindViewHolder(#NonNull AdapterPdfHome.HolderPdfAdmin holder, int position) {
/*Get data, Set Data, handle clicks, etc.*/
//get data
ModelPdf model = pdfArrayList.get(position);
String title = model.getTitle();
String author = model.getAuthor();
Log.d(TAG, "onBindViewHolder: "+title);
//set data
holder.titleTv.setText(title);
holder.authorTv.setText(author);
Glide.with(context)
.load(model.getCoverPageUrl())
.placeholder(R.drawable.back01)
.into(holder.pdfIv);
}
#Override
public int getItemCount() {
//return size of arrayList
return pdfArrayList.size();
}
/*view holder class for row_pdf_user.xml*/
class HolderPdfAdmin extends RecyclerView.ViewHolder {
//UI views of row_pdf_admin.xml
TextView titleTv, authorTv;
ImageView pdfIv;
public HolderPdfAdmin(#NonNull View itemView) {
super(itemView);
//init ui views
titleTv = itemView.findViewById(R.id.titleTv);
authorTv = itemView.findViewById(R.id.authorTv);
pdfIv = itemView.findViewById(R.id.pdfIv);
}
}
}
move "private AdapterPdfHome adapterPdfHome;" to "onBindViewHolder"

About opening a new activity in respond to a click on a RecyclerView item which is inside of a fragment

I'm loading some data into a RecyclerView from Firebase Realtime Database. This RecyclerView is in a fragment and I want to open a new activity when an item is clicked. But when i add the onClickListener to an item from the adapter, my click doesn't even recognized by the app. I'm not sure what I'm doing wrong here because this method worked fine for a RecyclerView when it is inside of a normal activity.
This is a project for my university and I should submit it tomorrow. So I can really use some help.
This is the my data Adapter class,
public class Adapter_NoLimit extends RecyclerView.Adapter<Adapter_NoLimit.LViewHolder> {
Context context;
ArrayList<Helper> list_nl;
public Adapter_NoLimit(Context context, ArrayList<Helper> list_nl) {
this.context = context;
this.list_nl = list_nl;
}
#NonNull
#Override
public Adapter_NoLimit.LViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.itemlist, parent, false);
return new LViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull Adapter_NoLimit.LViewHolder holder, int position) {
//final Helper temp = list_nl.get(position);
String fname_txt = list_nl.get(position).getFname();
String catg_txt = list_nl.get(position).getSpin();
String prof_img = list_nl.get(position).getProfile_url();
holder.setUsers(fname_txt, catg_txt, prof_img);
holder.f_name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity activity = (AppCompatActivity) v.getContext();
Intent i = new Intent(activity, UserProfile_VV.class);
i.putExtra("full name", fname_txt);
activity.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return list_nl.size();
}
public class LViewHolder extends RecyclerView.ViewHolder{
private TextView f_name, catG;
private ImageView profile_pic;
public LViewHolder(#NonNull View itemView) {
super(itemView);
f_name = itemView.findViewById(R.id.username_view);
catG = itemView.findViewById(R.id.category_view);
profile_pic = itemView.findViewById(R.id.userimage);
}
public void setUsers(String fname_txt, String catg_txt, String prof_img) {
f_name.setText(fname_txt);
catG.setText(catg_txt);
Picasso.get().load(prof_img).fit().into(profile_pic);
}
}
}
This is one of fragments,
public class Beauty_Frag extends Fragment {
RecyclerView recyclerView;
DatabaseReference reference, user_ref;
ArrayList<Helper> list;
Adapter adapter;
FirebaseAuth auth;
String uid;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_beauty, container, false);
recyclerView = v.findViewById(R.id.beauty_recycler_frag);
reference = FirebaseDatabase.getInstance().getReference();
user_ref = reference.child("users");
auth = FirebaseAuth.getInstance();
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
//searchField = findViewById(R.id.search_field);
list = new ArrayList<>();
adapter = new Adapter(getContext(), list);
recyclerView.setAdapter(adapter);
user_ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull /*#org.jetbrains.annotations.NotNull*/ DataSnapshot snapshot) {
for (DataSnapshot key : snapshot.getChildren()) {
if( key.child("spin").getValue().toString().equals("Beauty")) {
Helper helper = key.getValue(Helper.class);
list.add(helper);
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onCancelled(#NonNull /*#org.jetbrains.annotations.NotNull*/ DatabaseError error) {
}
});
return v;
}
}
You are very welcome if you have any solution.
Use below code for onClicklistner:
holder.f_name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context, UserProfile_VV.class);
i.putExtra("full name", fname_txt);
context.startActivity(i);
}
});

How do I show info from two different models / adapters in one recyclerview

I have two Models (ModelChat and ModelUsers) and their class adapters (PostsAdapter and AllUsersAdapter).
I want to get and set user info such as name and email from the ModelUser and get and set post information from the ModelPost from Firebase database into the same recyclerview in my HomeActivity.
The codes are as shown below:
PostsAdapter.java
public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.MyHolder>{
Context context;
List<ModelPost> postList;
public PostsAdapter(Context context, List<ModelPost> postList) {
this.context = context;
this.postList = postList;
}
#NonNull
#Override
public MyHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//inflate layout row_post.xml
View view = LayoutInflater.from(context).inflate(R.layout.row_posts, parent, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyHolder holder, int position) {
//get data
String userUID = postList.get(position).getUserUID();
String userEmail = postList.get(position).getUserEmail();
String userProfilePic = postList.get(position).getUserProfilePic();
String firstName = postList.get(position).getUserFirstName();
String lastName = postList.get(position).getUserLastName();
String userNickName = postList.get(position).getUserNickName();
String postTimeStamp = postList.get(position).getPostTime();
String userPost = postList.get(position).getUserPost();
//set data
//set data
Glide
.with(context)
.load(userProfilePic)
.apply(RequestOptions.circleCropTransform())
.into(holder.avatarTv);
holder.firstnameTv.setText(firstName);
holder.lastnameTv.setText(lastName);
holder.nicknameTv.setText(userNickName);
}
#Override
public int getItemCount() {
return postList.size();
}
//view holder class
class MyHolder extends RecyclerView.ViewHolder {
//views from row_posts layout
public MyHolder(#NonNull View itemView) {
super(itemView);
//init view
//my views here
}
}
}
AllUsersAdapter.java
public class AllUsersAdapter extends RecyclerView.Adapter<AllUsersAdapter.MyHolder>{
Context context;
List<ModelUser> userList;
//Constructor > Generate
public AllUsersAdapter(Context context, List<ModelUser> userList) {
this.context = context;
this.userList = userList;
}
#NonNull
#Override
public MyHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//Inflate layout (row_user)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_all_users, parent, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyHolder holder, int position) {
//get data
String userUID = userList.get(position).getUid();
String userProfilePic = userList.get(position).getProfilepic();
String userName = userList.get(position).getFirstname() + " " + userList.get(position).getLastname();
String userNickname = userList.get(position).getNickname();
String userStatus = userList.get(position).getStatus();
//set data
Glide
.with(context)
.load(userProfilePic)
.apply(RequestOptions.circleCropTransform())
.into(holder.mAvatarIv);
holder.mNameTv.setText(userName);
holder.mNicknameTv.setText(userNickname);
holder.mStatusTv.setText(userStatus);
//Handle item click
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Click user from user list to start conversation
*Start Activity by putting UID of receiver
*we will use that UID to identify the user we are gonna chat */
Intent intent = new Intent(context, MessageActivity.class);
intent.putExtra("userUid", userUID);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return userList.size();
}
class MyHolder extends RecyclerView.ViewHolder {
public MyHolder(#NonNull View itemView) {
super(itemView);
//init my views here
}
}
}
HomeActivity.java
public class HomeActivity extends AppCompatActivity {
FirebaseAuth firebaseAuth;
RecyclerView recyclerView;
List<ModelPost> postList;
PostsAdapter postsAdapter;
String mUID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
firebaseAuth = FirebaseAuth.getInstance();
//recyclerview and its properties
recyclerView = findViewById(R.id.posts_recyclerview);
//init post list
postList = new ArrayList<>();
loadPosts();
}
private void loadPosts() {
//path of all posts
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
//get all data from this reference
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
postList.clear();
for (DataSnapshot ds: snapshot.getChildren()) {
ModelPost modelPost = ds.getValue(ModelPost.class);
postList.add(modelPost);
//adapter
postsAdapter = new PostsAdapter(HomeActivity.this, postList);
//set adapter to recyclerview
recyclerView.setAdapter(postsAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
//in case of errors
//Toast.makeText(HomeActivity.this, ""+error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
Try using ConcatAdapter.
An RecyclerView.Adapter implementation that presents the contents of multiple adapters in sequence. More info
Concatenate adapters sequentially with ConcatAdapter:
https://medium.com/androiddevelopers/merge-adapters-sequentially-with-mergeadapter-294d2942127a
I think this will help
MyAdapter adapter1 = ...;
AnotherAdapter adapter2 = ...;
ConcatAdapter concatenated = new ConcatAdapter(adapter1, adapter2);
recyclerView.setAdapter(concatenated);

DiffUtil with Async callback only displays list once and doesn't update

I am using DiffUtil async callback to update my list.
The problem is that it only displays the dataset once, at the first call. Later, when the dataset updates, the list only displays the items that were initially displayed. So the problem is that the dataset updates, but the list is stuck on its first state.(With the items that were initially created)
The dataset is being updated via a button click initiated by the user, this is how it looks:
private void updateUsersList() {
#Override
public void onResponse(JSONArray response) { // the JSON ARRAY response of user ids ["uid1", "uid334", "uid1123"]
for (int i = 0; i < response.length(); i++) {
try {
String userKey = response.get(i).toString(); // the currently iterated user id
final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userKeyRef = rootRef.child("users").child(userKey); // reference to currently iterated user
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
myDataset.add(new User(dataSnapshot.getKey(), dataSnapshot.child("imageUrl").getValue().toString())); //add new user: id and image url
mAdapter.updateList(myDataset);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
userKeyRef.addListenerForSingleValueEvent(listener);
}
catch (JSONException e) { Log.d(TAG, "message " + e); }
}
}
And this is my adapter using async DiffUtil:
public class MyAdapter extends RecyclerView.Adapter {
private AsyncListDiffer<User> mAsyncListDiffer;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public ImageView singleItemImage;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemImage = (ImageView) v.findViewById(R.id.icon);
singleItemTextView = (TextView) v.findViewById(R.id.singleitemtv);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.nbConstraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter() {
DiffUtil.ItemCallback<User> diffUtilCallback = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.getUserId().equals(oldUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.equals(oldUser);
}
};
mAsyncListDiffer = new AsyncListDiffer<>(this, diffUtilCallback);
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.nb_image_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
User user = mAsyncListDiffer.getCurrentList().get(position);
Uri userImage = user.getImageUrl();
Log.d("test123", "user uri: " + userImage.toString());
holder.singleItemTextView.setText(user.getUserId());
Glide.with(holder.itemView.getContext() /* context */)
.load(userImage)
.into(holder.singleItemImage);
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), DisplayUserActivity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mAsyncListDiffer.getCurrentList().size();
}
public void updateList(ArrayList<User> newList) {
mAsyncListDiffer.submitList(newList);
}
}
So why does my dataset update, but the list is stuck on first update only?

When/How to declare recyclerView adapter while waiting for database to be fetched from Firebase

I'll appreciate if anyone can help me with this.
So what's happening is the Adapter is being declared before the SenderNames Array List is fetched from Firebase Database.So how do I wait for the SenderNames to be fetched first from database and then display them?
Tab 2 code
public class Tab2 extends Fragment {
private static RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private static RecyclerView recyclerView;
private static ArrayList<String> reminderMessages;
protected static ArrayList<String> senderNames;
String receiverUID;
private DatabaseReference mDatabase;
int i =0;
private Button profile;
//Overriden method onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
View v =inflater.inflate(R.layout.tab2, container, false);
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
reminderMessages = new ArrayList<>();
receiverUID = user.getUid();
mDatabase = FirebaseDatabase.getInstance().getReference();
Query query = mDatabase.child("reminders").orderByChild("receiverUID").equalTo(receiverUID);
//Setting size of recycler view as constant
recyclerView = (RecyclerView) v.findViewById(R.id.my_recycler_view2);
recyclerView.setHasFixedSize(true);
//Setting Linear Layout
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
senderNames = new ArrayList<>();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
//Getting corresponding username of the ReceiverUID
//Getting senderUID
String sUID = ds.child("senderUID").getValue(String.class);
//Getting senders Name
GetSenderName getName = new GetSenderName();
getName.GetSenderssName(sUID);
//Getting message from database
String message = ds.child("reminderMessage").getValue(String.class);
//Adding database to ArrayList
reminderMessages.add(message);
//Getting corresponding username of the ReceiverUID
// Log.d("String names", receiverNames.toString());
}
adapter = new DataAdapter(reminderMessages,senderNames);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Error in Reaching Database
Toast.makeText(getContext(), "Something went Wrong!", Toast.LENGTH_SHORT).show();
}
});
return v;
}
GetSenderName Class
import static com.example.admin.import2.Tab2.senderNames;
public class GetSenderName {private FirebaseAuth auth;
ListView listView;
private DatabaseReference mDatabase;
private String senderName;
public void GetSenderssName(String UID){
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
//Running a query to find matching UID
Query query = mDatabase.orderByKey().equalTo(UID);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot2) {
// Getting user name with matching UID
for (DataSnapshot users : dataSnapshot2.getChildren()) {
senderName = users.child("username").getValue(String.class);
senderNames.add(senderName);
Log.d("sendername retrieved",senderNames.toString());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
DataAdapter Class
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<String> reminderMessage;
private ArrayList<String> receiverName;
public DataAdapter(ArrayList<String> reminderMessage,ArrayList<String> receiverName) {
this.reminderMessage = reminderMessage;
this.receiverName = receiverName;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup,int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cards_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
viewHolder.reminderText.setText(reminderMessage.get(i));
viewHolder.receiverName.setText(receiverName.get(i));
}
#Override
public int getItemCount() {
return reminderMessage.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView reminderText;
private TextView receiverName;
public ViewHolder(View view) {
super(view);
reminderText = (TextView)view.findViewById(R.id.remindertext);
receiverName = (TextView)view.findViewById(R.id.receiverName);
}
}
}
To avoid problems like populate a list before the databases values are fetched, you should use a FirebaseRecyclerAdapter available in firebaseUI library.
It work in asynchronously so you dont need to do nothing. Just set up the recyclerview, the adapter and the query.
Take a look at the official repository
FirebaseUI
Instead of sending the data in constructor you can create some setter method to set the data and update the list,
Remove the arguments in Adapter constructor
Initialize the ArrayList while declaring as a global variable.
Create a setter method to set the data,
If you do your Adapter will be like this,
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<String> reminderMessage = new ArrayList<>();
private ArrayList<String> receiverName = new ArrayList<>();
public DataAdapter(ArrayList<String> reminderMessage, ArrayList<String> receiverName) {
this.reminderMessage = reminderMessage;
this.receiverName = receiverName;
}
public void setData(ArrayList<String> reminderMessage, ArrayList<String> receiverName) {
if(reminderMessage == null || receiverName != null) {
return;
}
this.reminderMessage.clear();
this.receiverName.clear();
this.reminderMessage.addAll(reminderMessage);
this.receiverName.addAll(receiverName);
notifyDataSetChanged();
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cards_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
viewHolder.reminderText.setText(reminderMessage.get(i));
viewHolder.receiverName.setText(receiverName.get(i));
}
#Override
public int getItemCount() {
return reminderMessage.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView reminderText;
private TextView receiverName;
public ViewHolder(View view) {
super(view);
reminderText = (TextView) view.findViewById(R.id.remindertext);
receiverName = (TextView) view.findViewById(R.id.receiverName);
}
}
}
so from your activity you can call like this, adapter.setData(reminderMessages,senderNames); so that you can create the adapter and set in Recycle View before get the data from server.

Categories

Resources