Creating chatapp using FirebaseRecyclerPagination - android

I'am trying to create a chat app using Firebase as database. I want to implement FirebaseRecyclerPagination because I don't want to load all the chat right away I want it to load by a certain number only per refresh. I'm following this tutorial [Sample App Using Firebase Recycler Pagination Library]
(https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md). But still not getting the result I wanted.
Here is my current code
public class ChatTestActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private DatabaseReference mDatabase;
private SwipeRefreshLayout mSwipeRefreshLayout;
RecyclerView.LayoutManager layoutManager;
FirebaseRecyclerPagingAdapter<ChatMessage, PostViewHolder> mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_test);
mSwipeRefreshLayout = findViewById(R.id.swipe_refresh_layout);
//Initialize RecyclerView
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
//Initialize Database
mDatabase = FirebaseDatabase.getInstance().getReference().child("conversations").child("message");
final PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setInitialLoadSizeHint(2)
.setPrefetchDistance(2)
.setPageSize(2)
.build();
final DatabasePagingOptions<ChatMessage> options = new DatabasePagingOptions.Builder<ChatMessage>()
.setLifecycleOwner(this)
.setQuery(mDatabase, config, ChatMessage.class)
.build();
mAdapter = new FirebaseRecyclerPagingAdapter<ChatMessage, PostViewHolder>(options) {
#NonNull
#Override
public PostViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new PostViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_message, parent, false));
}
#Override
protected void onBindViewHolder(#NonNull PostViewHolder holder,
int position,
#NonNull ChatMessage model) {
holder.setItem(model);
}
#Override
protected void onLoadingStateChanged(#NonNull LoadingState state) {
switch (state) {
case LOADING_INITIAL:
case LOADING_MORE:
// Do your loading animation
mSwipeRefreshLayout.setRefreshing(true);
break;
case LOADED:
// Stop Animation
mSwipeRefreshLayout.setRefreshing(false);
break;
case FINISHED:
//Reached end of Data set
mSwipeRefreshLayout.setRefreshing(false);
break;
case ERROR:
retry();
break;
}
}
#Override
protected void onError(#NonNull DatabaseError databaseError) {
super.onError(databaseError);
mSwipeRefreshLayout.setRefreshing(false);
databaseError.toException().printStackTrace();
}
};
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mAdapter.refresh();
}
});
mRecyclerView.setAdapter(mAdapter);
}
//Start Listening Adapter
#Override
protected void onStart() {
super.onStart();
mAdapter.startListening();
}
//Stop Listening Adapter
#Override
protected void onStop() {
super.onStop();
mAdapter.stopListening();
}
public class PostViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView msgMessage;
public final TextView user;
TextView mAuthor;
TextView mDate;
public ChatMessage mItem;
public PostViewHolder(View view) {
super(view);
mView = view;
msgMessage = (TextView) view.findViewById(R.id.msgMessage);
user = (TextView) view.findViewById(R.id.user);
}
public void setItem(ChatMessage chatMessage){
msgMessage.setText(chatMessage.messageText);
user.setText(chatMessage.messageUser);
}
public TextView getMsgMessage() {
return msgMessage;
}
#Override
public String toString() {
return super.toString() + " '" + user.getText() + "'";
}
}
}
Here is my activity_chat_test.xml file
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout 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:id="#+id/swipe_refresh_layout"
tools:context=".ChatTestActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/recycler_view">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

Related

Problem with Recycler view in android studio - Only appearing occasionally

