[Android] replacing ListView with RecyclerView (1)

Source: Internet
Author: User

[Android] replacing ListView with RecyclerView (1)
RecyclerView is a more flexible control than ListView. In the future, you can discard ListView directly. Where can I find the details. First, we will use RecyclerView to implement the ListView effect. For a rolling list, let's take a look at it first (except for animations, There is nothing special --): the layout of each item is as follows: <? Xml version = "1.0" encoding = "UTF-8"?> <LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: id = "@ + id/recycler_view_test_item_person_view" android: orientation = "vertical" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: padding = "15dp" android: background = "# aabbcc"> <TextView android: id = "@ + id/recycler_view_test_item_person_name_ TV" android: layout_width = "match_parent" android: layou T_height = "wrap_content" android: textSize = "18sp" 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 layout of the item is very simple. There are only two textviews, one for displaying the name and the other for displaying the age. The entity class of Person does not post code. There are two attributes: name and age. Then you need to use RecyclerView. Therefore, you need to add support v7 to the 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 onCreate: 1 recyclerView. setHasFixedSize (true); 2 3 RecyclerView. layoutManager layoutManager = new LinearLayoutManager (co Ntext); 4 recyclerView. setLayoutManager (layoutManager); 5 6 initData (); 7 adapter = new PersonAdapter (personList); 8 adapter. setOnRecyclerViewListener (this); 9 recyclerView. setAdapter (adapter); for example, the preceding code: Line1: keeps the RecyclerView of a fixed size, which improves the RecyclerView performance. Line3: LinearLayoutManager. If you want to display a horizontal or vertical scrolling list, use this LayoutManager. Obviously, we need to implement the ListView effect, so we need to use it. After the LinearLayoutManager is generated, you can set its Scroll direction. By default, it is vertical, so it is not explicitly set here. Line6: Initialize the data source. Line7 ~ 9: Like ListView, you need to set the RecyclerView Adapter. However, the Adapter here is different from the Adapter used by ListView. The Adapter here must inherit the RecyclerView. adapter, You need to implement three methods:-onCreateViewHolder ()-onBindViewHolder ()-getItemCount () directly read the code: copy the Code 1 package com. wangjie. helloandroid. sample. recycler. person; 2 3 import android. support. v7.widget. recyclerView; 4 import android. view. layoutInflater; 5 import android. view. view; 6 import android. view. viewGroup; 7 import android. widget. linearLayout; 8 import android. widget. textView; 9 import com. wangjie. androidbucket. log. logger; 10 import com. wangjie. helloandroid. r; 11 12 import java. util. list; 13 14/** 15 * Author: wangjie16 * Email: tiantian.china.2@gmail.com17 * Date: 1/17/15.18 */19 public class PersonAdapter extends RecyclerView. adapter {20 public static interface OnRecyclerViewListener {21 void onItem Click (int position); 22 boolean onItemLongClick (int position); 23} 24 25 private OnRecyclerViewListener onRecyclerViewListener; 26 27 public void setOnRecyclerViewListener (OnRecyclerViewListener onrecyclerlistener) {28 this. onRecyclerViewListener = onRecyclerViewListener; 29} 30 31 private static final String TAG = PersonAdapter. class. getSimpleName (); 32 private List <Person> list; 33 34 public Perso NAdapter (List <Person> list) {35 this. list = list; 36} 37 38 @ Override39 public RecyclerView. viewHolder onCreateViewHolder (ViewGroup viewGroup, int I) {40 Logger. d (TAG, "onCreateViewHolder, I:" + I); 41 View = LayoutInflater. from (viewGroup. getContext ()). inflate (R. layout. recycler_view_test_item_person, null); 42 LinearLayout. layoutParams lp = new LinearLayout. layoutParams (ViewGroup. layoutParams. M ATCH_PARENT, ViewGroup. layoutParams. WRAP_CONTENT); 43 view. setLayoutParams (lp); 44 return new PersonViewHolder (view); 45} 46 47 @ Override48 public void onBindViewHolder (RecyclerView. viewHolder viewHolder, int I) {49 Logger. d (TAG, "onBindViewHolder, I:" + I + ", viewHolder:" + viewHolder); 50 PersonViewHolder holder = (PersonViewHolder) viewHolder; 51 holder. position = I; 52 Person person = list. get (I); 53 holder. nameTv. setText (person. getName (); 54 holder. ageTv. setText (person. getAge () + ""); 55} 56 57 @ Override58 public int getItemCount () {59 return list. size (); 60} 61 62 class PersonViewHolder extends RecyclerView. viewHolder implements View. onClickListener, View. onLongClickListener63 {64 public View rootView; 65 public TextView nameTv; 66 public TextView ageTv; 67 public int position; 68 69 public P ErsonViewHolder (View itemView) {70 super (itemView); 71 nameTv = (TextView) itemView. findViewById (R. id. recycler_view_test_item_person_name_ TV); 72 ageTv = (TextView) itemView. findViewById (R. id. recycler_view_test_item_person_age_ TV); 73 rootView = itemView. findViewById (R. id. recycler_view_test_item_person_view); 74 rootView. setOnClickListener (this); 75 rootView. setOnLongClickListener (this); 76} 77 78 @ Over Ride79 public void onClick (View v) {80 if (null! = OnRecyclerViewListener) {81 onRecyclerViewListener. onItemClick (position); 82} 83} 84 85 @ Override86 public boolean onLongClick (View v) {87 if (null! = OnRecyclerViewListener) {88 return onRecyclerViewListener. onItemLongClick (position); 89} 90 return false; 91} 92} 93 94} as shown in the code above: public RecyclerView. the ViewHolder onCreateViewHolder (ViewGroup viewGroup, int I) method generates a View for each Item inflater, but this method returns a ViewHolder. The method is to directly encapsulate the View in ViewHolder, and then we are targeting the ViewHolder instance. Of course, this ViewHolder needs to be compiled by ourselves. Saves the tedious steps of convertView. setTag (holder) and convertView. getTag. Public void onBindViewHolder (RecyclerView. ViewHolder viewHolder, int I) is used to adapt rendering data to the View. The method provides you with a viewHolder instead of the original convertView. Compared with the previous method, it is clear: 1 @ Override 2 public View getView (int position, View convertView, ViewGroup parent) {3 ViewHolder holder; 4 if (null = convertView) {5 holder = new ViewHolder (); 6 LayoutInflater mInflater = (LayoutInflater) context. getSystemService (Context. LAYOUT_INFLATER_SERVICE); 7 convertView = mInflater. inflate (R. layout. item, null); 8 holder. btn = (Button) convertView. findViewById (R. id. btn ); 9 holder. TV = (TextView) convertView. findViewById (R. id. TV); 10 holder. iv = (TextView) convertView. findViewById (R. id. iv); 11 12 convertView. setTag (holder); 13} else {14 holder = (ViewHolder) convertView. getTag (); 15} 16 final HashMap <String, Object> map = list. get (position); 17 18 holder. iv. setImageResource (Integer. valueOf (map. get ("iv "). toString (); 19 holder. TV. setText (map. get ("TV "). toString (); 20 21 ho Lder. btn. setOnClickListener (new View. onClickListener () {22 @ Override23 public void onClick (View v) {24 Toast. makeText (context, map. get ("btn "). toString (), Toast. LENGTH_SHORT ). show (); 25} 26}); 27 28 return convertView; 29} 30 31 class ViewHolder {32 Button btn; 33 ImageView iv; 34 TextView TV; 35 36} After comparison, we can find that Line5 ~ Line12 + Line28 Code actually plays a role equivalent to onCreateViewHolder () in the new writing method; Line14 ~ in the old Writing Method ~ Line26 part of the Code actually plays a role equivalent to onBindViewHolder () in the new writing method. In this case, we can move the original code to the corresponding onCreateViewHolder () and onBindViewHolder () you can use both methods. Because RecyclerView encapsulates Holder, ViewHolder we write must inherit RecyclerView. ViewHolder. Only in this way can RecyclerView help you manage this ViewHolder class. Since the code in the rendered Data Part Of The getView method is equivalent to onBindViewHolder (), if you call the adapter. notifyDataSetChanged () method, you should call the onBindViewHolder () method again, right? This is true after the experiment! Except adapter. except the notifyDataSetChanged () method, the new Adapter also provides other methods, as follows: public final void policydatasetchanged () public final void policyitemchanged (int position) public final void policyitemrangechanged (int positionStart, int itemCount) public final void policyiteminserted (int position) public final void policyitemmoved (int fromPosition, int toPosition) public final void limit (int positio NStart, int itemCount) public final void policyitemremoved (int position) public final void policyitemrangeremoved (int positionStart, int itemCount) basically knows what this method is for when you see the method name, the first method has nothing to talk about, just as before. NotifyItemChanged (int position). If the position data changes, the onBindViewHolder () method corresponding to the position will be called back. Of course, ViewHolder is reused, therefore, if the position is outside the current screen, no callback will be made, because it is meaningless. The next time the position is rolled, The onBindViewHolder () method will be called to refresh the data within the current screen. The same applies to other methods. Public final void policyitemrangechanged (int positionStart, int itemCount). As the name suggests, you can refresh the number of itemCount items starting from positionStart (here, refresh refers to the onBindViewHolder () method for callback ). Public final void policyiteminserted (int position). This method can be used to refresh when a data entry is inserted at the position. Note that an animation will be inserted after this method is called, you can use the default animation or define it yourself. Public final void policyitemmoved (int fromPosition, int toPosition). This method can be used to refresh public final void policyitemrangeinserted (int positionStart, int itemCount) from fromPosition to toPosition ), it is obviously batch add. Public final void policyitemremoved (int position), refresh when the first position is deleted, there will also be an animation. Public final void policyitemrangeremoved (int positionStart, int itemCount), batch Delete. After analyzing these methods, we can click a button to add a piece of data, long press an item, and delete a piece of data. The following code adds a new data entry: 1 Person person = new Person (I, "WangJie _" + I, 10 + I); 2 adapter. policyiteminserted (2); 3 personList. add (2, person); 4 adapter. policyitemrangechanged (2, adapter. getItemCount (); the Code above: Line2: inserts a piece of data at the position of 2. At this time, the animation starts to run. Line3: adds a data entry at the position of 2 in the data source (in fact, this is the real new data ). Line4: Why do we need to refresh the data after position 2? Because after a piece of data is inserted at the position of 2, the position of the new data becomes 2, and the original position of 2 should be changed to 3, and the position of 3 should be changed to 4, therefore, the position of all data after position2. therefore, you need to refresh the data after position2. Theoretically, this is the case, but in fact, the number of refreshes is only the data after the position is 2 displayed on the screen. Can I use yydatasetchanged () to refresh all items displayed on the screen? There will be no errors in the results, but there will be a problem. after calling the yyiteminserted () method, the animation will be executed. If you call yydatasetchanged () to refresh all the items displayed on the screen, it will inevitably refresh the item that is currently executing the animation. As a result, the animation is refreshed immediately before it is executed. So you only need to refresh the item after 2. I read the RecyclerView api and found that there is no setOnItemClickListener --, so I should call back onItemClick from the Adapter myself. This is very simple, just like the OnRecyclerViewListener written in PersonAdaper above. The code for Long-pressed deletion is as follows: 1 adapter. policyitemremoved (position); 2 personList. remove (position); 3 adapter. policyitemrangechanged (position, adapter. getItemCount (); the Code is basically the same as the previously inserted code. First, the animation is notified, then the data in the data source is deleted, and then the data refresh after the position is notified. In this way, the ListView effect is achieved.

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.