Android development of the Diffutil use of detailed _android

Source: Internet
Author: User

It's written in front of you.

Diffutil is a collection of changes to find a tool class, is used with Recyclerview, if you do not know Recyclerview, you can read some information, this is not introduced.

First place Effect chart:

As you can see, when we click on the button, the set that the Recyclerview shows has changed, and some elements have been added (8). Jason), and some of the elements were moved (3). Rose), was even modified (2. fndroid).

Recyclerview the animation for each item is refreshed in a different way:

notifyiteminserted

Notifyitemchanged

Notifyitemmoved

Notifyitemremoved

For a continuous refresh of several item, you can call:

Notifyitemrangechanged

notifyitemrangeinserted

Notifyitemrangeremoved

As the collection changes, only the method can be invoked notifyDataSetChanged to refresh the entire interface, and can not be based on the change of the set for each of the changed elements to add animation. So here's a diffutil to solve the problem.

The role of Diffutil is to find out what happens to each item in the collection, and then give the corresponding refresh for each change.

This diffutil uses the Eugene Myers differential algorithm, which does not check the movement of the elements, that is, the movement can only be counted first to delete, then increase, and Diffutil is in the algorithm after the result of a move check. It is assumed that without detecting element movement, the time complexity of the algorithm is O (N + D2), while the detection element movement is O (N2). So, if the set itself is already sorted out, you can improve the efficiency without moving the detection.

Let's take a look at how this tool is used.

First for each item, the data is a student object:

Class Student {
 private String name;
 private int num;

 Public Student (String name, int num) {
  this.name = name;
  This.num = num;
 }

 Public String GetName () {return
  name;
 }

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

 public int Getnum () {return
  num;
 }

 public void setnum (int num) {
  this.num = num;
 }
}

We then define the layout (ellipsis) and adapters:

