RecyclerView actual use
Make a list with RecyclerView. Display test data.
This example is divided into the following steps:
- Determine the data. Analog data is used here.
- Design UI and presentation.
- Write layout and adapter.
Analog data
A skillful woman can't make bricks without rice. Simulation data is simulation demand.
Create a new DataTest class and design four properties.
public class DataTest { private String timezone; private int number; private int personCount; private int count; public DataTest(String timezone, int number, int personCount, int count) { this.timezone = timezone; this.number = number; this.personCount = personCount; this.count = count; } // getter setter... }
Design the layout of item
Design UI and display 4 attribute values in one line. Item uses item_recy2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv1" style="@style/RePage2Header" android:layout_marginEnd="@dimen/re_2_half_gap" /> <TextView android:id="@+id/tv2" style="@style/RePage2Header" android:layout_marginStart="@dimen/re_2_half_gap" android:layout_marginEnd="@dimen/re_2_half_gap" /> <TextView android:id="@+id/tv3" style="@style/RePage2Header" android:layout_marginStart="@dimen/re_2_half_gap" android:layout_marginEnd="@dimen/re_2_half_gap" /> <TextView android:id="@+id/tv4" style="@style/RePage2Header" android:layout_marginStart="@dimen/re_2_half_gap" /> </LinearLayout>
Prepare resources such as color, size, etc
The relevant style, color and size configuration files are in the res/values directory.
The style file style.xml.
<style name="RePage2Header"> <item name="android:layout_width">0dp</item> <item name="android:layout_height">40dp</item> <item name="android:layout_weight">2</item> <item name="android:textColor">#ffffff</item> <item name="android:gravity">center</item> <item name="android:background">@color/rePage2Item</item> </style>
We set layout for each TextView in layout_width is 0dp. To use layout_weight attribute. Let them divide the width of the parent View proportionally among the four textviews.
The segmentation here uses the segmentation proportion feature of LinearLayout.
Add the following color settings to the color configuration file color.xml.
<color name="rePage2Item">#082941</color>
Dimension configuration dimensions.xml.
<dimen name="re_2_gap">4dp</dimen> <dimen name="re_2_half_gap">2dp</dimen>
Design ViewHolder
When the resource file and layout are ready, start writing the corresponding viewHolder. Here, VH class and Adapter class are also placed in the activity class.
private class VH extends RecyclerView.ViewHolder { TextView tv1; TextView tv2; TextView tv3; TextView tv4; public VH(@NonNull View itemView) { super(itemView); tv1 = itemView.findViewById(R.id.tv1); tv2 = itemView.findViewById(R.id.tv2); tv3 = itemView.findViewById(R.id.tv3); tv4 = itemView.findViewById(R.id.tv4); } }
Design Adapter class
Adapter class.
private class Adapter extends RecyclerView.Adapter<VH> { private List<DataTest> dataList = new ArrayList<>(); public Adapter() { } public void setDataList(List<DataTest> dataList) { this.dataList = dataList; // It is better to judge the empty space notifyDataSetChanged(); } @NonNull @Override public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new VH(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recy2, parent, false)); } @Override public void onBindViewHolder(@NonNull VH holder, int position) { DataTest dataTest = dataList.get(position); holder.tv1.setText(dataTest.getTimezone()); holder.tv2.setText(String.valueOf(dataTest.getNumber())); holder.tv3.setText(String.valueOf(dataTest.getPersonCount())); holder.tv4.setText(String.valueOf(dataTest.getCount())); } @Override public int getItemCount() { return dataList.size(); } }
Configure RecyclerView
Set recyclerview.
// In activity or fragment private Adapter mAdapter = new Adapter(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.act_recy_2); RecyclerView recyclerView = findViewById(R.id.re_view); recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false)); recyclerView.setAdapter(mAdapter); mAdapter.setDataList(genDataTestList()); recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.top = getResources().getDimensionPixelOffset(R.dimen.re_2_gap); } }); } // Generate simulation data private List<DataTest> genDataTestList() { List<DataTest> list = new ArrayList<>(); for (int i = 1; i <= 60; i++) { DataTest d = new DataTest("time zone" + i, i, i, i); list.add(d); } return list; }
Configure recyclerView in the onCreate method. The recyclerView.addItemDecoration method is to set the interval style for the item. getItemOffsets can set the spacing of children. Here, a spacing value is given to the bottom of the subitem. The specific value is set in the dimen sion. genDataTestList() is the data that generates the simulation.
Modify layout using include
Some friends asked: the header and item have the same structure. Can they be reused?
Actually, it can. We can use the include tag in the layout to "include" another layout file. Copy act_ recy_ 2. Paste XML to get act_recy_2_include.xml, change the LinearLayout of the original header to include.
<include layout="@layout/item_recy2" />
Set the layout for include, that is, the layout of the item we defined_ recy2. When we want to add a margin top, for example
<include android:layout_marginTop="4dp" layout="@layout/item_recy2" />
as will pop up a warning:
Layout parameter layout_marginTop ignored unless both layout_width and layout_height are also specified on tag
That is, in the include tab, if you want to set other properties, you need to set layout first_ Width and layout_height.
Modify it and add an id to make it like this.
<include android:id="@+id/header" layout="@layout/item_recy2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" />
Let the Activity use this layout. Modify RecyclerViewDemo2Act.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.act_recy_2_include); initHeader(); // Part of configuring RecyclerView } private void initHeader() { View header = findViewById(R.id.header); TextView tv1 = header.findViewById(R.id.tv1); tv1.setText("time zone"); TextView tv2 = header.findViewById(R.id.tv2); tv2.setText("Serial number"); TextView tv3 = header.findViewById(R.id.tv3); tv3.setText("personnel"); TextView tv4 = header.findViewById(R.id.tv4); tv4.setText("quantity"); }
We added a method initHeader(). First find the header and find its sub views through the header, that is, the four textviews. Just set the text separately.
RecyclerView related interview questions
1. Will pre layout occur during the first layout of recyclerview?
A pre layout is not triggered the first time you layout. Pre layout will only be triggered every notify change. The purpose is to record the coordinates of ViewHolder at each position in the screen through saveOldPosition method, and realize the animation effect of Item through comparison after re layout.
2. When is the viewholder cached in the RecycledViewPool?
There are two main situations:
- When the ItemView is slid off the screen and the CachedView is full, the ViewHolder is cached in the RecycledViewPool
- When the data changes, the ViewHolder after executing the disappearance will be cached in the RecycledViewPool
3. Relationship between cachedview and RecycledViewPool
When an ItemView is slid out of the screen, it will be saved in the CachedView by default. The default size of CachedView is 2, and its value can be modified by setItemViewCacheSize method.
When the CachedView is full and a new ItemView slides out of the screen, it will force the CachedView to transfer the previously cached ViewHolder to the RecycledViewPool according to FIFO rules
The default size of RecycledViewPool is 5. You can modify the cache size of RecycledViewPool in the following ways:
RecyclerView.getRecycledViewPool().setMaxRecycledViews(int viewType, int max);
4. The difference between cachedview and RecycledViewPool
The ViewHolder cached in the CachedView does not clean up relevant information (such as position, state, etc.), so when the ViewHolder just moved out of the screen is moved back to the screen, it can be found and displayed in the CachedView without rebinding (bindViewHolder).
The ViewHolder cached in the RecycledViewPool will be cleared of status and location information. Therefore, if the ViewHolder is found from the RecycledViewPool, you need to call bindViewHolder again to bind data.
5. From what aspects do you optimize RecyclerView?
RecyclerView can be optimized from the following aspects:
- Try to put complex data processing operations into asynchrony. The data that RecyclerView needs to display is often requested from the remote server, but after the network requests to get the data, it is necessary to flatten the data and try to return the best data format to the UI thread.
- Optimize the layout of RecyclerView to avoid using it with ConstraintLayout
- For fast sliding events, you can use addOnScrollListener to add monitoring for fast sliding. When the user slides quickly, stop loading data.
- If the height of the ItemView is fixed, you can use setHasFixSize(true). In this way, the height of the RecyclerView can be calculated directly in the onMeasure stage without calculating the height of the sub ItemView multiple times. This situation has a very significant effect on the nesting of horizontal recyclerviews in the vertical RecyclerView.
- When the UI is a Tab feed stream, you can consider using RecycledViewPool to share the cache of multiple recyclerviews.