FirebaseRecyclerAdapter not updating data automatically - android

I am using FirebaseRecyclerAdapter that comes with FirebaseAndroid-UI library and I assume that when the data will change on Firebase it will automatically refresh and update the RecyclerView.
My code is simple:
Firebase firebasePicturesRef = new Firebase(FIREBASE_URL);
mAdapter = new FirebaseRecyclerAdapter<Image, ImageViewHolder>(
Image.class, R.layout.pictures_grid_item,
ImageViewHolder.class, firebasePicturesRef) {
#Override
protected void populateViewHolder(ImageViewHolder viewHolder, Image model, int position) {
super.populateViewHolder(viewHolder, model, position);
Glide.with(getActivity()).load(model.getThumbnailUrl()).into(viewHolder.mImageView);
}
};
I have also tried to manually refresh the adapter using notifyDatasetChanged in the the onDataChange method:
firebasePicturesRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (mAdapter != null)
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Am I doing something wrong? What is the fix?

I found the problem, i was calling mAdapter.cleanup(); in onStop() of the fragment. Removing it fixed the problem.
Instead of doing cleanup in onStop(); it should be called in onDestroy()
As suggested by Frank:
In general you should call cleanup() in the "opposite" method from where you create the adapter. So onCreate()<->onDestroy(), onStart()<->onStop(), onPause()<->onResume()

Related

Retrieve value of key from firebase database to listview

In my firebase database the date is the key value (node) which has its own children. How to retrieve the date into firebase adapter and show it in the listview? I am using the below code but the list is blank.
databaseReference = FirebaseDatabase.getInstance().getReference().child("Lectures").child(post_key);
FirebaseListOptions<String> options = new FirebaseListOptions.Builder<String>()
.setLayout(R.layout.subject_list_heading)
.setQuery(databaseReference, String.class)
.build();
adapter = new FirebaseListAdapter<String>(options) {
#Override
protected void populateView(View v, String model, int position) {
TextView subject_name = v.findViewById(R.id.tv_sub_heading);
subject_name.setText(model);
}
};
list_of_date.setAdapter(adapter);
This is the JSON object:
{
  "-LHSdSCzD_tZhzqvSOw_" : {
    "17-7-2018" : {
      "Absent" : "0",
      "Present" : "1",
      "Total_Lectures" : "1"
    }
I want to retrieve the date in the listview.
Any help is appreciated.
To solve this, please add the following lines of code in the onStart() and onStop() methods.
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if(adapter != null) {
adapter.stopListening();
}
}
So because you are using a listener, you need to start listen for changes. If you are interested, this is a recommended way in which you can retrieve data from a Firebase Realtime database and display it in a RecyclerView using FirebaseRecyclerAdapter.

Recyclerview is not displaying anything, any ideas? Using FirestoreUI RecyclerAdapter

The code Below I seem to have done everything needed, but the recyclerview is just not being populated.
I even put the Log on OnDateChange to see if it's called, and it was called once on the LogCat after I ran it on my Galaxy S6. Also, the database is public.
RecyclerView chat_view;
EditText message_text;
CollectionReference reference = FirebaseFirestore.getInstance().collection("stage2");
Query query = reference.orderBy("timestamp");
FirestoreRecyclerAdapter<ChatMessage,ChatHolder> adapter=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//initializing, called below
init();
}
private FirestoreRecyclerAdapter<ChatMessage,ChatHolder> newAdapter() {
final FirestoreRecyclerOptions options = new FirestoreRecyclerOptions.Builder<ChatMessage>()
.setQuery(query,ChatMessage.class)
.setLifecycleOwner(this)
.build();
return new FirestoreRecyclerAdapter<ChatMessage, ChatHolder>(options) {
#Override
public ChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item,parent,false);
//if(((ChatMessage)options.getSnapshots().getSnapshot(viewType)).)
return new ChatHolder(view);
}
#Override
protected void onBindViewHolder(ChatHolder holder, int position, ChatMessage model) {
//displaying the message and users into the recyclerview
holder.user_msg.setText(model.getMessage());
holder.user_date.setText(model.getDate());
holder.user_name.setText(model.getName());
}
#Override
public void onDataChanged() {
Log.d("TAG", "YESSIR");
}
#Override
public void onError(FirebaseFirestoreException e) {
super.onError(e);
}
};
}
private void init(){
chat_view = (RecyclerView) findViewById(R.id.chat_view);
chat_view.setVerticalScrollBarEnabled(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
chat_view.setLayoutManager(layoutManager);
adapter = newAdapter();
chat_view.setAdapter(adapter);
message_text = (EditText) findViewById(R.id.message_text);
message_text.setEnabled(appUtils.isSignedIn());
findViewById(R.id.send_button).setEnabled(appUtils.isSignedIn());
}
So, there we have it, I have no idea what the problem could be at this point. I am using the most recent Firestore UI dependency as well.
It seems that you have done everything necessary..using FirestoreRecycleroptions and inflating the layout in onCreateViewHolder.
For FirestoreRecyclerAdapter to be able to have the data on the activity, then you need to listen to any changes in onStart() which is after onCreate(). Also
in onStop you can stop listening.
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}

