Android中用RxJava和ViewPager实现轮播图

所属分类: 软件编程 / Android 阅读数: 34
收藏 0 赞 0 分享

前言

很多人要实现轮播图都会想到使用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中加入名片扫描功能实例代码

这篇文章主要介绍了Android中加入名片扫描功能实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android仿微信发表说说实现拍照、多图上传功能

这篇文章主要为大家详细介绍了Android仿微信发表说说实现拍照、多图上传功能,使用Retrofit2.0技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

设置Android系统永不锁屏永不休眠的方法

在进行Android系统开发的时候,有些特定的情况需要设置系统永不锁屏,永不休眠。本篇文章给大家介绍Android 永不锁屏,开机不锁屏,删除设置中休眠时间选项,需要的朋友一起学习吧
收藏 0 赞 0 分享

Android Retrofit 2.0框架上传图片解决方案

这篇文章主要介绍了Android Retrofit 2.0框架上传一张与多张图片解决方案,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android自定义等待对话框

这篇文章主要为大家详细介绍了Android自定义等待对话框的实现方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android中Window添加View的底层原理

这篇文章主要介绍了Android中Window添加View的底层原理,需要的朋友可以参考下
收藏 0 赞 0 分享

Android调用系统默认浏览器访问的方法

这篇文章主要介绍了Android调用系统默认浏览器访问的方法的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android开发退出程序的方法汇总

Android程序有很多Activity,比如说主窗口A,调用了子窗口B,子窗口B又调用子窗口C,back返回子窗口B后,在B中如何关闭整个Android应用程序呢? 下面脚本之家小编就给大家介绍android开发退出程序的几种方法,感兴趣的朋友参考下吧
收藏 0 赞 0 分享

Android程序开发中单选按钮(RadioGroup)的使用详解

在android程序开发中,无论是单选按钮还是多选按钮都非常的常见,接下来通过本文给大家介绍Android程序开发中单选按钮(RadioGroup)的使用,需要的朋友参考下吧
收藏 0 赞 0 分享

Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

这篇文章主要介绍了Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多