The practice of using Recyclerview instead of ListView in Android app development _android

Source: Internet
Author: User
Tags call back

Recyclerview is the new Android 5.0 feature that can directly replace the ListView and GridView, and can achieve the layout of the waterfall flow, feeling the advantage of Recyclerview use is that it does not care about the layout, only concerned about the recovery and reuse of resources, because of this , Recyclerview Viewholder was written separately, which is exactly what Google has been advocating, and recyclerview can be simpler to implement layout transformations.
The new view class Recyclerview, which is used in place of the ListView and the GridView, provides a more efficient reuse mechanism, while managing the solution coupling with the view. Characteristics of Recyclerview:
1, Recyclerview do not care about the layout, you need to use Setlayoutmanager to set the layout.
2, Recyclerview do not care about the split line, so the split line we need to find ways to set up.
3, Recyclerview does not care about the item click event and animation effect, need to write their own interface for listening.
4, Recyclerview only focus on the view of recovery and reuse.
Related classes:
1, Recyclerview.adapter: Managed data collection, create a view for each item;
2, Recyclerview.viewholder: Host the item view of the child view;
3, Recyclerview.layoutmanager: Responsible for the layout of the item view;
4, Recyclerview.itemdecoration: To add a split line for each item view;
5, Recyclerview.itemanimator: Responsible for adding, delete data when the animation effect;

Example of using Recyclerview instead of ListView
Recyclerview is a more flexible control than the ListView, can be directly discarded after the ListView. What is the specific place, look down to know.
First we use Recyclerview to implement the ListView effect, a scrolling list, first look at the effect chart (except for the animation, nothing special-):

The layout of each item is as follows:

 <?xml version= "1.0" encoding= "Utf-8"?> <linearlayout "xmlns:android=" Schemas.android.com/apk/res/android "android:id=" @+id/recycler_view_test_item_person_view "Android:orientati on= "vertical" android:layout_width= "match_parent" android:layout_height= "Wrap_content" Android:paddin G= "15DP" android:background= "#aabbcc" > <textview android:id= "@+id/recycler_view_test_item_person _name_tv "android:layout_width=" match_parent "android:layout_height=" Wrap_content "android:textSize=" 18s P "android:background=" #ccbbaa "/> <textview android:id=" @+id/recycler_view_test_item_person_age
      _tv "android:layout_width=" match_parent "android:layout_height=" wrap_content "android:paddingleft=" 5DP " Android:background= "#aaccbb" android:textsize= "15sp"/> </LinearLayout> 

The item's layout is simple, with only two TextView, one to display the name, and one to display the age.

The entity class for person does not have code, two attributes: Name and age.

Then you need to use the Recyclerview, so you need to add support V7 to class path and add the control to the layout:

<android.support.v7.widget.recyclerview
        android:id= "@+id/recycler_view_test_rv"
        android:scrollbars= "Vertical"
        android:layout_width= "match_parent"
        android:layout_height= "Match_parent"
        android: Background= "#bbccaa"
        />

And then in the OnCreate:

Recyclerview.sethasfixedsize (true);

    Recyclerview.layoutmanager LayoutManager = new Linearlayoutmanager (context);
    Recyclerview.setlayoutmanager (LayoutManager);

    InitData ();
    adapter = new Personadapter (personlist);
    Adapter.setonrecyclerviewlistener (this);
    Recyclerview.setadapter (adapter);

such as the above code:

Line1: Keeps the recyclerview in a fixed size, which can improve the performance of Recyclerview.

Line3:linearlayoutmanager, if you need to display a scrolling list or a vertical scrolling list, use this layoutmanager. Obviously, we want to achieve the effect of ListView, so we need to use it. After this linearlayoutmanager is generated, you can set the direction of his scrolling, the default vertical scrolling, so there is no explicit setting.

Line6: Initializes the data source.

Line7~9: Like ListView, you need to set up the Recyclerview adapter, but the adapter here is not the same as the ListView adapter use, The Adapter here need to inherit recyclerview.adapter, and you need to implement 3 methods:

1, Oncreateviewholder ()

2, Onbindviewholder ()

3, GetItemCount ()

Look directly at the code:

Package Com.wangjie.helloandroid.sample.recycler.person;
Import Android.support.v7.widget.RecyclerView;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.LinearLayout;
Import Android.widget.TextView;
Import Com.wangjie.androidbucket.log.Logger;

Import COM.WANGJIE.HELLOANDROID.R;