I`ve followed a tutorial to create a recyclerview for my app
I doesnt work, in that it only occasionally shows anything in the view
There doesnt appear to be any rime or reason at all...
The layout that is recycled
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:id="#+id/text_value"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Test"
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout>
The xml with the recyclerview in it
<?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="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycler_view_accounts"/>
</LinearLayout>
The RecyclerViewAdapter class
public class RecyclerViewAdapterAccounts extends RecyclerView.Adapter<RecyclerViewAdapterAccounts.ViewHolder> {
private ArrayList<String> mlist;
private Context mContext;
public RecyclerViewAdapterAccounts(ArrayList<String> list, Context context) {
mlist = list;
mContext = context;
}
#NonNull
#Override
public RecyclerViewAdapterAccounts.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewAdapterAccounts.ViewHolder holder, final int position) {
holder.accountName.setText(mlist.get(position));
holder.parent_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext, mlist.get(position), Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return mlist.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView accountName;
LinearLayout parent_layout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
accountName = itemView.findViewById(R.id.text_value);
parent_layout = itemView.findViewById(R.id.parent_layout);
}
}
}
The relevant onCreate activity
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_accounts);
initAccounts();
RecyclerView recyclerView = findViewById(R.id.recycler_view_accounts);
RecyclerViewAdapterAccounts adapter = new RecyclerViewAdapterAccounts(accounts, this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter.notifyDataSetChanged();
}
Although not shown, I can test that initAccounts() is filling the array as it should
I can also see that onCreateViewHolder and onBindViewHolder is not being called
Any suggestions???
edit:
heres the initAccounts
private void initAccounts() {
DatabaseReference userRef =
FirebaseDatabase.getInstance().getReference().child("users");
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
Iterator<DataSnapshot> children = snapshot.getChildren().iterator();
while (children.hasNext()) {
DataSnapshot child = children.next();
String[] parts = child.getValue().toString().split(",");
String role = parts[0].replace('{', ' ');
String msg = child.getKey() + ": " + role;
accounts.add(msg);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
The problem here is you are adding object to accounts but not notifying the Adapter about the change . Make the following changes to your code .
For setting adapter inside onCreate() use Only .
private RecyclerViewAdapterAccounts adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_accounts);
initAccounts();
RecyclerView recyclerView = findViewById(R.id.recycler_view_accounts);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new RecyclerViewAdapterAccounts(accounts, this);
recyclerView.setAdapter(adapter);
}
Now create a method in RecyclerViewAdapterAccounts to add elements in adapter ;
public void addAll(ArratList<String> list){
mlist.clear();// To clear list if thats the case
mlist.addAll(list);
notifyDataSetChanged();
}
Now you can add all elements in one go to adapter .
public void onDataChange(#NonNull DataSnapshot snapshot) {
ArrayList<String> dataList=new ArrayList<>();
Iterator<DataSnapshot> children = snapshot.getChildren().iterator();
while (children.hasNext()) {
DataSnapshot child = children.next();
String[] parts = child.getValue().toString().split(",");
String role = parts[0].replace('{', ' ');
String msg = child.getKey() + ": " + role;
dataList.add(msg);
}
adapter.addAll(dataList);
}

Not getting total item count from recyclerview

I want to display "No upcoming Appointments" when my recyclerview is empty and display recyclerview when it's not empty. I have tried various codes to check whether my recyclerview is empty or not, but none worked.
Here is my code
public class appointments extends Fragment {
private RecyclerView recyclerView;
private DatabaseReference ref;
private ArrayList<BookedUserInfo> arrayList;
private FirebaseRecyclerOptions<BookedUserInfo> options;
private FirebaseAuth mAuth;
private String uid;
private FirebaseRecyclerAdapter<BookedUserInfo, FireBaseViewHolderUpcomingAppointment> adapter;
private String shopname;
private ProgressDialog progressDialog;
private TextView emptyview;
private int x=0;
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View RootView = inflater.inflate(R.layout.appointment_navigation,container,false);
//find view by ID
recyclerView = (RecyclerView) RootView.findViewById(R.id.recycleupcomingappointment);
emptyview = (TextView) RootView.findViewById(R.id.empty_view);
//Auth instance
mAuth = FirebaseAuth.getInstance();
FirebaseUser currentuser = mAuth.getCurrentUser();
uid = currentuser.getUid();
//initialize progress dialog
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Loading");
progressDialog.show();
//database refrence
ref = FirebaseDatabase.getInstance().getReference().child("USER").child(uid).child("UpcomingAppointment");
ref.keepSynced(true);
//recycler view
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(llm);
//array list
arrayList = new ArrayList<BookedUserInfo>();
options = new FirebaseRecyclerOptions.Builder<BookedUserInfo>().setQuery(ref,BookedUserInfo.class).build();
//adapter
adapter = new FirebaseRecyclerAdapter<BookedUserInfo, FireBaseViewHolderUpcomingAppointment>(options) {
#Override
protected void onBindViewHolder(#NonNull final FireBaseViewHolderUpcomingAppointment holder, int position, #NonNull final BookedUserInfo model) {
final String datedata = model.getDate();
final String timedata = model.getTime();
final int bookingiddata = model.getBookingid();
Date initDate = null;
try {
initDate = new SimpleDateFormat("dd-MM-yyyy").parse(datedata);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy");
final String parsedDate = formatter.format(initDate);
holder.time.setText(timedata);
holder.date.setText(parsedDate);
holder.id.setText(String.valueOf(bookingiddata));
final String shopuid = model.getShopuid();
DatabaseReference myRef =FirebaseDatabase.getInstance().getReference().child("SHOP").child(shopuid);
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
shopname = dataSnapshot.child("shopname").getValue().toString();
holder.name.setText(shopname);
progressDialog.dismiss();
}
#Override
public void onCancelled(DatabaseError error) {
progressDialog.dismiss();
// Failed to read value
}
});
progressDialog.dismiss();
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), AppointmentBill.class);
intent.putExtra("bookingid",String.valueOf(bookingiddata));
intent.putExtra("timetext",timedata);
intent.putExtra("datetext",datedata);
intent.putExtra("uidtext",shopuid);
intent.putExtra("appointmentinfotext",model.getAppointmentinfo());
startActivity(intent);
}
});
}
#NonNull
#Override
public FireBaseViewHolderUpcomingAppointment onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new FireBaseViewHolderUpcomingAppointment(LayoutInflater.from(getActivity()).inflate(R.layout.cardview_appointment,parent,false));
}
};
recyclerView.setAdapter(adapter);
//check total items
if(adapter.getItemCount() == 0)
{
recyclerView.setVisibility(View.GONE);
emptyview.setVisibility(View.VISIBLE);
}
else
{
recyclerView.setVisibility(View.VISIBLE);
emptyview.setVisibility(View.GONE);
}
progressDialog.dismiss();
return RootView;
}
XML code
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/relativelayoutview"
android:layout_below="#id/upcomingappointments">
<TextView
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="30dp"
android:visibility="gone"
android:background="#E7E7E7"
android:paddingBottom="30dp"
android:text="---------No Upcoming Appointments---------"
android:gravity="center">
</TextView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycleupcomingappointment"
android:layout_width="match_parent"
android:background="#E7E7E7"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
I'm using google firebase(realtime database) to get appointment details. Please suggest me a solution for this problem.
I also tried this but failed so I instead used snapshot.getchilderncount In my firebase database reference and checked if childrencount =0 or not
Create a value event listener For your apointment database reference and in it say if(snapshot.getChildrenCount==0) { ///your logic }
Try to move this logic inside onDataChange callback method:
//check total items
if(adapter.getItemCount() == 0)
{
recyclerView.setVisibility(View.GONE);
emptyview.setVisibility(View.VISIBLE);
}
else
{
recyclerView.setVisibility(View.VISIBLE);
emptyview.setVisibility(View.GONE);
}
this is a sample recyclerView app
Adapter.java
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
List<?> list; //i don`t know your model or type date then i write (?)
public Adapter(List<?> list) {
this.list = list;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.your_layout,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//you write your code when bind your view hoder
YourMode model = list.get(position);
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(#NonNull View itemView) {
super(itemView);
//for get your view or widget your use **itemView.findViewById()**
}
}
}
and this code for get Item count :
public class MyFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_fragment_layout, container,false);
Adapter adapter = Adapter(yourList);
if (adapter.getItemCount() == 0){
}else {
}
return view;
}
}

