Android RecyclerView的卡頓問題的解決方法
RecyclerView為什么會卡
RecyclerView作為v7包的新控件,自從推出就廣受Android Developer們歡迎,實(shí)際上它已經(jīng)取代了ListView和GridView兩位老前輩的地位。然而不少親們想必也已經(jīng)發(fā)現(xiàn)了:沒有優(yōu)化過的Recycler性能很poor。上一篇博主使用的item也僅僅是一個圖兩串字而已,結(jié)果一滑動就卡的要命,不能忍!
那么why?回想在用ListView和GridView的adapter時,我們是用一種叫ViewHolder的自定義類(容器)來實(shí)現(xiàn)優(yōu)化的,而RecyclerView的特性之一就是強(qiáng)制你使用它的RecyclerView.ViewHolder。可是,RecyclerView.ViewHolder要比我們寫的那個單純的容器復(fù)雜多了(源碼里算上注釋有大約500行),與RecyclerView.Adapter的聯(lián)系也是千絲萬縷。
按stackoverflow上面比較通俗的解釋:RecyclerView.Adapter里面的onCreateViewHolder()方法和onBindViewHolder()方法對時間都非常敏感。類似I/O讀寫,Bitmap解碼一類的耗時操作,最好不要在它們里面進(jìn)行。
如何解決這個問題
首先當(dāng)然得優(yōu)化你的item,合理運(yùn)用<include>,<merge>,<ViewStub>等標(biāo)簽,使布局層次盡量少——其實(shí)ListView和GridView里你也應(yīng)該這么做,應(yīng)該當(dāng)成是一種寫UI的習(xí)慣。
其次就是靈活使用各種第三方庫,去完成各種耗時操作,比如通過Glide或者是Picasso加載圖片。優(yōu)秀的開源庫在性能上往往都考慮得很仔細(xì)。
最后的問題來了,如果只想寫一個小demo,不愿大張旗鼓怎么辦?如果即便一般的第三方庫也不好解決問題,比如上一篇那個該死的loadIcon()方法返回的是一個Drawable對象,Glide和Picasso都沒法直接處理,轉(zhuǎn)碼又等于添了個耗時任務(wù),那怎么辦?
真正的app管理應(yīng)用,應(yīng)該引入UIL或者Picasso一類的加載庫進(jìn)行圖標(biāo)加載
答案就是,想法在你setAdapter之前就把任務(wù)給完成。
Demo
喲西,上代碼!本文代碼完全基于上一篇文,無須刪減重構(gòu)。
主要就是增添了一個實(shí)體bean對象,setAdapter()時要傳遞的數(shù)據(jù),全部通過它預(yù)先加載到內(nèi)存里!這樣那倆敏感方法里只需要簡單的get出來即可。
實(shí)體類AppBean.java
package com.example.jin.localapp;
import android.graphics.drawable.Drawable;
/**
 * Created by Jin on 2016/11/8.
 */
public class AppBean {
  private CharSequence name;
  private String packageName;
  private Drawable icon;
  //這類代碼可別逞英雄手動寫哦,IDE(Android Studio和Eclipse都有的)里可以直接生成
  public CharSequence getName() {
    return name;
  }
  public void setName(CharSequence name) {
    this.name = name;
  }
  public String getPackageName() {
    return packageName;
  }
  public void setPackageName(String packageName) {
    this.packageName = packageName;
  }
  public Drawable getIcon() {
    return icon;
  }
  public void setIcon(Drawable icon) {
    this.icon = icon;
  }
}
主界面MainActivity.java
  private List<AppBean> mList;//mList的泛型換成AppBean
  private void initData() {//然后只需要改這個方法
    mList = new ArrayList<>();
    manager = getPackageManager();
    List<PackageInfo> list = manager.getInstalledPackages(0);//獲取已安裝的全部應(yīng)用
    for (PackageInfo info : list) {
      if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
        AppBean bean = new AppBean();
        bean.setName(info.applicationInfo.loadLabel(manager));
        bean.setPackageName(info.packageName);
        bean.setIcon(info.applicationInfo.loadIcon(manager));
        mList.add(bean);
      }
    }
    //拿到數(shù)據(jù)再setAdapter
    mainRcv.setLayoutManager(new LinearLayoutManager(this));
    mainRcv.setHasFixedSize(true);
    mainRcv.setAdapter(new AppAdapter(this, mList));
  }
