RecyclerView使用 及 滑动时加载图片优化方案,GitHub上标星13k的《Android面试突击版》

本文介绍了Android中RecyclerView的使用,包括设置固定大小以提高性能,使用线性LayoutManager,自定义Adapter。同时,文章讨论了滑动时加载图片的优化策略,如控制线程数量、数据分页加载,并提供了实现方案,包括重写onScrollStateChanged方法。此外,还分享了一个解决ScrollView嵌套RecyclerView显示问题的开源示例。

setContentView(R.layout.my_activity);

mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

// improve performance if you know that changes in content do not change the size of the RecyclerView

//如果确定每个item的内容不会改变RecyclerView的大小,设置这个选项可以提高性能

mRecyclerView.setHasFixedSize(true);

// use a linear layout manager

//创建默认的线性LayoutManager

mLayoutManager = new LinearLayoutManager(this);

mRecyclerView.setLayoutManager(mLayoutManager);

// specify an adapter (see also next example)

//设置Adapter

mAdapter = new MyAdapter(myDataset);

mRecyclerView.setAdapter(mAdapter);

}

}

LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。提供默认的动画效果,你也可以定义你自己的LayoutManager和添加删除动画。在回收或重用一个View时,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法。

2.MyAdapter

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

private String[] mDataset;

// Provide a reference to the type of views that you are using (custom viewholder)

//自定义的ViewHolder,持有每个Item的的所有界面元素

public static class ViewHolder extends RecyclerView.ViewHolder {

public TextView mTextView;

public ViewHolder(TextView v) {

super(v);

mTextView = v;

}

}

// Provide a suitable constructor (depends on the kind of dataset)

public MyAdapter(String[] myDataset) {

mDataset = myDataset;

}

// Create new views (invoked by the layout manager)

//创建新View,被LayoutManager调用

@Override

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,

int viewType) {

// create a new view

View v = LayoutInflater.from(parent.getContext())

.inflate(R.layout.my_text_view, parent, false);

// set the view’s size, margins, paddings and layout parameters

ViewHolder vh = new ViewHolder(v);

return vh;

}

// Replace the contents of a view (invoked by the layout manager)

//将数据与界面进行绑定

@Override

public void onBindViewHolder(ViewHolder holder, int position) {

// - get element from your dataset at this position

// - replace the contents of the view with that element

holder.mTextView.setText(mDataset[position]);

}

// Return the size of your dataset (invoked by the layout manager)

//这个就不解释了

@Override

public int getItemCount() {

return mDataset.length;

}

}

Adapter:在使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。

3.XML布局

<android.support.v7.widget.RecyclerView

android:id="@+id/my_recycler_view"

android:scrollbars=“vertical”

android:layout_width=“match_parent”

android:layout_height=“match_parent”/>

注: recyclerview No adapter attached; skipping layout 若出现该错误,是由于跳过了布局,没有Adapter与之对接的原因。

附:

①设置为横向的List:

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

②设置Grid布局列表,声明LayoutManager为GridLayoutManager即可:

mLayoutManager = new GridLayoutManager(context,columNum);

mRecyclerView.setLayoutManager(mLayoutManager);

③瀑布流布局

//使用StaggeredGridLayoutManager

从上述例子可以看出,RecyclerView的用法并不复杂,反而更灵活好用,它将数据、排列方式、数据的展示方式都分割开来,自定义的形式也非常多,非常灵活。下方共享一个开源示例,且解决了ScrollView嵌套RecyclerView无法显示的问题:

        

下载链接:http://download.youkuaiyun.com/detail/gao_chun/9124221

滑动时图片优化方案描述

===============

1、控制线程数量 + 数据分页加载

我们在使用滑动控件呈现图片数据时,显然都会在getView方法里创建新的线程去异步加载图片,不可能有一百条或上千条数据一口气全部塞过来吧(当然你要这么干也是可以的),那么根据项目需求必然会进行分页加载,咱一页显示的item条数也别太夸张就好。而且,当我们点击屏幕快速向下滑动时,每个Item都会调用getView一次,必然会创建出很多线程去加载图片的URL资源,控制好线程的数量,加个线程池就非常有必要了。为了避免OOM导致FC,注意图片需要缓存,因为从内存中读取图片资源是非常快的。

2、重写onScrollStateChanged方法

这种方案用的也很普遍,相信只要细心观察,就会发现类似微博、Facebook、或者一些图片壁纸类的APP,在滑动时未加载的图片是不会立刻加载呈现的,只有当滑动停止后才会加载,这里需要注意一点的是,只加载当前屏幕内的图片。这么一说可能有童鞋就明白了。我们可以通过继承RecyclerView去自定义一个滑动控件,通过继承OnScrollListener后重写其 onScrolled方法 和 onScrollStateChanged 等方法来做相应处理。

例如:

private class AutoLoadScrollListener extends OnScrollListener {

//…

public void onScrollStateChanged(RecyclerView recyclerView, int newState){

}

}