Class Myadapter extends Recyclerview.adapter {private arraylist<student> data;
  Arraylist<student> GetData () {return data;
  } void SetData (arraylist<student> data) {this.data = new arraylist<> (data); @Override public Recyclerview.viewholder Oncreateviewholder (viewgroup parent, int viewtype) {View Itemview = La
   Youtinflater.from (Recyclerviewactivity.this). Inflate (R.layout.itemview, NULL);
  return new Myviewholder (Itemview);  @Override public void Onbindviewholder (recyclerview.viewholder holder, int position) {Myviewholder Myviewholder
   = (myviewholder) holder;
   Student Student = data.get (position);
  MyViewHolder.tv.setText (Student.getnum () + "." + Student.getname ());
  @Override public int GetItemCount () {return data.size ();

   Class Myviewholder extends Recyclerview.viewholder {TextView TV;
    Myviewholder (View Itemview) {super (Itemview); TV = (TextView) Itemview.findviewbyid (r.id.item_tV); }
  }
 }

Initializing data collection:

private void InitData () {
  students = new arraylist<> ();
  Student S1 = new Student ("John", 1);
  Student s2 = new Student ("Curry", 2);
  Student s3 = new Student ("Rose", 3);
  Student S4 = new Student ("Dante", 4);
  Student S5 = new Student ("Lunar", 5);
  Students.add (S1);
  Students.add (S2);
  Students.add (S3);
  Students.add (S4);
  Students.add (S5);
 }

Then instantiate the adapter and set it to Recyclerview:

@Override
 protected void onCreate (Bundle savedinstancestate) {
  super.oncreate (savedinstancestate);
  Setcontentview (R.layout.activity_recycler_view);
  InitData ();
  Recyclerview = (Recyclerview) Findviewbyid (R.ID.RV);
  Recyclerview.setlayoutmanager (This) (new Linearlayoutmanager);
  adapter = new Myadapter ();
  Adapter.setdata (students);
  Recyclerview.setadapter (adapter);
 }

None of this is the content of this article, but one area that needs to be noted is the definition of adapter:

Class Myadapter extends Recyclerview.adapter {
  private arraylist<student> data;

  Arraylist<student> GetData () {return
   data;
  }

  void SetData (arraylist<student> data) {
   this.data = new arraylist<> (data);
  }

  Omit part of code ... 
 }

The setData method here is not to save the ArrayList reference directly, but to build a ArrayList again, remember, and then explain why.

How to use Diffutil:

When the mouse is pressed, modify the contents of the ArrayList:

public void Change (view view) {
  Students.set (1, New Student ("Fndroid", 2));
  Students.add (New Student ("Jason", 8));
  Student s2 = students.get (2);
  Students.remove (2);
  Students.add (S2);

  arraylist<student> old_students = Adapter.getdata ();
  Diffutil.diffresult result = Diffutil.calculatediff (new Mycallback (old_students, students), true);
  Adapter.setdata (students);
  Result.dispatchupdatesto (adapter);
 }

2-6 rows are modified for the collection, and line 8th gets the old data from the collection in adapter.

The focus is on line 9th calling DiffUtil.calculateDiff methods to compute the differences in the collection, passing in a callback interface's implementation class (which specifies the rules for the calculation) and passing both the old and new data to the implementation class of the interface, and finally to a Boolean type of argument, This parameter specifies whether move detection is required and, if not required, if an item is moved, it is considered first remove and then insert. This is specified as true, so there is the move effect of the move graph display.

Line 10th again sets the new data to adapter.

Line 11th calls the method of the Diffresult object obtained from line 9th to dispatchUpdatesTo notify the Recyclerview refresh corresponding to the changed item.

Here we go back to the method mentioned above setData , because we are here to distinguish two sets, and if you setData save the reference directly in the method, then the 2-6-row modification directly modifies the collection in adapter (Java knowledge).

If the setting does not check item movement, the effect is as follows:

Then let's look at how the implementation class for the callback interface is defined:

Private class Mycallback extends Diffutil.callback {
  private arraylist<student> old_students, new_students;< C2/>mycallback (arraylist<student> data, arraylist<student> students) {
   this.old_students = data;
   this.new_students = students;
  }

  @Override public
  int getoldlistsize () {return
   old_students.size ();
  }

  @Override public
  int getnewlistsize () {return
   new_students.size ();
  }

  Determines whether the item already exists
  @Override public
  boolean areitemsthesame (int olditemposition, int newitemposition) {
   Return Old_students.get (olditemposition). Getnum () = = New_students.get (newitemposition). Getnum ()
  ;

  If item already exists, this method is called to determine whether the item's contents are consistent
  @Override public
  boolean arecontentsthesame (int olditemposition, int Newitemposition) {return
   old_students.get (olditemposition). GetName (). Equals (New_students.get ( newitemposition). GetName ());
  }
 

Here according to the school number to determine whether the same item, according to the name of the item has been modified.

In fact, this callback abstract class also has a method getChangePayload() that we can use to tell adapter to update the item locally rather than the entire update.

First you know what this payload is? Payload is an object that describes the item change, which is how our item changed, and these changes are encapsulated into a payload, so we can generally use bundle to act as.

Next, the getChangePayload() method areItemsTheSame() returns True, and the areContentsTheSame() callback when it returns false is that the contents of an item have changed, and the change may be local (for example, Weibo's point of praise, we just need to refresh the icon instead of the entire item). So you can getChangePayload() encapsulate an object in to tell Recyclerview to make a partial refresh.

Suppose the above example high School number and name with different TextView display, when we modify a school number corresponding to the name, the local refresh name can (this example may appear to be redundant, but if an item is very complex, useful is more important):

First, rewrite the method in callback:

@Nullable
  @Override public
  Object getchangepayload (int olditemposition, int newitemposition) {
   Student Newstudent = Newstudents.get (newitemposition);
   Bundle diffbundle = new Bundle ();
   Diffbundle.putstring (Name_key, Newstudent.getname ());
   return diffbundle;
  }

Where will the returned object be received? RecyclerView.AdapterThere are actually two ways in which we have to onBindViewHolder rewrite, and the third argument is a list of payload:

   @Override public
   void Onbindviewholder (recyclerview.viewholder holder, int position, List payloads) {}

So we simply rewrite this method in adapter, and if the list is empty, perform the original onbindviewholder to update the entire item, otherwise refresh the content based on payloads:

@Override public
  void Onbindviewholder (recyclerview.viewholder holder, int position, List payloads) {
   if ( Payloads.isempty ()) {
    Onbindviewholder (holder, position);
   } else {
    Myviewholder Myviewholder = ( Myviewholder) holder;
    Bundle Bundle = (Bundle) payloads.get (0);
    if (bundle.getstring (name_key)!= null) {
     myViewHolder.name.setText (bundle.getstring (Name_key));
     MyViewHolder.name.setTextColor (Color.Blue);}}
  

The payloads here will not be null, so direct judgment is null.

Note here: If a large amount of data is loaded in the Recyclerview, then the algorithm may not be completed immediately, pay attention to the problem of ANR, you can open a separate thread for calculation.

Summarize

The use of Diffutil in Android is here, and hopefully this article will help Android developers, and if you have questions, you can talk.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.