Android RecyclerView的卡顿问题的解决方法

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>

最终运行效果

截图已经不太能感受到卡了,真机运行更加流畅!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-10-08 01:35:11

Android RecyclerView的卡顿问题的解决方法的相关文章

Android 关于ExpandableListView刷新问题的解决方法_Android

正文 首先是最基础的 ExpandableListView vList = (ExpandableListView) this.findViewById(R.id.list); EListAdapter adapter = new EListAdapter(getApplicationContext(), list); //list 是数据源 vList.setAdapter(adapter); //适配器就不写了, 都懂的 class EListAdapter extends BaseExpa

Android 关于ExpandableListView刷新问题的解决方法

正文 首先是最基础的 ExpandableListView vList = (ExpandableListView) this.findViewById(R.id.list); EListAdapter adapter = new EListAdapter(getApplicationContext(), list); //list 是数据源 vList.setAdapter(adapter); //适配器就不写了, 都懂的 class EListAdapter extends BaseExpa

Android Studio 报错“app:processDebugResources"解决方法

Android Studio 报错"app:processDebugResources"解决方法 Android Studio项目Build的时候报了这么一个错误: Error:Execution failed for task ':app:processDebugResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Pro

Android 7.0行为变更 FileUriExposedException解决方法

Android 7.0行为变更 FileUriExposedException解决方法 当我们开发关于[在应用间共享文件]相关功能的时候,在Android 7.0上经常会报出此运行时异常,那么Android 7.0以下没问题的代码,为什么跑到Android 7.0+的设备上运行就出问题了呢?,这主要来自于Android 7.0的一项[行为变更]! 对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI

android建立项目时失败:Android Manifest.xml file missing的解决方法

安卓(android)建立项目时失败,出现AndroidManifest.xml file missing几种解决方法?(总结中) Eclipse新建项目,遇到这样的问题,注意如下: 1.文件名最好不要用中文. 2.目录也不要用中文. 3.这个不会出错,但出于程序编写习惯,第一个字母最好为大写. 查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/extra/

android java.lang.UnsatisfiedLinkError: 分析及解决方法

产生此类异常主要有两种原因:   一, jni还没有编译 是一边编译一边用的  这要分两种情况: 第一种是UnsatisfiedlinkError:dll名称.说明dll没有放到合适的位置.对于Android开发,我们一般把so放在 libs目录下,但是还是会出现这个错误.根本原因System.loadLibrary函数会加载你指定的so,该so中需要链接的所有符号都需要能够链接到,如果有一个链接不成功,那么整个so也会加载失败.仔细检查so中需要的所有符号,确保其存在且在正确的位置上. 第二种

Android library projects cannot be launched解决方法

 今天的项目总是报这个问题,解决方法如下 将图中的 Is Library前面的对勾去掉,这样问题就解决了

Android RecyclerView添加头部和底部的方法_Android

如果只是想添加头部,可是使用GitHub里面这个项目,它可以为LinearLayoutManager,GridLayoutManager ,StaggeredGridLayoutManager布局的RecyclerView添加header.使用起来也十分简单: 只需将RecyclerViewHeader布局放在RecyclerView的上层. <FrameLayout android:layout_width="match_parent" android:layout_heigh

Android RecyclerView添加头部和底部的方法

如果只是想添加头部,可是使用GitHub里面这个项目,它可以为LinearLayoutManager,GridLayoutManager ,StaggeredGridLayoutManager布局的RecyclerView添加header.使用起来也十分简单: 只需将RecyclerViewHeader布局放在RecyclerView的上层. <FrameLayout android:layout_width="match_parent" android:layout_heigh