Listview,Recycleview以及Adapter优化

一.Listview和优化

首先

listview继承自AbsListView,(Gridview也继承自这个类,有机会再说),

Screenshot from 2017-07-04 10:34:02.png

(源码本人今天眼睛不舒服日后再看- -)

然后

关于Adapter。先说控件,是用来交互和展示数据的,但是由于listview需要展示的数据量过大,所以需要adapter提供数据,顾名思义,Adapter是适配器的意思,它在ListView和数据源之间起到了一个桥梁的作用,ListView并不会直接和数据源打交道,而是会借助Adapter这个桥梁来去访问真正的数据源,与之前不同的是,Adapter的接口都是统一的,因此ListView不用再去担心任何适配方面的问题。而Adapter又是一个接口(interface),它可以去实现各种各样的子类,每个子类都能通过自己的逻辑来去完成特定的功能,以及与特定数据源的适配操作。而adapter作为复杂数据的展示的转换载体,所以各种Adapter只不过是转换的方式和能力不一样而已。如图:

Screenshot from 2017-07-04 10:26:23.png

ArrayAdapter

ArrayAdapter是一个绑定View到一组对象的通用类。默认情况下,ArrayAdapter绑定每个对象的toString值到在layout中预先定义的TextView控件上。可变通的,构造函数允许你使用更加复杂的layout或者通过重写getView方法来扩展类从而使用TextView的替代物(如ImageView或嵌套的layout)。

SimpleCursorAdapter

SimpleCursorAdapter绑定View到Content Provider查询返回的游标上。指定一个XML layout定义,然后将数据集中的每一列的值绑定到layout中的一个View上。

Adapter的getView方法

个人觉得这个方法在重写adapter的时候上镜率很高,所以具体分析下。

public View getView(int position, View convertView, ViewGroup parent) {}

getview方法用来刷新listview,在每一次item从屏幕外滑进屏幕内的时候,或者程序刚开始的时候创建第一屏item的时候都会调用这个方法。
position是指当前dataset的位置,通过getCount和getItem来使用。如果list向下滑动的话那么就是最低端的item的位置,如果是向上滑动的话那就是最上端的item的位置。convertView是指可以重用的视图,即刚刚出队的视图。parent应该就是list。还有一个return:
A View corresponding to the data at the specified position.
具体使用看情况,完毕。

最后

关于listview的优化问题。菜鸟写法:

public class CustomAdapter extends ArrayAdapter {
    private int dataid;
    public CustomAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
        super(context, resource, textViewResourceId);
        dataid=resource;
    }
    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View view= LayoutInflater.from(getContext()).inflate(dataid,parent,false);
        TextView textView=(TextView)view.findViewById(...);
        ImageView imageView=(ImageView)view.findViewById(...);
        return view;
    }
}

上述方法效率低在:getview方法中每次都把布局重新加载了一遍。而且可以看到上述方法中有个convertview一直闲着,他是用来把之前加载好的布局先进行缓存,以便之后重用。所以优化getview如下:

@Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View view;
        if(convertView==null){
        view= LayoutInflater.from(getContext()).inflate(dataid,parent,false);
        }else{
            view=convertView;
        }
        TextView textView=(TextView)view.findViewById(...);
        ImageView imageView=(ImageView)view.findViewById(...);
        return view;
    }

上面这个方法虽然不会在重复加载布局,但是有一个叫做findviewbyid的方法一直重复使用。这个方法会自上而下的遍历控件树,十分消耗内存,所以再借助一个viewholder来优化性能。viewholder类需要自己进行定义(内部类):

class ViewHolder{
private Textview textview;
private Imageview imageview;
}

具体如下:

public view getView(int position,View convertview,ViewGroup parent){
View view;
ViewHolder viewholder;
if(convertview== null){
view=LayoutInflater.from(getContext()).inflate(dataid,parent,false);
viewholder = new ViewHolder();
viewholder.textview=(Textview)view.findviewbyId(...);
viewholder.imageview=(Imageview)view.findviewbyId(...);
view.setTag(viewholder);     //将viewholder存储在view中
}else{
view = convertview;
viewholder= (ViewHolder)view.getTag();  //重新获取ViewHolder
}
return view;
}

view的setTag和getTag方法,存储和获取ViewHolder,不用每次重新加载都去调用findviewbyid方法。后续关于listiew的运用有缘再更新,接下来学习recyclerview.

二.Recyclerview

首先

recyclerview定义在了support库中,想用的话要先在build.gradle中添加依赖库。
dependencies{
...
compile 'com.android.support:recyclerview-v7:25.2.1'
...
}

然后

关于使用。基本和listview差不多,找几个方法说一哈:

  • ItemDecoration:添加item之间的分割线。
    addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
    也可以自己在style和drawable中定义分割线的颜色,这里先过。
  • LayoutManager :这是一个抽象类,系统提供了3个实现类:
    1 LinearLayoutManager 现行管理器,支持横向、纵向。
    2 GridLayoutManager 网格布局管理器。
    3 StaggeredGridLayoutManager 瀑布就式布局管理器。
  • ItemAnimator: 设置item动画
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());有机会用到再详细学习。

最后

在下学习的是第二行代码里面有详细介绍了横向滚动和瀑布式布局,在此整理下。

  • 横向布局就是利用了LinearLayoutManager实现:
LinearLayoutManager llm=new LinearLayoutManager(this);
llm.setorientation(LinearLayoutManager.HORIZONTAL);
recycleview.setLayoutManager(llm);
  • StaggeredGridLayoutManager 瀑布就式布局管理器:
StaggeredGridLayoutManager mmm=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
...

书中运用了一个Random方法看上去效果很明显这里就不赘述了。

最后

关于瀑布式布局的点击事件,重写了Adapter extends RecycleView.Adapter<...ViewHolder>,在ViewHolder中添加view的变量保存最外层布局实例,然后在onCreatedViewHolder()方法中添加点击时间就好了。具体项目以后做到再单独贴,书上的就不办过来了。

补充:

Recyclerview实际上是一个自定义的Viewgroup,子视图chilid对应着每一个RecyclerView的item。其中关于ItemDecoration类,可以优化它的视觉效果,具体的明天看心情写。

关于Recyclerview的界面跳转:

  • 由于Recyclerview是没有onclicklistener的,所以跳转的时候写在了adapter的onCreateViewHolder中,本人用的是intent的隐式:
 <activity android:name=".SecondActivity"
            android:theme="@style/AppTheme.Zero">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
  @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent,int viewtype){
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.car_item,parent,false);
        final ViewHolder viewHolder=new ViewHolder(view);
        viewHolder.carview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position=viewHolder.getAdapterPosition();
                Car car=mcarList.get(position);
                Toast.makeText(view.getContext(),"你点击了"+car.getCarname()
                ,Toast.LENGTH_SHORT).show();
                Intent intent=new Intent("android.intent.action.ACTION_START");
                view.getContext().startActivity(intent);
            }
        });

因为心情原因就不多说了直接看代码。

以前看书的时候没啥感觉看过就过了再复习一遍觉得印象更加深刻了,就先酱紫。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容