Issue
I am new to firebase. I am trying to update my RecyclerView data in the firebase database while reflecting the same updated value in my RecyclerView data dynamically. Even in case of someone tries to update the data from firebase console itself, the change has to be reflected in the recyclerView. I have a seekBar in my list and every time i change the data from the list, it has to be reflected back in the database. The problem is, every time i am trying to change the data from the recyclerView list itself, data is getting changed in the firebase database which in turn calling the onDataChanged() and its making my whole recyclerView getting reloaded again without showing the updated data on the list. Please help.
Below I am posting my listfragment as well as adapter class code:
ListFragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v= inflater.inflate(R.layout.fragment_slc_list, container, false);
slcList = (RecyclerView)v.findViewById(R.id.addedSlcList);
noSLC = (TextView)v.findViewById(R.id.noSLCText);
fragmentManager= myContext.getSupportFragmentManager();
slcList.setHasFixedSize(true);
ref = new Firebase(Config.FIREBASE_URL);
list = new ArrayList<slcItem>();
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
// dAdapter = new slcListAdapter(myContext,list, ref );
// slcList.setLayoutManager(llm);
// slcList.setAdapter(dAdapter);
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot)
{
Log.d("clear","cleared");
list.clear();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
Log.v("2nd",""+ childDataSnapshot.getKey()); //displays the key for the node
Log.v("2nd",""+ childDataSnapshot.getValue());
Slc val= childDataSnapshot.getValue(Slc.class);
Log.v("2ndClass",""+ val.getOn_off());
slcItem item = new slcItem();
item.setSlcOnOff(val.getOn_off());
item.setSlcID(val.getUser_id());
item.setSlcProgress(val.getDimming_val());
item.setSlcName(childDataSnapshot.getKey());
item.setSlcStatus(val.getStatus());
list.add(item);
LinearLayoutManager llm1 = new LinearLayoutManager(getActivity());
dAdapter = new slcListAdapter(myContext,list, ref );
dAdapter.notifyDataSetChanged();
slcList.setLayoutManager(llm1);
slcList.setAdapter(dAdapter);
}
for(int i=0; i<list.size();i++)
{
Log.d("animesh",list.get(i).getSlcName()+" "+list.size()+" "+dataSnapshot.getChildrenCount());
}
if(dataSnapshot.getChildrenCount() == 0)
{
LinearLayoutManager llm1 = new LinearLayoutManager(getActivity());
dAdapter = new slcListAdapter(myContext,list, ref );
getActivity().runOnUiThread(new Runnable() {
public void run() {
dAdapter.notifyDataSetChanged();
}
});
slcList.setLayoutManager(llm1);
slcList.setAdapter(dAdapter);
}
}
@Override
public void onCancelled(FirebaseError firebaseError)
{
Log.d("animesh",firebaseError+"");
}
});
Log.d("anilist",list.size()+"");
Adapter class:
public slcListAdapter(Context context,ArrayList<slcItem> list, Firebase ref ) {
super();
this.context=context;
this.list=list;
this.ref=ref;
dItems = new ArrayList<slcItem>();
for(int i=0;i<list.size();i++)
{
slcItem deal = new slcItem();
deal.setSlcName(list.get(i).getSlcName());
dItems.add(deal);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.single_slc_row, viewGroup, false);
viewHolder = new ViewHolder(v);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
int v;
nature = dItems.get(i);
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot)
{
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren())
{
Log.d("animesh",childDataSnapshot.toString());
Slc val = childDataSnapshot.getValue(Slc.class);
// viewHolder.dimming.setProgress(val.getDimming_val());
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
viewHolder.name.setText(nature.getSlcName());
viewHolder.inv.setVisibility(View.GONE);
viewHolder.onOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Log.d("checkani",nature.getSlcName());
if(isChecked){
ref.child(list.get(i).getSlcName()).child("on_off").setValue(1);
}else{
ref.child(list.get(i).getSlcName()).child("on_off").setValue(0);
Log.d("Ani",list.get(i).getSlcName());
}
}
});
viewHolder.dimming.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
Log.d("dimming",nature.getSlcName());
ref.child(list.get(i).getSlcName()).child("dimming_val").setValue(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
viewHolder.expand.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
// ViewAnimationsUtils.expand(viewHolder.inv);
viewHolder.collapse.setVisibility(View.VISIBLE);
viewHolder.inv.setVisibility(View.VISIBLE);
viewHolder.expand.setVisibility(View.GONE);
}
});
viewHolder.collapse.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
// ViewAnimationsUtils.collapse(inv);
viewHolder.inv.setVisibility(View.GONE);
viewHolder.expand.setVisibility(View.VISIBLE);
viewHolder.collapse.setVisibility(View.GONE);
}
});
viewHolder.edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.update_slc);
dialog.setCancelable(false);
Window window = dialog.getWindow();
if(window == null) return;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.CENTER;
dialog.getWindow().setAttributes(lp);
final EditText name = (EditText) dialog.findViewById(R.id.slcNameu);
final EditText id = (EditText) dialog.findViewById(R.id.slcIDu);
TextView cancel = (TextView) dialog.findViewById(R.id.cancelu);
TextView update = (TextView) dialog.findViewById(R.id.updateSlc);
// update.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v)
// {
// final String Sname = nature.getSlcName();
// Map mParent = new HashMap();
// mParent.put("user_id", id.getText().toString().trim());
// mParent.put("on_off", nature.getSlcOnOff());
// mParent.put("status", nature.getSlcStatus());
// mParent.put("dimming_val",nature.getSlcProgress());
// ref.child(name.getText().toString().trim()).setValue(mParent, new Firebase.CompletionListener()
// {
// @Override
// public void onComplete(FirebaseError firebaseError, Firebase firebase) {
// Log.d("aniNature","Value was set. Error = "+firebaseError+" "+nature.getSlcName()+" "+Sname);
// ref.child(Sname).removeValue();
// dialog.dismiss();
// }
// });
//
// }
// });
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
});
viewHolder.delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Dialog dialog = new Dialog(context);
dialog.setTitle("Delete Slc?");
dialog.setContentView(R.layout.delete_slc);
dialog.setCancelable(false);
Window window = dialog.getWindow();
if(window == null) return;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.CENTER;
dialog.getWindow().setAttributes(lp);
TextView delete = (TextView)dialog.findViewById(R.id.deleteSlc);
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Log.d("delete1",nature.getSlcName());
ref.child(list.get(i).getSlcName()).removeValue();
Log.d("delete",nature.getSlcName());
dialog.dismiss();
}
});
TextView dialogButton = (TextView) dialog.findViewById(R.id.canceld);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
dialog.dismiss();
}
});
dialog.show();
}
});
}
@Override
public int getItemCount()
{
return dItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView name;
public Switch onOff;
public SeekBar dimming;
public TextView edit;
public TextView delete;
public TextView expand;
public TextView collapse;
public LinearLayout inv;
public ViewHolder(View itemView)
{
super(itemView);
name = (TextView) itemView.findViewById(R.id.slcName);
onOff = (Switch) itemView.findViewById(R.id.slcONOFFSwich);
dimming=(SeekBar) itemView.findViewById(R.id.slcDimming);
edit = (TextView) itemView.findViewById(R.id.EditSlc);
delete = (TextView) itemView.findViewById(R.id.DeleteSlc);
expand = (TextView) itemView.findViewById(R.id.down);
collapse = (TextView) itemView.findViewById(R.id.up);
inv = (LinearLayout) itemView.findViewById(R.id.invisibleLayout);
}
}
}
Solution
If you want to respond to child-level changes, you should use a ChildEventListener
. This interface has separate methods for when a child is added, removed, changed or moved (onChildAdded
, onChildRemoved
, onChildChanged
and onChildMoved
respectively).
Note that you'll need to do a lot more work in this scenario to ensure the items stay in the correct order in list
. For example: you'll need to track the key of each item, so that you can compare it to previousKey
argument in onChildAdded
and onChildChanged
.
For an example of a working implementation of such an adapter, I recommend checking out FirebaseUI's FirebaseRecyclerAdapter
and its underlying FirebaseArray
.
Answered By - Frank van Puffelen
Answer Checked By - Gilberto Lyons (JavaFixing Admin)