適配器AppAdapter.java
  private List<AppBean> appList;
  //同樣這邊的類型換過來
  public AppAdapter(Context context, List<AppBean> appList) {
    this.context = context;
    this.appList = appList;
    inflater = LayoutInflater.from(context);
    manager = context.getPackageManager();
  }
  //然后也只需要改這個方法
  @Override
  public void onBindViewHolder(AppHolder holder, final int position) {
    final AppBean bean = appList.get(position);
    holder.itemIconIv.setImageDrawable(bean.getIcon());//圖標(biāo)
    holder.itemNameTv.setText(bean.getName());//名稱
    holder.itemPackageTv.setText(bean.getPackageName());//包名
    holder.view.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Intent intent = new Intent(manager.getLaunchIntentForPackage(bean.getPackageName()));//根據(jù)包名啟動此應(yīng)用
        context.startActivity(intent);
      }
    });
  }
搞定!因為博主是用手機(jī)直接錄像再轉(zhuǎn)gif,為了使點(diǎn)擊看上去有效果,于是給item增添了一個背景層,這需求實(shí)戰(zhàn)中也是很常見的哦~~
色彩資源文件colors.xml
這個粉紅色其實(shí)很難看,單純當(dāng)區(qū)別用。。。。。。
實(shí)戰(zhàn)開發(fā)如果沒有美工,一定要仔細(xì)斟酌選取,盡量讓自己審美好點(diǎn)!
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorWhite">#ffffff</color> <color name="colorPink">#f8bbd0</color> </resources>
選擇器item_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:drawable="@color/colorWhite" /> <item android:state_focused="true" android:drawable="@color/colorPink" /> <item android:state_pressed="true" android:drawable="@color/colorPink" /> <item android:drawable="@color/colorWhite"/> </selector>
條目布局item_app.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@drawable/item_selector" android:layout_width="match_parent" android:layout_height="60dp"> <!-- 中間內(nèi)容無須修改,略--> </RelativeLayout>
最終運(yùn)行效果
截圖已經(jīng)不太能感受到卡了,真機(jī)運(yùn)行更加流暢!
 
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android中使用RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
 - Android中RecyclerView布局代替GridView實(shí)現(xiàn)類似支付寶的界面
 - Android中RecyclerView實(shí)現(xiàn)多級折疊列表效果(二)
 - Android中RecyclerView實(shí)現(xiàn)橫向滑動代碼
 - Android RecyclerView網(wǎng)格布局(支持多種分割線)詳解(2)
 - Android Recyclerview實(shí)現(xiàn)多選,單選,全選,反選,批量刪除的功能
 - Android RecyclerView 復(fù)用錯亂通用解法詳解
 - Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
 - Android項目實(shí)戰(zhàn)之仿網(wǎng)易新聞的頁面(RecyclerView )
 - Android如何利用RecyclerView實(shí)現(xiàn)列表倒計時效果實(shí)例代碼
 
相關(guān)文章
 Android自定義view實(shí)現(xiàn)標(biāo)簽欄功能(只支持固定兩個標(biāo)簽)
這篇文章主要介紹了Android自定義view實(shí)現(xiàn)標(biāo)簽欄(只支持固定兩個標(biāo)簽),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
 Android xml文件的序列化實(shí)現(xiàn)代碼
Android提供了XmlSerializer來實(shí)現(xiàn)XML文件的序列化。相比傳統(tǒng)方式,更高效安全,需要的朋友可以參考下2014-02-02
 Android自定義Camera實(shí)現(xiàn)拍照小功能
這篇文章主要為大家詳細(xì)介紹了Android自定義Camera實(shí)現(xiàn)拍照小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05
 Android Studio如何獲取SQLite數(shù)據(jù)并顯示到ListView上
這篇文章主要介紹了Android Studio獲取SQLite數(shù)據(jù)并顯示到ListView上,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
 Android TextView中文本點(diǎn)擊文字跳轉(zhuǎn) (代碼簡單)
用過微博Android手機(jī)端的朋友的都知道微博正文有時有一些高亮顯示的文本,如話題、提到的人等等,當(dāng)點(diǎn)擊這些文本時會跳到另外一個頁面(即另一個activity),下面就要來模仿微博的這個功能2016-01-01
 Android開發(fā)筆記SQLite優(yōu)化記住密碼功能
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)筆記SQLite優(yōu)化記住密碼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07

