本文其實是上一篇Android本地app操作相關基礎的延伸秃励,然而內容基本沒什么聯(lián)系了(初學者身份瞬間暴露劝堪,打一槍換一個地方←_←)晚岭,就不好意思再添個“續(xù)”或者“(2)”了~~
照舊先碼字嗤无!
RecyclerView為什么會卡
RecyclerView作為v7包的新控件壶愤,自從推出就廣受Android Developer們歡迎,實際上它已經取代了ListView和GridView兩位老前輩的地位乔夯。然而不少親們想必也已經發(fā)現(xiàn)了:沒有優(yōu)化過的Recycler性能很poor期虾。上一篇博主使用的item也僅僅是一個圖兩串字而已,結果一滑動就卡的要命驯嘱,不能忍!
那么why喳坠?回想在用ListView和GridView的adapter時鞠评,我們是用一種叫ViewHolder的自定義類(容器)來實現(xiàn)優(yōu)化的,而RecyclerView的特性之一就是強制你使用它的RecyclerView.ViewHolder壕鹉√昊希可是,RecyclerView.ViewHolder要比我們寫的那個單純的容器復雜多了(源碼里算上注釋有大約500行)晾浴,與RecyclerView.Adapter的聯(lián)系也是千絲萬縷负乡。
按stackoverflow上面比較通俗的解釋:RecyclerView.Adapter里面的onCreateViewHolder()方法和onBindViewHolder()方法對時間都非常敏感。類似I/O讀寫脊凰,Bitmap解碼一類的耗時操作抖棘,最好不要在它們里面進行。
如何解決這個問題
- 首先當然得優(yōu)化你的item狸涌,合理運用<include>切省,<merge>,<ViewStub>等標簽帕胆,使布局層次盡量少——其實ListView和GridView里你也應該這么做朝捆,應該當成是一種寫UI的習慣。
- 其次就是靈活使用各種第三方庫懒豹,去完成各種耗時操作芙盘,比如通過Glide或者是Picasso加載圖片。優(yōu)秀的開源庫在性能上往往都考慮得很仔細脸秽。
- 最后的問題來了儒老,如果只想寫一個小demo,不愿大張旗鼓怎么辦记餐?如果即便一般的第三方庫也不好解決問題贷盲,比如上一篇那個該死的loadIcon()方法返回的是一個Drawable對象,Glide和Picasso都沒法直接處理,轉碼又等于添了個耗時任務巩剖,那怎么辦铝穷?
真正的app管理應用,應該引入UIL或者Picasso一類的加載庫進行圖標加載
(在此原諒博主沒仔細敲代碼佳魔,就信口開河了)
答案就是曙聂,想法在你setAdapter之前就把任務給完成。
Demo
喲西鞠鲜,上代碼宁脊!本文代碼完全基于上一篇文,無須刪減重構贤姆。
主要就是增添了一個實體bean對象榆苞,setAdapter()時要傳遞的數(shù)據(jù),全部通過它預先加載到內存里霞捡!這樣那倆敏感方法里只需要簡單的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);
}
}
//拿到數(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());//圖標
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ù)包名啟動此應用
context.startActivity(intent);
}
});
}
搞定碧信!因為博主是用手機直接錄像再轉gif赊琳,為了使點擊看上去有效果,于是給item增添了一個背景層砰碴,這需求實戰(zhàn)中也是很常見的哦~~
色彩資源文件colors.xml
這個粉紅色其實很難看躏筏,單純當區(qū)別用。呈枉。趁尼。。猖辫。弱卡。
實戰(zhàn)開發(fā)如果沒有美工,一定要仔細斟酌選取住册,盡量讓自己審美好點婶博!
推薦一個不錯的配色方案網站Material Design調色板
<?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>
最終運行效果
截圖已經不太能感受到卡了荧飞,真機運行更加流暢凡人!