您好,登錄后才能下訂單哦!
RecyclerView為什么會卡
RecyclerView作為v7包的新控件,自從推出就廣受Android Developer們歡迎,實際上它已經取代了ListView和GridView兩位老前輩的地位。然而不少親們想必也已經發現了:沒有優化過的Recycler性能很poor。上一篇博主使用的item也僅僅是一個圖兩串字而已,結果一滑動就卡的要命,不能忍!
那么why?回想在用ListView和GridView的adapter時,我們是用一種叫ViewHolder的自定義類(容器)來實現優化的,而RecyclerView的特性之一就是強制你使用它的RecyclerView.ViewHolder。可是,RecyclerView.ViewHolder要比我們寫的那個單純的容器復雜多了(源碼里算上注釋有大約500行),與RecyclerView.Adapter的聯系也是千絲萬縷。
按stackoverflow上面比較通俗的解釋:RecyclerView.Adapter里面的onCreateViewHolder()方法和onBindViewHolder()方法對時間都非常敏感。類似I/O讀寫,Bitmap解碼一類的耗時操作,最好不要在它們里面進行。
如何解決這個問題
首先當然得優化你的item,合理運用<include>,<merge>,<ViewStub>等標簽,使布局層次盡量少——其實ListView和GridView里你也應該這么做,應該當成是一種寫UI的習慣。
其次就是靈活使用各種第三方庫,去完成各種耗時操作,比如通過Glide或者是Picasso加載圖片。優秀的開源庫在性能上往往都考慮得很仔細。
最后的問題來了,如果只想寫一個小demo,不愿大張旗鼓怎么辦?如果即便一般的第三方庫也不好解決問題,比如上一篇那個該死的loadIcon()方法返回的是一個Drawable對象,Glide和Picasso都沒法直接處理,轉碼又等于添了個耗時任務,那怎么辦?
真正的app管理應用,應該引入UIL或者Picasso一類的加載庫進行圖標加載
答案就是,想法在你setAdapter之前就把任務給完成。
Demo
喲西,上代碼!本文代碼完全基于上一篇文,無須刪減重構。
主要就是增添了一個實體bean對象,setAdapter()時要傳遞的數據,全部通過它預先加載到內存里!這樣那倆敏感方法里只需要簡單的get出來即可。
實體類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);//獲取已安裝的全部應用 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); } } //拿到數據再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());//圖標 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()));//根據包名啟動此應用 context.startActivity(intent); } }); }
搞定!因為博主是用手機直接錄像再轉gif,為了使點擊看上去有效果,于是給item增添了一個背景層,這需求實戰中也是很常見的哦~~
色彩資源文件colors.xml
這個粉紅色其實很難看,單純當區別用。。。。。。
實戰開發如果沒有美工,一定要仔細斟酌選取,盡量讓自己審美好點!
<?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"> <!-- 中間內容無須修改,略--> </RelativeLayout>
最終運行效果
截圖已經不太能感受到卡了,真機運行更加流暢!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。