Ron Daulagupu
Ron Daulagupu

Reputation: 423

How to delete duplicate data that I get after updating data in firebase console

I am developing an android app that displays the ranks of students based on their marks retrieved from the firebase database. Everything is working fine but, when I update the marks in the db, it keeps the old data and adds the new data in the recyclerView. I can restart the app to refresh the data. But while it is still running, it shows the old data too.

Below is my firebase data:

Student1: {
      c: 70,
      cPlus: 90,
      java: 70,
      name: "Samson",
      regno: "16sksb7034",
      unix: 60
       }
Student2: {
      c: 20,
      cPlus: 85,
      java: 68,
      name: "Samson",
      regno: "16sksb7034",
      unix: 86
       }
Student3: {
      c: 70,
      cPlus: 70,
      java: 80,
      name: "Samson",
      regno: "16sksb7034",
      unix: 90
       }

Here is my dataModel class:

public class Marks {
private String name;
private String regno;
private int c;
private int cPlus;
private int  java;
private int unix;
private int percentage;

public Marks() {}

public Marks(int c, int cPlus, int java, int unix) {
    this.c = c;
    this.cPlus = cPlus;
    this.java = java;
    this.unix = unix;
}

public int getPercentage() {
    return percentage;
}

public void setPercentage(int percentage) {
    this.percentage = percentage;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getRegno() {
    return regno;
}

public void setRegno(String regno) {
    this.regno = regno;
}

public int getC() {
    return c;
}

public void setC(int c) {
    this.c = c;
}

public int getcPlus() {
    return cPlus;
}

public void setcPlus(int cPlus) {
    this.cPlus = cPlus;
}

public int getJava() {
    return java;
}

public void setJava(int java) {
    this.java = java;
}

public int getUnix() {
    return unix;
}

public void setUnix(int unix) {
    this.unix = unix;
     }
  }

class MarksComparator implements Comparator<Marks> {
  @Override
  public int compare(Marks marks1, Marks marks2) {
    int Marks1Total = marks1.getPercentage();
    int Marks2Total = marks2.getPercentage();

    if (Marks2Total < Marks1Total) {
        return -1;
    } else if (Marks2Total > Marks1Total) {
        return 1;
    } else {
        return 0;
    }
 }
}

Here's my activity class:

public class MarksFragment extends Fragment{

private List<Marks> mMarksList = new ArrayList<>();

private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private FirebaseDatabase mDatabase;
private DatabaseReference mReference;
private int total=0;

    public MarksFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_marks, container, false);


        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);

        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

        // specify an adapter (see also next example)
        /*mAdapter = new MyAdapter(getContext(),mMarksList);
        mAdapter.notifyDataSetChanged();
        mRecyclerView.setAdapter(mAdapter);*/

        //get Firebase Reference
        FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        mDatabase = FirebaseDatabase.getInstance();
        mReference = mDatabase.getReference();

        mReference.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    fetchData(dataSnapshot);


            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                    fetchData(dataSnapshot);
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
        return view;
    }

public void findPercentage(Marks value) {
        total =value.getC() + value.getcPlus() + value.getJava() + value.getUnix();
        value.setPercentage(total);
}

private void fetchData(DataSnapshot dataSnapshot) {
    Marks value = dataSnapshot.getValue(Marks.class);
    Log.v("Marks Fragment", "" +value);
    findPercentage(value);
    mMarksList.add(value);
    Collections.sort(mMarksList, new MarksComparator());

    // specify an adapter (see also next example)
    mAdapter = new MyAdapter(getContext(),mMarksList);
    mAdapter.notifyDataSetChanged();
    mRecyclerView.setAdapter(mAdapter);

Here is my adapter class:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{

private Context mContext;
private List<Marks> marksList;


public MyAdapter(Context mContext, List<Marks> marksList) {
    this.mContext = mContext;
    this.marksList = marksList;
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView mItemName, mItemRegNo, mItemNo, mTotal;
    CircleImageView mImageView;

    public MyViewHolder(View view) {
        super(view);
        mItemName = (TextView) view.findViewById(R.id.card_name);
        mItemRegNo = (TextView) view.findViewById(R.id.card_regno);
        mItemNo = (TextView) view.findViewById(R.id.item_id);
        mImageView = (CircleImageView) view.findViewById(R.id.item_photo);
        mTotal = view.findViewById(R.id.card_total);
    }
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_item, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    Marks marks = marksList.get(position);
    int count = position + 1;
    holder.mItemName.setText("" + marks.getName());
    holder.mItemRegNo.setText("" + marks.getRegno());
    holder.mItemNo.setText("" + count);
    holder.mImageView.setImageResource(R.drawable.after_cookie);
    holder.mTotal.setText(""+ marks.getPercentage());

}

@Override
public int getItemCount() {
    return marksList.size();
        }
    }

So the code does what its intended to do it retrieves the data and calculates the total and ranks the students. but when I update the data in firebase console the views in recyclerView duplicates temporarily. Like for example if I update Student1 unix value as 10 then two views will be shown in the recyclerView: 1 for previous value and 2 for updated value and again if I update the values it will yet show another views representing the new data without removing the old views. But if I restart recyclerView gets refreshed and its all ok but while I am running the app during the update it shows temporary duplicate views too.

I am new here and this is my first question so I can't even upload picture as you need 10 points to upload photo. I really hope someone help me out on this. I thank you in advance.

UPDATE

Here is link to the image:

When I start the app, the image is: first Image

when I update the unix value of Student3, the image in recyclerView becomes like this: After updating the data in firebase console

So, you see it adds new data as well as keeps the old data untill I restart.

Upvotes: 1

Views: 3330

Answers (1)

Thomas
Thomas

Reputation: 481

Your problem is that you're never checking if the student already exists in your mMarksList so you're simply duplicating him by adding him again with new grades.

What I would do in you case is to add an unique id in firebase to each student.

Then you can check in your fetchData whether the student with that id is already in the array, delete him and add the new one.

private void fetchData(DataSnapshot dataSnapshot) {
    Marks value = dataSnapshot.getValue(Marks.class);
    Log.v("Marks Fragment", "" +value);
    findPercentage(value);
    // Get an iterator.
    Iterator<Marks> ite = mMarksList.iterator();
    while(ite.hasNext()) {
        Marks iteValue = ite.next();
        if(iteValue.getId().equals(value.getId())) ite.remove();
    }
    mMarksList.add(value);

    ....
}

Optionally To make that even cleaner, you can override the equals and hashcode methods in your Marks data model, so that a Marks object is considered the same if the id is equal. More

//ASSUMING THAT ID IS int

@Override
public int hashCode() {
    return id;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (this.getClass() != obj.getClass()) return false;

    Marks other = (Marks) obj;
    if (this.getId != other.getId) {
        return false;
    }
    return true;

}

Then it's possible to either use a hashmap, which will override the old student automatically or a arraylist as is and iterate through it before and check if a student equals your new student, like this:

private void fetchData(DataSnapshot dataSnapshot) {
    Marks value = dataSnapshot.getValue(Marks.class);
    Log.v("Marks Fragment", "" +value);
    findPercentage(value);
    // Use an iterator.
    Iterator<Marks> ite = mMarksList.iterator();
    while(ite.hasNext()) {
        Marks iteValue = ite.next();
        if(iteValue.equals(value)) ite.remove();
    }
    mMarksList.add(value);

    ....
}

Upvotes: 2

Related Questions