FirebaseRecyclerAdapter working for API 21 but not working with oreo or nougat

public class AllUsersActivity extends AppCompatActivity {
private Toolbar mToolbar;
private RecyclerView mUserRecycler;
private DatabaseReference mAllUsersDatabase;
private DatabaseReference mUserRef;
private FirebaseAuth mAuth;
private FirebaseUser mCurrentUser;
FirebaseRecyclerAdapter<Users, AllUsersViewHolder> firebaseRecyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_users);
mToolbar = (Toolbar) findViewById(R.id.users_app_bar);
setSupportActionBar(mToolbar);
getSupportActionBar().setTitle("All Users");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mAuth = FirebaseAuth.getInstance();
mCurrentUser = mAuth.getCurrentUser();
mUserRef = FirebaseDatabase.getInstance().getReference().child("Users").child(mAuth.getCurrentUser().getUid());
mAllUsersDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
mAllUsersDatabase.keepSynced(true);
Log.i(TAG, "Toolbar DOne");
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
mUserRecycler = (RecyclerView) findViewById(R.id.allusers_recycler_view);
mUserRecycler.setHasFixedSize(true);
mUserRecycler.setLayoutManager(linearLayoutManager);
}
#Override
protected void onStart() {
super.onStart();
mUserRef.child("online").setValue("true");
FirebaseRecyclerOptions personsOptions = new FirebaseRecyclerOptions.Builder<Users>()
.setQuery(mAllUsersDatabase, Users.class).build();
Log.i(TAG, "onStart - ");
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, AllUsersViewHolder>(personsOptions) {
#NonNull
#Override
public AllUsersViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.allusers_single, parent, false);
Log.i(TAG, "Create VIewHolder ");
return new AllUsersViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull AllUsersViewHolder holder, int position,
#NonNull final Users model) {
Log.i(TAG, "onBindVIewHolder - " + model.getName());
holder.setDisplayName(model.getName());
holder.setUserImage(model.getThumb_image(), getApplicationContext());
final String user_id = getRef(position).getKey();
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent chat_intent = new Intent(AllUsersActivity.this, ChatActivity.class);
chat_intent.putExtra("user_id", user_id);
chat_intent.putExtra("user_name", model.getName());
startActivity(chat_intent);
}
});
}
};
mUserRecycler.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
if (mCurrentUser != null) {
mUserRef.child("online").setValue(ServerValue.TIMESTAMP);
}
firebaseRecyclerAdapter.stopListening();
}
public static class AllUsersViewHolder extends RecyclerView.ViewHolder {
public View mView;
public AllUsersViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setDisplayName(String a) {
TextView userName = (TextView) mView.findViewById(R.id.allusers_name);
userName.setText(a);
}
public void setUserImage(String thumb_image, Context ct) {
CircleImageView userImageView = (CircleImageView) mView.findViewById(R.id.allusers_image);
Picasso.get().load(thumb_image).placeholder(R.drawable.user).into(userImageView);
}
}
The problem is I am getting the data from Firebase and its showing on screen in API 21 i.e. lollipop but with oreo and nougat nothing loads on to the screen and I can see the data in logs. What is wrong with the code? Please help.
I am retrieving the list of all users from Firebase and using the Firebase UI database. Using Firebase 16.0.0
Resource Link
https://github.com/firebase/FirebaseUI-Android/tree/master/database
this works on android 7 just look the difference between our codes and change the parameters
private RecyclerView usersList;
private DatabaseReference usersDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("Users List");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
usersDatabase = FirebaseDatabase.getInstance().getReference().child("locations");
usersList = findViewById(R.id.usersList);
usersList.setHasFixedSize(true);
usersList.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
usersList.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Users, UsersViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, UsersViewHolder>(
Users.class,
R.layout.user_list,
UsersViewHolder.class,
usersDatabase
) {
#Override
protected void populateViewHolder(final UsersViewHolder usersViewHolder, Users users, final int position) {
String str = getRef(position).getKey();
String newName = str.replace(" ", ".");
usersViewHolder.setDisplayName(newName);
final String user_id = getRef(position).getKey();
usersViewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, UserActivity.class);
intent.putExtra("user_id", user_id);
startActivity(intent);
}
});
}
};
usersList.setAdapter(firebaseRecyclerAdapter);
}
#SuppressWarnings("WeakerAccess")
public static class UsersViewHolder extends RecyclerView.ViewHolder {
View mView;
public UsersViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setDisplayName(String name) {
TextView userNameView = mView.findViewById(R.id.userName);
userNameView.setText(name);
}
public void setDisplayStatus(String status) {
TextView statusView = mView.findViewById(R.id.userStatus);
if (status.equals("offline")) {
statusView.setText("offline");
statusView.setTextColor(Color.RED);
} else {
statusView.setText(status);
statusView.setTextColor(Color.GREEN);
}
}
}
and this is the activity_main.xml
<LinearLayout
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"
android:orientation="vertical"
tools:context="com.example.mike.mapfirebasedisplay.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/usersList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp" />
and this is the user list that you are free to change it .....!
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp">
<TextView
android:id="#+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="#string/name"
android:textColor="#android:color/black"
android:textSize="18sp" />
</RelativeLayout>

