RecyclerView使用,優化,條目閃爍問題
RecyclerView的基本介紹
RecyclerView是谷歌V7包下新增的控制元件,用來替代ListView的使用,在RecyclerView標準化了ViewHolder類似於ListView中convertView用來做檢視緩.
RecyclerView好處
①RecylerView封裝了viewholder的回收複用,也就是說RecylerView標準化了ViewHolder,編寫Adapter面向的是 ViewHolder而不再是View了,複用的 邏輯被封裝了,寫起來更加簡單。
②提供了一種插拔式的體驗,高度的解耦,異常的靈活,針對一個Item的顯示RecylerView專門抽取出了相應的類,來控制Item的顯示,使其的擴充套件性非常強。例如recyclerview不侷限與下拉選單,它還支援GridView效果和瀑布流效果
③可以控制Item增刪的動畫,可以通過ItemAnimator這個類進行控制,當然針對增刪的動畫,RecylerView有其自己預設的實現。
涉及到的類
Adapter:使用RecyclerView之前,你需要一個繼承自RecyclerView.Adapter的介面卡,作用是將資料與每一個item的介面進行繫結。
LayoutManager:用來確定每一個item如何進行排列擺放,何時展示和隱藏。回收或重用一個View的時候,LayoutManager會向介面卡請求新的資料來替換舊的資料,這種機制避免了建立過多的View和頻繁的呼叫findViewById方法(與ListView原理類似)。
RecyclerView的三種顯示方式
目前SDK中提供了三種自帶的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
RecyclerView依賴,佈局,屬性使用
1、新增依賴
implementation ‘com.android.support:recyclerview-v7:27.1.1’
2.然後是在XML檔案用使用它
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
3.建立完佈局之後在MainActivity中獲取這個RecyclerView,並宣告LayoutManager與Adapter,程式碼如下:
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this );
//設定佈局管理器
recyclerView.setLayoutManager(layoutManager);
//設定為垂直佈局,這也是預設的
layoutManager.setOrientation(OrientationHelper. VERTICAL);
//設定Adapter
recyclerView.setAdapter( recycleAdapter);
//設定分隔線
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));
//設定增加或刪除條目的動畫
recyclerView.setItemAnimator( new DefaultItemAnimator());
RecyclerView的介面卡RecyclerView.Adapter
RecyclerView.Adapter
①onCreateViewHolder()
這個方法主要生成為每個Item inflater出一個View,但是該方法返回的是一個ViewHolder。該方法把View直接封裝在ViewHolder中,然後我們面向的是ViewHolder這個例項,當然這個ViewHolder需要我們自己去編寫。直接省去了當初的convertView.setTag(holder)和convertView.getTag()這些繁瑣的步驟。
②onBindViewHolder()
這個方法主要用於適配渲染資料到View中。方法提供給你了一個viewHolder,而不是原來的convertView。
③getItemCount()
這個方法就類似於BaseAdapter的getCount方法了,即總共有多少個條目。
建立介面卡和ViewHolder
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private final ArrayList<String> mData;
private final Context mContext;
private final LayoutInflater mInflater;
private OnItemClickListener mListener;
public MyAdapter(Context context,ArrayList<String> data) {
this.mContext = context;
this.mData = data;
mInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//建立一個自定義ViewHolder
View inflate = mInflater.inflate(R.layout.item, parent,false);
ViewHolder viewHolder = new ViewHolder(inflate);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, final int position) {
//將資料與介面繫結
holder.mTv.setText(mData.get(position));
if (position%2 == 0){
holder.mIv.setImageResource(R.drawable.friend_circle_default);
}else{
holder.mIv.setImageResource(R.drawable.cate);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//這個方法被呼叫的時候,想要讓MainActivity知道
if (mListener != null){
mListener.onItemClick(v,position);
}
}
});
}
//1.定義一個介面
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
//2.傳遞介面類實現物件
public void setOnItemClickListener(OnItemClickListener listener){
this.mListener = listener;
}
@Override
public int getItemCount() {
//獲取item數量
return mData.size();
}
/**
* RecyclerView 內部封裝了VIewHolder的回收複用,標準化了ViewHolder,編寫Adapter就是面向ViewHolder,而不是View
*/
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView mTv;
private ImageView mIv;
public ViewHolder(View itemView) {
super(itemView);
mTv = itemView.findViewById(R.id.tv);
mIv = itemView.findViewById(R.id.iv);
}
}
}
RecyclerView介面回撥
1.定義介面
在哪裡定義?
定義外部介面和內部介面都可以,google一般定義內部,所以我們也定義內部介面
介面裡有什麼方法
取決於我們要做什麼,需要什麼方法就定義什麼
//Adapter內部定義
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
2.設定傳遞介面類實現物件的方法
public void setOnItemClickListener(OnItemClickListener listener){
this.mListener = listener;
}
3.傳遞介面實現類物件
mAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "position:" + position, Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.this, MultiTypeActivity.class));
}
});
Recycleview優化:
1,如果確定recycleview中資料變化的位置,可以對其進行區域性重新整理
2,在編寫佈局的時候,如果能通過程式碼實現排布,可以將xml方式進行替換,提升頁面載入的效率;另外尤其在多佈局展示中,對應不同item中公用的一些控制元件或元件,可以通過自定義view的方式,減少view的構造和巢狀。
3,如果一個item中,多個子view都需要設定點選事件的監聽,我們可以設定一個全域性的監聽,然後通過view.getId或view.getTag來找到具體item,將具體view的點選事件設定到viewHolder中,避免列表在不停滑動過程中,猶豫onbindviewholder要反覆繪製資料帶來的點選事件的重複建立。
4,如果一個recyclerview中巢狀了多個recyclerview,而巢狀recycerview的介面卡是一樣的,可以共享一個物件池。
5,對recyclerview資料的預載入,當我們載入完一頁資料後,不管使用者有沒有及時上拉檢視,我們可以再後臺動態的載入一定數量的資料,當列表上劃時,計算劃出的條目數量,然後從預載入的資料中取出對應條目的數量追加到recycleview末尾,這樣給使用者更為流暢的滑動體驗。
6,對於scrollview中巢狀recyclerview,我們可以呼叫setNestedScrollingEnabled(false)來禁止recycleview的滑動,以確保外部view可流暢的滑動。
7,如果item高度固定,可以設定RecyclerView.setHasFixedSize(true); 來避免 requestLayout 浪費資源;
8,呼叫RecyclerView.onViewRecycled(holder) 來回收資源。
9,通過 RecycleView.setItemViewCacheSize(size); 來加大 RecyclerView 的快取,用空間換時間來提高滾動的流暢性
10,瀑布流上拉載入時發生item抖動,建議採用notifyItemRangeChanged進行區域性重新整理
關於recycleview重新整理是條目閃爍問題
1,如果僅僅是重新整理某一個item,一定要呼叫指定位置的區域性重新整理,儘量避免更為消耗資源的全部重新整理
2,如果沒有給item加出場動畫,儘量把預設的動畫禁止掉,防止onbindviewholder重繪item的時候,由於出場動畫給item的重新整理帶來閃爍的bug
3,對於item中圖片的閃爍,一方面要注意圖片的載入是否加了出場動畫(比如glide預設有出場動畫,應該把它禁止掉),第二就是看有沒有在重新整理的時候動態繪製imageview的形狀,如果繪製效率不高的情況下,也會引發圖片閃爍,第三在item中儘量不要使用辦透明效果,尤其是資料量較大或者涉及到需要頻繁重新整理的情況,因為半透明繪製底層涉及到大量的數學運算,而這些嚴重影響item的繪製,所以當item數量龐大時,會出現item閃爍甚至滑動卡頓的問題。
相關文章
- vue渲染時閃爍{{}}的問題及解決方法Vue
- WinForm 載入自定義控制元件閃爍問題ORM控制元件
- RecyclerView使用封裝與優化View封裝優化
- 短視訊平臺原始碼,單條目重新整理notifyItem 去除閃爍動畫原始碼動畫
- Flutter 混合開發實戰問題記錄(一)FlutterView閃爍FlutterView
- Java swing JFrame用repaint出現閃爍的問題解決JavaAI
- js閃爍效果JS
- 討論TableLayoutPanel載入緩慢和閃爍問題解決方案
- Arduino 初級使用 單LED等閃爍UI
- RecyclerView 多條目型別含有多個EditTextView型別
- 細談RecyclerView:(二)重新整理閃爍?不存在的,帶你瞭解RecyclerView區域性重新整理View
- SceneKit-解決模型重疊時渲染畫面閃爍的問題模型
- vuejs在解析時出現閃爍的原因及防止閃爍的方法VueJS
- RecyclerView問題彙總View
- Flutter——實現閃爍效果Flutter
- [20181119]使用sql profile優化問題.txtSQL優化
- jQuery 項卡標題欄閃爍提示新資訊jQuery
- windows10桌面閃爍怎麼辦_windows10桌面閃爍無法使用修復方法Windows
- c51控制led閃爍
- vue頁面渲染是閃爍{{}}Vue
- 凸優化問題優化
- QT 讓工作列圖示閃爍QT
- 「GAN優化」什麼是模式崩潰,以及如何從優化目標上解決這個問題優化模式
- Oracle優化案例-緊急處理一條sql引起cpu使用率99%的問題(十六)Oracle優化SQL
- RecyclerView的使用總結以及常見問題解決方案View
- 斜率優化(凸包優化)DP問題acm優化ACM
- RecyclerView 效能優化 | 安卓 offer 收割基View優化安卓
- 從Glide.with(View)開始最佳化RecyclerView掉幀問題IDEView
- c++切面條題目C++
- CSS3文字閃爍效果CSSS3
- fcpx影片去閃爍外掛:Remove FlickeREM
- Canvas繪製星光閃爍的生日祝福Canvas
- 03-凸優化問題優化
- FCPX外掛:視訊去閃爍消除頻閃工具Remove FlickeREM
- 數值最優化—優化問題的解(二)優化
- iOS使用Instrument Time Profiler工具分析和優化效能問題iOS優化
- 如何在 kitten 裡生成動態個數個立方體(水平方向平鋪)以及避免閃爍問題
- [譯] 在 Flutter 中實現微光閃爍效果Flutter