我们通过 extends OnScrollListener 并且 @Override 其 onScrollStateChanged 方法,通过判断state来处理,此处对其滚动的状态newState做一个说明,方面大家了解学习,分别有3个状态,即 0 - 1 - 2:

状态为0时:当前屏幕停止滚动;

状态为1时:屏幕在滚动 且 用户仍在触碰或手指还在屏幕上;

状态为2时:随用户的操作,屏幕上产生的惯性滑动;

实现

======

我们就不自己去写那些异步加载图片,缓存啥的代码块了,简单明了,直接使用ImageLoader就可以。下面通过实例讲解该功能的实现,老规矩,先来效果图:

先来瞄瞄activity_main.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:fitsSystemWindows=“true”

android:orientation=“vertical”>

<RelativeLayout

android:id="@+id/layout_titlebar"

android:layout_width=“match_parent”

android:layout_height=“48dp”

android:background="#00F1A0">

<TextView

android:textSize=“16dp”

android:id="@+id/text_title"

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:gravity=“center”

android:text=“好慌~”

android:textColor="@android:color/white" />

<FrameLayout

android:id="@+id/frame_container"

android:layout_width=“match_parent”

android:layout_height=“match_parent” />

很简单,用了一个Fragment而已,再来看看主Fragment的布局:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:background="@android:color/white">

<android.support.v4.widget.SwipeRefreshLayout

android:id="@+id/swipeRefreshLayout"

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

<org.gaochun.view.AutoLoadRecyclerView

android:id="@+id/recycler_view"

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:scrollbars=“vertical” />

</android.support.v4.widget.SwipeRefreshLayout>

我们使用了 SwipeRefreshLayout 中包裹了自定义的 AutoLoadRecyclerView,关于SwipeRefreshLayout 控件的使用,大家可以自行百度,这里就不多说了。有盆友可能会说,挖槽,好慌~ ,这测试图哪来的,貌似还挺清晰的哇,好吧,只能帮你到这了:

package org.gaochun.myapplication;

import java.util.ArrayList;

import java.util.List;

/**

  • Created by gao_chun on 2015/9/18.

*/

public class ImageUrl {

public static List imageList(){

List mUrls = new ArrayList();

mUrls.add(“http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg”);

mUrls.add(“http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg”);

mUrls.add(“http://h.hiphotos.baidu.com/image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg”);

mUrls.add(“http://g.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d5277fd5d0628535e5dd6f4a.jpg”);

mUrls.add(“http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg”);

mUrls.add(“http://b.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c81b94575cfb93eb13533fa40a2.jpg”);

mUrls.add(“http://e.hiphotos.baidu.com/image/pic/item/4bed2e738bd4b31c1badd5a685d6277f9e2ff81e.jpg”);

mUrls.add(“http://www.huabian.com/uploadfile/2014/1202/20141202025659854.jpg”);

mUrls.add(“http://www.huabian.com/uploadfile/2014/1202/20141202025700989.jpg”);

mUrls.add(“http://g.hiphotos.baidu.com/image/pic/item/0d338744ebf81a4c87a3add4d52a6059252da61e.jpg”);

mUrls.add(“http://a.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee5080c8142ff5e0fe99257e19.jpg”);

mUrls.add(“http://f.hiphotos.baidu.com/image/pic/item/4034970a304e251f503521f5a586c9177e3e53f9.jpg”);

mUrls.add(“http://b.hiphotos.baidu.com/image/pic/item/279759ee3d6d55fbb3586c0168224f4a20a4dd7e.jpg”);

mUrls.add(“http://img2.xkhouse.com/bbs/hfhouse/data/attachment/forum/corebbs/2009-11/2009113011534566298.jpg”);

mUrls.add(“http://a.hiphotos.baidu.com/image/pic/item/e824b899a9014c087eb617650e7b02087af4f464.jpg”);

mUrls.add(“http://c.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg”);

mUrls.add(“http://d.hiphotos.baidu.com/image/pic/item/b58f8c5494eef01f119945cbe2fe9925bc317d2a.jpg”);

mUrls.add(“http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg”);

mUrls.add(“http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg”);

mUrls.add(“http://a.hiphotos.baidu.com/image/pic/item/8d5494eef01f3a292d2472199d25bc315d607c7c.jpg”);

mUrls.add(“http://b.hiphotos.baidu.com/image/pic/item/e824b899a9014c08878b2c4c0e7b02087af4f4a3.jpg”);

mUrls.add(“http://g.hiphotos.baidu.com/image/pic/item/6d81800a19d8bc3e770bd00d868ba61ea9d345f2.jpg”);

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

以上分享【我的阿里P7移动开发架构师学习笔记】七大模块整套学习资料均免费分享,需要的小伙伴,我已经上传到石墨文档了,大家自取就可以了。白嫖可以,别忘了给我点个关注哈。

当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

如果你需要,我把他放在GitHub了,无偿分享的。

【Android架构视频+BATJ面试专题PDF+学习笔记】

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。

如果你需要,我把他放在GitHub了,无偿分享的。

【Android架构视频+BATJ面试专题PDF+学习笔记】

[外链图片转存中…(img-xzkaBw32-1645005428627)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值