Import java.util.List; public class Personadapter extends Recyclerview.adapter {public static interface Onrecyclerviewlistener {void Onit
    Emclick (int position);
  Boolean onitemlongclick (int position);

  Private Onrecyclerviewlistener Onrecyclerviewlistener; public void Setonrecyclerviewlistener (Onrecyclerviewlistener onrecyclerviewlistener) {This.onrecyclerviewlistener =
  Onrecyclerviewlistener;
  private static final String TAG = PersonAdapter.class.getSimpleName ();

  Private list<person> List;
  Public Personadapter (list<person> list) {this.list = list; } @Override Public RECYCLERVIEW.VIEWHOlder Oncreateviewholder (viewgroup viewgroup, int i) {LOGGER.D (TAG, "Oncreateviewholder, I:" + i);
    View view = Layoutinflater.from (Viewgroup.getcontext ()). Inflate (R.layout.recycler_view_test_item_person, NULL); Linearlayout.layoutparams LP = new Linearlayout.layoutparams (ViewGroup.LayoutParams.MATCH_PARENT,
    ViewGroup.LayoutParams.WRAP_CONTENT);
    VIEW.SETLAYOUTPARAMS (LP);
  Return to New Personviewholder (view); @Override public void Onbindviewholder (Recyclerview.viewholder viewholder, int i) {LOGGER.D (TAG, "onbindviewho
    Lder, I: "+ i +", Viewholder: "+ Viewholder";
    Personviewholder holder = (personviewholder) Viewholder;
    Holder.position = i;
    Person person = list.get (i);
    Holder.nameTv.setText (Person.getname ());
  Holder.ageTv.setText (Person.getage () + "old");
  @Override public int GetItemCount () {return list.size (); Class Personviewholder extends Recyclerview.viewholder implements View.onclicklistener, View.onlongclickliStener {public View rootview;
    Public TextView Nametv;
    Public TextView Agetv;

    public int position;
      Public Personviewholder (View Itemview) {super (Itemview);
      Nametv = (TextView) Itemview.findviewbyid (R.ID.RECYCLER_VIEW_TEST_ITEM_PERSON_NAME_TV);
      Agetv = (TextView) Itemview.findviewbyid (R.ID.RECYCLER_VIEW_TEST_ITEM_PERSON_AGE_TV);
      Rootview = Itemview.findviewbyid (R.id.recycler_view_test_item_person_view);
      Rootview.setonclicklistener (this);
    Rootview.setonlongclicklistener (this); @Override public void OnClick (View v) {if (null!= onrecyclerviewlistener) {Onrecyclerviewliste
      Ner.onitemclick (position); @Override public boolean Onlongclick (View v) {if (null!= onrecyclerviewlistener) {return o
      Nrecyclerviewlistener.onitemlongclick (position);
    return false;

 }
  }

}

As shown in the code above:

Public Recyclerview.viewholder Oncreateviewholder (viewgroup viewgroup, int i)

This method is primarily born into a view for each item inflater, but the method returns a Viewholder. The approach is to encapsulate the view directly in the Viewholder, and then we're looking at the Viewholder example, and of course this viewholder needs to be written by ourselves. The tedious steps of the original Convertview.settag (holder) and Convertview.gettag () were omitted directly.

public void Onbindviewholder (Recyclerview.viewholder viewholder, int i)

This method is mainly used for matching rendering data into view. Method provides you with a viewholder instead of the original Convertview.

In contrast, the previous wording is clear:

@Override public View getview (int position, View Convertview, ViewGroup parent) {Viewholder holder;
      if (null = = Convertview) {holder = new Viewholder ();
      Layoutinflater Minflater = (layoutinflater) context.getsystemservice (Context.layout_inflater_service);
      Convertview = minflater.inflate (R.layout.item, NULL);
      HOLDER.BTN = (Button) Convertview.findviewbyid (R.ID.BTN);
      Holder.tv = (TextView) Convertview.findviewbyid (r.id.tv);

      HOLDER.IV = (TextView) Convertview.findviewbyid (R.ID.IV);
    Convertview.settag (holder);
    }else{holder = (viewholder) convertview.gettag ();

    Final hashmap<string, object> map = list.get (position);
    Holder.iv.setImageResource (Integer.valueof (Map.get ("IV"). ToString ());

    Holder.tv.setText (Map.get ("TV"). toString ()); Holder.btn.setOnClickListener (New View.onclicklistener () {@Override public void OnClick (View v) {Toa St.maketext (Context, Map.get ("btn"). ToString (), TOast.
      Length_short). Show ();

    }
    });
  return convertview;
    Class viewholder{Button btn;
    ImageView IV;

  TextView TV;

 }

The comparison can be found:

1, the old writing in the line5~line12+line28 part of the code in fact play a role equivalent to the new Oncreateviewholder ();

2, the old writing in the Line14~line26 part of the code in fact play a role equivalent to the new Onbindviewholder ();

Since this is the case, then we can move the corresponding code to the corresponding Oncreateviewholder () and Onbindviewholder () two methods.

Because Recyclerview helped us encapsulate the holder, So we write our own viewholder need to inherit Recyclerview.viewholder, only in this way, Recyclerview can help you to manage this viewholder class.

Since the code for the rendering data portion of the GetView method is equivalent to Onbindviewholder (), if the Adapter.notifydatasetchanged () method is invoked, the Onbindviewholder () should also be called again. Method, right? After the experiment, sure enough!

In addition to the adapter.notifydatasetchanged () method, the new adapter also provides other methods, as follows:

Public final void notifydatasetchanged () public
    final void notifyitemchanged (int position) public final void
    notifyitemrangechanged (int positionstart, int itemCount) public
    final void notifyiteminserted (int position) 
    Public final void notifyitemmoved (int fromposition, int toposition) public
    final void notifyitemrangeinserted (int Positionstart, int itemCount) public
    final void notifyitemremoved (int position) public
    final void notifyitemrangeremoved (int positionstart, int itemCount)

Basically see the name of the method to know what this method is doing,

The first method has nothing to say, as before.

    • notifyitemchanged (int position), position data has changed, and invoking this method will call back the Onbindviewholder () method of the corresponding position, of course, Because Viewholder is reused, if the position is outside the current screen, it will not be recalled, because there is no sense, the next time the position scroll will be within the current screen will also invoke the Onbindviewholder () method to refresh the data. The same is true of other methods.
    • public final void notifyitemrangechanged (int positionstart, int itemCount), as the name suggests, You can refresh the number of item ItemCount starting from Positionstart (here The refresh refers to the callback Onbindviewholder () method).
    • public final void notifyiteminserted (int position), which can be refreshed using this method when the position position is inserted into a piece of data. Note that this method invocation will have an inserted animation that can be used either by default or by definition.
    • public final void notifyitemmoved (int fromposition, int toposition), This method is used when moving from fromposition to Toposition to refresh the
    • public final void notifyitemrangeinserted (int positionstart , int itemCount), is obviously bulk added.
    • public final void notifyitemremoved (int position), which is refreshed when the position is deleted, as well as animations.
    • public final void notifyitemrangeremoved (int positionstart, int itemCount), bulk deletion.

After the analysis of these methods, we will implement a click a button, add a data, long press an item, delete a piece of data scene.

Here's the code for a new piece of data:

person person = new person (i, "wangjie_" + I, + i);
Adapter.notifyiteminserted (2);
Personlist.add (2, person);
Adapter.notifyitemrangechanged (2, Adapter.getitemcount ());

As above code:

Line2: Indicates where the position is 2, inserts a piece of data, this time the animation begins to execute.

Line3: Represents a new piece of data in the data source where position is 2 (in fact, this is the real new data).

Line4: Why do you want to refresh the data after position is 2? Because, after inserting a data in the position of position 2, the position of the new data becomes 2, the original position 2 should become 4, so the position of all the data after 2 has changed, So we need to refresh the data after Position2. This is theoretically true, but the number of refreshes is only position on the screen after 2 of the data. If you use Notifydatasetchanged () here to refresh all the item displayed on the screen, can you? The results will not go wrong, but there is a problem, the previous call to the Notifyiteminserted () method will be executed after the animation, if you call notifydatasetchanged () Refresh all the item displayed on the screen, The item that is currently executing the animation must also be refreshed so that the result is that the previous animation is not finished, it is immediately refreshed, and the animation is not visible. So just refresh 2 after the item is OK.

Look at the Recyclerview API, found no setonitemclicklistener--, so or their own onitemclick from the adapter of the callback out of it. This is very simple, just like Onrecyclerviewlistener in the personadaper above.

Long press the deletion code as follows:

adapter.notifyitemremoved (position);
Personlist.remove (position);
Adapter.notifyitemrangechanged (position, Adapter.getitemcount ());

The code is basically consistent with the code you inserted earlier. First notify the animation, then delete the data from the data source, and then notify the position after the data refresh is OK.

So the ListView effect is realized.

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.