data show in RecycleView but when i want to count size of list show null (android)

I have a question about list. I have a list that save more than one data. and then, when I run my apps it work and show the data. but when I debug and want to check the size of my list just show 0 of size. what is the problem?
please help.
this is my code :
query.addValueEventListener(new com.firebase.client.ValueEventListener() {
#Override
public void onDataChange(com.firebase.client.DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (com.firebase.client.DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
SisaKendaraanModel sisaModel = postSnapshot.getValue(SisaKendaraanModel
if (//somecondition) {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
break;
}
} else {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
break;
}
}
}
} else {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
} else {
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
long sizeKendaraanModel = kendaraanModel.size(); // it show 0
adapter = new MenuHasilPencarianAdapter(MenuHasilPencarian.this, kendaraanModel, tanggalSewaPencarian, tanggalKembaliPencarian, jumlahKendaraanPencarian);
recyclerView.setAdapter(adapter);
This is my debug result:
See you are making asynchronous call addValueEventListener . your code below is going to call just after setting listener.
long sizeKendaraanModel = kendaraanModel.size();
So this will give you size 0 each time cause its called sequentially. The onDataChange not called yet cause its an Asynchronous call .
You can match this scenario the when we start and new thread and its runs in its own flow(the run() method) then we have to wait for response .
So what you can do is .
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
// Add remove your value here
}
long sizeKendaraanModel = kendaraanModel.size();
adapter = new MenuHasilPencarianAdapter(MenuHasilPencarian.this, kendaraanModel, tanggalSewaPencarian, tanggalKembaliPencarian, jumlahKendaraanPencarian);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Also in your code i am seeing lots of adapter.notifyDataSetChanged(); . If you are using recycler view notifyDataSetChanged() is most expensive in term of just notifying the the list for changes . So make Use of .
notifyItemRangeChanged()
notifyItemChanged()
notifyItemInserted()
notifyItemRemoved()
This is because You are adding value in "kendaraanModel" after Initializing Recycler
and after adding values in "kendaraanModel" , You have added > adapter.notifyDataSetChanged(); i.e affecting the list..
So,
if you want to check size You can check it in "OnDataChange"

android firebase reads all the database

i am trying to read a specific child in Firebase which i named Tags. the problem is, i just can't put the object from tags (dados.getValue) into a ArrayList to later populate in my ListView.
I know is simple, sorry about that, ut i am new here in android
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_taglist);
tags = new ArrayList<>();
tagList = (ListView) findViewById(R.id.tagsList);
tagsRefs = FirebaseConfig.getFireBase();
tagsRefs.child("tags").child("categorias");
tagsRefs.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dados : dataSnapshot.child("tags").getChildren()) {
System.out.println("tag EXTRAIDA NO taglist " + dados.getValue());
dados.getValue(); //HOW CAN I PUT THIS INTO AN ARRAY TO LATER ADD IN MY ArrayList tags??
String tagS = dados.getValue(String.class);
tags.addAll(tagS);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
tagAdapter = new ArrayAdapter(getBaseContext(), android.R.layout.simple_list_item_2,
android.R.id.text1,
tags);
tagList.setAdapter(tagAdapter);
tagList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedTag = (String) tagList.getItemAtPosition(position);
setSelectedTag(selectedTag);
}
});
}
here is my database:
h
This is happening because onDataChange() method is called asynchronously. This means that the statement that adds tags to your list is executed before onDataChange() method has been called. That's why your list is empty outside that method. So in order to use that lists, you need to use it inside the onDataChange().
For other approach, please visit this post and this post.
Hope it helps.

How to detect null value or no child values present in FirebaseRecyclerAdapter

I have used Firebase RecyclerViewAdapter extensively in my app but since the below code doesn't fire populateViewHolder without any data to load in the first place, I can't show the load complete message for the initial load
RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
};
recycler.setAdapter(mAdapter);
What you're describing is covered by this feature: Handle empty state for recycleview. You can handle this by implementing onDataChanged() in your adapter. A snippet from the sample app of FirebaseUI:
#Override
protected void onDataChanged() {
// if there are no chat messages, show a view that invites the user to add a message
mEmptyListView.setVisibility(
mRecyclerViewAdapter.getItemCount() == 0 ? View.VISIBLE : View.INVISIBLE
);
}
if(chatMessage.getName().equals("")){ //null value }else{
//execute code }
Override onDataChanged() and check in it
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
#Override
protected void onDataChanged() {
// do your tests here
}
};

Categories

Resources