Android - FirebaseUI sometimes not showing RecyclerView

I have a fragment called HomeFragment inside an activity called MainActivity that using RecyclerView to load the data from Firebase. And when I clicked the RecyclerView, it will open a new activity called ItemActivity.
The problem is sometimes the RecyclerView does not load anything when it opened the new activity.
For example, I clicked the RecyclerView in the HomeFragment, the new ItemActivity will start but without any RecyclerView, and after I closed it and reopen it again, the RecyclerView is showing. This happened on a random occasion, sometimes it loads and sometimes it does not load the RecyclerView.
And whenever I put adapter.stopListening(), the RecyclerView never show up in the ItemActivity.
HomeFragment
public class HomeFragment extends Fragment {
private OnFragmentInteractionListener mListener;
FirebaseDatabase database;
DatabaseReference category;
FirebaseRecyclerAdapter adapter;
TextView txtUsername;
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
public HomeFragment() {
// Required empty public constructor
}
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = FirebaseDatabase.getInstance();
category = database.getReference("Category");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container,false);
// set name for user
String username = Common.currentUser.getEmail();
StringTokenizer tokens = new StringTokenizer(username, "#");
String first = tokens.nextToken();// this will contain string before #
// set name for user
txtUsername = (TextView) view.findViewById(R.id.textUsername);
txtUsername.setText(first);
// load category
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerViewCategory);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
loadMenu();
return view;
}
private void loadMenu(){
Query query = FirebaseDatabase
.getInstance()
.getReference()
.child("Category");
FirebaseRecyclerOptions<Category> options =
new FirebaseRecyclerOptions.Builder<Category>()
.setQuery(query, Category.class)
.build();
adapter = new FirebaseRecyclerAdapter<Category, CategoryViewHolder>(options) {
#Override
public CategoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(getActivity())
.inflate(R.layout.category_item, parent, false);
return new CategoryViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull CategoryViewHolder holder, int position, #NonNull Category model) {
holder.txtMenuName.setText(model.getName());
Picasso.with(getActivity()).load(model.getImage())
.into(holder.imageView);
final Category clickItem = model;
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
// get category id and send to new activity
Intent intent = new Intent(getActivity(), ItemActivity.class);
// get category id to filter
intent.putExtra("CategoryId",adapter.getRef(position).getKey());
startActivity(intent);
}
});
}
};
recyclerView.setAdapter(adapter);
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onStop() {
super.onStop();
//adapter.stopListening();
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
//Toast.makeText(context, "Home Fragment Attached", Toast.LENGTH_SHORT).show();
}
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
ItemActivity
public class ItemActivity extends AppCompatActivity {
ImageView imageView;
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
FirebaseDatabase database;
DatabaseReference itemList;
String categoryId;
public FirebaseRecyclerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
// Firebase
database= FirebaseDatabase.getInstance();
itemList = database.getReference("Item");
recyclerView = (RecyclerView) findViewById(R.id.recyclerViewItem);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
// get intent
if (getIntent() != null) {
categoryId = getIntent().getStringExtra("CategoryId");
}
if(!categoryId.isEmpty() && categoryId != null) {
loadListItem(categoryId);
}
}
private void loadListItem(String categoryId) {
Query query = itemList.orderByChild("CategoryId").equalTo(categoryId);
FirebaseRecyclerOptions<Item> options =
new FirebaseRecyclerOptions.Builder<Item>()
.setQuery(query, Item.class)
.build();
adapter = new FirebaseRecyclerAdapter<Item, ItemViewHolder>(options) {
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.product_item, parent, false);
return new ItemViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull ItemViewHolder holder, int position, #NonNull Item model) {
holder.itemTitle.setText(model.getName());
holder.itemUsername.setText(model.getUsername());
holder.itemPrice.setText(model.getPrice());
holder.itemDescription.setText(model.getDescription());
holder.itemPhone.setText(model.getPhone());
holder.itemDate.setText(model.getDate());
holder.itemQuality.setText(model.getQuality());
Picasso.with(getBaseContext()).load(model.getPicture())
.into(holder.itemImage);
final Item clickItem = model;
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
//
}
});
}
};
adapter.startListening();
recyclerView.setAdapter(adapter);
Toast.makeText(this, "" + categoryId, Toast.LENGTH_SHORT).show();
}
#Override
public void onStart() {
super.onStart();
//adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
//adapter.stopListening();
}
I found the problem.
Just remove recyclerView.setHasFixedSize(true);

