前言
很多人要實(shí)現(xiàn)輪播圖都會想到使用ViewPager + Handler來完成輪播圖的效果。但是在RxJava快速發(fā)展的情況下,已經(jīng)可以使用RxJava來代替Handler完成這樣任務(wù)了。
下面我們就來介紹如何實(shí)現(xiàn)RxJava+ViewPager的輪播圖。
效果圖如下

ViewPager的操作
說到ViwePager應(yīng)該大家都不陌生,它可以結(jié)合普通的View也可以結(jié)合Fragment一起使用。在此我也就不對它的使用方法進(jìn)行過多的介紹了。直接開始介紹輪播的方法。
常見的輪播操作
private class ImageAdapter extends PagerAdapter{ private ArrayList<ImageView> viewlist; public ImageAdapter(ArrayList<ImageView> viewlist) { this.viewlist = viewlist; } @Override public int getCount() { //設(shè)置成最大,使用戶看不到邊界 return Integer.MAX_VALUE; } ....}private static class ImageHandler extends Handler{ ... @Override public void handleMessage(Message msg) { super.handleMessage(msg); //檢查消息隊(duì)列并移除未發(fā)送的消息,這主要是避免在復(fù)雜環(huán)境下消息出現(xiàn)重復(fù)等問題。 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); //準(zhǔn)備下次播放 activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY); break; case MSG_KEEP_SILENT: //只要不發(fā)送消息就暫停了 break; case MSG_BREAK_SILENT: activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY); break; case MSG_PAGE_CHANGED: //記錄當(dāng)前的頁號,避免播放的時(shí)候頁面顯示不正確。 currentItem = msg.arg1; break; default: break; } } ...}以上就是比較常見的輪播圖的代碼,我只是在網(wǎng)上隨便找的。首先它的代碼中將PagerAdapter的getCount()返回了一個(gè)Integer.MAX_VALUE;它的目的是為了讓圖片一直的播放下去,但是在一些極限情況下還是會crash的,并且它返回的數(shù)量太大了在一定程度上對內(nèi)存也造成了較大的消耗。其次我們可以看到handler的代碼極其的冗雜,不僅多而且邏輯也比較麻煩。 現(xiàn)在我們針對剛才的問題來進(jìn)行優(yōu)化
更好的輪播操作
更好的無限播放:設(shè)置頁卡視圖列表時(shí),在前后額外各加一個(gè)頁卡。最前面加最后一張圖片,最后面加第1張圖片。然后每當(dāng)切換到最前的頁卡時(shí),就替換成倒數(shù)第2個(gè)頁卡;每當(dāng)切換到最后的頁卡時(shí),就替換成第2個(gè)頁卡。這樣一來就形成了連貫,自然實(shí)現(xiàn)了無限滑動的功能。
1)設(shè)置ViewPager的視圖列表時(shí),在前后各加一個(gè)頁卡。
for (int i = 0; i < count + 2; i++) { if (i == 0) {// 將最前面一頁設(shè)置成本來最后的那頁 Glide.with(context). load(imageTitleBeanList.get(count - 1).getImageUrl()).into(ivImage); tvTitle.setText(imageTitleBeanList.get(count - 1).getTitle()); } else if (i == count + 1) {// 將最后面一頁設(shè)置成本來最前的那頁 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()); } // 將設(shè)置好的View添加到View列表中 viewList.add(view);}2)在監(jiān)聽ViewPager的頁卡狀態(tài)改變中,當(dāng)滑動到第1個(gè)頁卡時(shí)替換成倒數(shù)第2個(gè)頁卡;當(dāng)滑動到最后一個(gè)頁卡時(shí)替換成第2個(gè)頁卡。
@Overridepublic 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現(xiàn)在就該由RxJava來替代了。
Interval 操作符
創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable

Interval操作符返回一個(gè)Observable,它按固定的時(shí)間間隔發(fā)射一個(gè)無限遞增的整數(shù)序列。

RxJava將這個(gè)操作符實(shí)現(xiàn)為interval方法。它接受一個(gè)表示時(shí)間間隔的參數(shù)和一個(gè)表示時(shí)間單位的參數(shù)。
Javadoc: interval(long,TimeUnit)
Javadoc: interval(long,TimeUnit,Scheduler)
interval默認(rèn)在computation調(diào)度器上執(zhí)行。你也可以傳遞一個(gè)可選的Scheduler參數(shù)來指定調(diào)度器。
用RxJava取代Handler
public void start() { mViewPagerSubscribe = Observable.interval(5, 5, TimeUnit.SECONDS) // 5s的延遲,5s的循環(huán)時(shí)間 .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { // 進(jìn)行輪播操作 if (mWeeklyMovieInfos != null && mWeeklyMovieInfos.size() > 0 && isAutoPlay) { mCurrentPage++; mWeeklyViewPager.setCurrentItem(mCurrentPage); } } });}為了更好的用戶體驗(yàn),在用戶進(jìn)行滑動操作的時(shí)候,應(yīng)該停止自動輪播
mPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { //監(jiān)聽ViewPager的觸摸事件,當(dāng)用戶按下的時(shí)候取消注冊,當(dāng)用戶手抬起的時(shí)候再注冊 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(); }}總結(jié)
這篇文章主要是對ViewPager實(shí)現(xiàn)輪播圖的一種總結(jié)。首先提出更好的輪播圖的方法,其實(shí)講解了RxJava中interval操作符的使用,最后用該操作符替換掉Handler完美實(shí)現(xiàn)輪播圖。以上就是這篇文章的全部內(nèi)容,希望本文的內(nèi)容能對大家有所幫助,如果有疑問大家可以留言交流。
新聞熱點(diǎn)
疑難解答
圖片精選