Android中用RxJava和ViewPager实现轮播图
前言
很多人要实现轮播图都会想到使用ViewPager + Handler来完成轮播图的效果。但是在RxJava快速发展的情况下,已经可以使用RxJava来代替Handler完成这样任务了。
下面我们就来介绍如何实现RxJava+ViewPager的轮播图。
效果图如下

ViewPager的操作
说到ViwePager应该大家都不陌生,它可以结合普通的View也可以结合Fragment一起使用。在此我也就不对它的使用方法进行过多的介绍了。直接开始介绍轮播的方法。
常见的轮播操作
private class ImageAdapter extends PagerAdapter{
private ArrayList<ImageView> viewlist;
public ImageAdapter(ArrayList<ImageView> viewlist) {
this.viewlist = viewlist;
}
@Override
public int getCount() {
//设置成最大,使用户看不到边界
return Integer.MAX_VALUE;
}
....
}
private static class ImageHandler extends Handler{
...
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
if (activity.handler.hasMessages(MSG_UPDATE_IMAGE)){
activity.handler.removeMessages(MSG_UPDATE_IMAGE);
}
switch (msg.what) {
case MSG_UPDATE_IMAGE:
currentItem++;
activity.viewPager.setCurrentItem(currentItem);
//准备下次播放
activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_KEEP_SILENT:
//只要不发送消息就暂停了
break;
case MSG_BREAK_SILENT:
activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_PAGE_CHANGED:
//记录当前的页号,避免播放的时候页面显示不正确。
currentItem = msg.arg1;
break;
default:
break;
}
}
...
}
以上就是比较常见的轮播图的代码,我只是在网上随便找的。首先它的代码中将PagerAdapter的getCount()返回了一个Integer.MAX_VALUE;它的目的是为了让图片一直的播放下去,但是在一些极限情况下还是会crash的,并且它返回的数量太大了在一定程度上对内存也造成了较大的消耗。其次我们可以看到handler的代码极其的冗杂,不仅多而且逻辑也比较麻烦。 现在我们针对刚才的问题来进行优化
更好的轮播操作
更好的无限播放:设置页卡视图列表时,在前后额外各加一个页卡。最前面加最后一张图片,最后面加第1张图片。然后每当切换到最前的页卡时,就替换成倒数第2个页卡;每当切换到最后的页卡时,就替换成第2个页卡。这样一来就形成了连贯,自然实现了无限滑动的功能。
1)设置ViewPager的视图列表时,在前后各加一个页卡。
for (int i = 0; i < count + 2; i++) {
if (i == 0) {// 将最前面一页设置成本来最后的那页
Glide.with(context).
load(imageTitleBeanList.get(count - 1).getImageUrl()).into(ivImage);
tvTitle.setText(imageTitleBeanList.get(count - 1).getTitle());
} else if (i == count + 1) {// 将最后面一页设置成本来最前的那页
Glide.with(context).
load(imageTitleBeanList.get(0).getImageUrl()).into(ivImage);
tvTitle.setText(imageTitleBeanList.get(0).getTitle());
} else {
Glide.with(context).
load(imageTitleBeanList.get(i - 1).getImageUrl()).into(ivImage);
tvTitle.setText(imageTitleBeanList.get(i - 1).getTitle());
}
// 将设置好的View添加到View列表中
viewList.add(view);
}
2)在监听ViewPager的页卡状态改变中,当滑动到第1个页卡时替换成倒数第2个页卡;当滑动到最后一个页卡时替换成第2个页卡。
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
// 闲置中
case ViewPager.SCROLL_STATE_IDLE:
// “偷梁换柱”
if (vpImageTitle.getCurrentItem() == 0) {
vpImageTitle.setCurrentItem(count, false);
} else if (vpImageTitle.getCurrentItem() == count + 1) {
vpImageTitle.setCurrentItem(1, false);
}
currentItem = vpImageTitle.getCurrentItem();
break;
}
}
Handler现在就该由RxJava来替代了。
Interval 操作符
创建一个按固定时间间隔发射整数序列的Observable

Interval操作符返回一个Observable,它按固定的时间间隔发射一个无限递增的整数序列。

RxJava将这个操作符实现为interval方法。它接受一个表示时间间隔的参数和一个表示时间单位的参数。
Javadoc: interval(long,TimeUnit)
Javadoc: interval(long,TimeUnit,Scheduler)
interval默认在computation调度器上执行。你也可以传递一个可选的Scheduler参数来指定调度器。
用RxJava取代Handler
public void start() {
mViewPagerSubscribe = Observable.interval(5, 5, TimeUnit.SECONDS) // 5s的延迟,5s的循环时间
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
// 进行轮播操作
if (mWeeklyMovieInfos != null && mWeeklyMovieInfos.size() > 0 && isAutoPlay) {
mCurrentPage++;
mWeeklyViewPager.setCurrentItem(mCurrentPage);
}
}
});
}
为了更好的用户体验,在用户进行滑动操作的时候,应该停止自动轮播
mPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//监听ViewPager的触摸事件,当用户按下的时候取消注册,当用户手抬起的时候再注册
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
stop();
break;
case MotionEvent.ACTION_UP:
start();
break;
}
return false;
}});
public void stop() {
if(mViewPagerSubscribe.isUnsubscribed()) {
mViewPagerSubscribe.unsubscribe();
}
}
总结
这篇文章主要是对ViewPager实现轮播图的一种总结。首先提出更好的轮播图的方法,其实讲解了RxJava中interval操作符的使用,最后用该操作符替换掉Handler完美实现轮播图。以上就是这篇文章的全部内容,希望本文的内容能对大家有所帮助,如果有疑问大家可以留言交流。
相关文章
Android中自定义ImageView添加文字设置按下效果详解
这篇文章主要给大家介绍了关于Android中自定义ImageView添加文字设置按下效果的相关资料,实现后的效果非常利用用户的体验,文中给出了详细的示例代码供大家参考学习,需要的朋友们下面随着小编来一起学习学习下吧。2017-08-08
Android 日历控件库,可左右滑动,显示公历,农历,节假日等功能
这篇文章主要介绍了Android 日历控件库,可左右滑动,显示公历,农历,节假日等功能的相关资料,需要的朋友可以参考下2016-09-09
Android开发Jetpack组件ViewModel与LiveData使用讲解
Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减少样板代码并编写可在各种Android版本和设备中一致运行的代码,让开发者精力集中编写重要的代码2022-09-09
Android用ListView显示SDCard文件列表的小例子
本文简单实现了用ListView显示SDCard文件列表,目录的回退等功能暂不讨论,获取文件列表,files即为所选择目录下的所有文件列表2013-11-11
android将图片转换存到数据库再从数据库读取转换成图片实现代码
有时候我们想把图片存入到数据库中,尽管这不是一种明智的选择,但有时候还是不得以会用到,下面说说将图片转换成byte[]数组存入到数据库中去,并从数据库中取出来转换成图像显示出来2013-11-11
FloatingActionButton增强版一个按钮跳出多个按钮第三方开源之FloatingActionButton
这篇文章主要介绍了FloatingActionButton增强版一个按钮跳出多个按钮第三方开源之FloatingActionButton 的相关资料,需要的朋友可以参考下2015-12-12


最新评论