RecyclerView inside nestedscrollview with bottom sheet behavior

I am making an app that displays post activities of different users like facebook. I have made postList Activity, in which username, his post image and post text will be displayed. Also want to implement like and comment feature in my app. On comment textview, bottomsheet will appear with list of comments of different users.
Problem is that i have used nestedscrollview with bottomsheet behavior. Inside nestedscroll view, there is recycler view.
here is my xml layout of bottomsheet
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_sheet1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:fillViewport="true"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="80dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/commentList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
This is Post List xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/post_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/addNewPost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
</ScrollView>
<include layout="#layout/bottom_sheet" />
This is postlist adapter
public class CustomAdapter extends RecyclerView.Adapter<ViewHolder> {
NestedScrollView bottom_sheet;
CoordinatorLayout mainLayout;
private BottomSheetBehavior mBottomSheetBehavior;
public CustomAdapter(Context context, ArrayList<Post> posts,NestedScrollView
bottom_sheet,CoordinatorLayout mainLayout) {
this.posts = posts;
this.context = context;
this.bottom_sheet=bottom_sheet;
this.mainLayout=mainLayout;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
mBottomSheetBehavior = BottomSheetBehavior.from(bottom_sheet);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
break;
case BottomSheetBehavior.STATE_EXPANDED: {
}
break;
case BottomSheetBehavior.STATE_COLLAPSED: {
}
break;
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_SETTLING:
break;
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
holder.comment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
});
}
#Override
public int getItemCount() {
return posts.size();
}
}
And this is the adapter for comments
public class CommentAdapter extends RecyclerView.Adapter<CommentViewHolder> {
Context context;
public CommentAdapter(Context context,ArrayList<Comment> comments) {
this.comments = comments;
this.context=context;
}
#Override
public CommentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.comment_layout, parent, false);
CommentViewHolder viewHolder = new CommentViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(CommentViewHolder holder, int position) {
firebaseDatabase = FirebaseDatabase.getInstance();
commentReference = firebaseDatabase.getReference().child("Comments");
mAuth = FirebaseAuth.getInstance();
uId = mAuth.getCurrentUser().getUid();
final Comment comment = comments.get(position);
holder.commentUName.setText("Numrah");
holder.commentText.setText("hello");
holder.addCommentBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "comment", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return comments.size();
}
}
PostList Activity
public class PostList extends AppCompatActivity {
RecyclerView recyclerView;
ArrayList<Post> posts;
CustomAdapter customAdapter;
FloatingActionButton addPost;
FirebaseDatabase firebaseDatabase;
DatabaseReference postReference;
DatabaseReference likeReference;
DatabaseReference commentReference;
NestedScrollView bottomSheet;
CoordinatorLayout mainLayout;
private BottomSheetBehavior mBottomSheetBehavior;
RecyclerView commentRecyclerView;
ArrayList<Comment> comments;
CommentAdapter commentAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_list);
bottomSheet = (NestedScrollView) findViewById(R.id.bottom_sheet1);
mainLayout = (CoordinatorLayout) findViewById(R.id.main_layout);
commentRecyclerView=bottomSheet.findViewById(R.id.commentList);
comments = new ArrayList<>();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
//layoutManager.setAutoMeasureEnabled(true);
commentRecyclerView.setLayoutManager(layoutManager);
commentRecyclerView.setNestedScrollingEnabled(false);
commentAdapter = new CommentAdapter(this, comments);
commentRecyclerView.setAdapter(commentAdapter);
firebaseDatabase = FirebaseDatabase.getInstance();
postReference = firebaseDatabase.getReference("Post");
likeReference = firebaseDatabase.getReference("Likes");
commentReference = firebaseDatabase.getReference("Comments");
posts = new ArrayList<>();
addPost = (FloatingActionButton) findViewById(R.id.addNewPost);
recyclerView = (RecyclerView) findViewById(R.id.post_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
customAdapter = new CustomAdapter(this, posts, bottomSheet, mainLayout);
recyclerView.setAdapter(customAdapter);
addPost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(PostList.this, AddPost.class));
}
});
postReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Post post = dataSnapshot.getValue(Post.class);
posts.add(post);
customAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Post post = dataSnapshot.getValue(Post.class);
int indexOfItem = posts.indexOf(post);
if (indexOfItem >= 0) {
posts.set(indexOfItem, post);
}
customAdapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onBackPressed() {
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED) {
super.onBackPressed();
} else {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
}
As your arraylist comments is empty ( comments.size() is 0 ) the getItemCount() of your CommentAdapter is returning 0 . Hence zero rows will be inflated and your recyclerView would be blank. So your test case wont be executed To execute your test case try this in your CommentAdapter :-
#Override
public int getItemCount() {
return 5; // returning static no of items
}

Categories

Resources