LoginSignup
8
11

More than 5 years have passed since last update.

RxAndroidでSwipeRefreshLayoutを使う

Posted at
  • ListViewを使うときによくあるアクションとして下に引っ張って更新するPull to Refreshというような動きがありますが、AndroidではSupport LibraryからSwipeRefreshLayoutというものが提供されています。今回はこれをRxAndroidと一緒に使ってみました。
  • 今、Kotlinでアプリを書いているので、サンプルのコードもKotlinになっていますがJavaで適時置き換えてください。
  • 事前の準備は KotlinでRxAndroid1.0を使う を参照。

RxSwipeRefreshLayout

  • RxAndroidからはRxSwipeRefreshLayoutというBinding用のクラスが提供されています。
// refreshingはRefreshLayoutのプログレスを切り替えることができるAction1を返す
val refreshLayoutRefreshing = RxSwipeRefreshLayout.refreshing(refreshLayout)

// refreshesはProgress状態になったら配信されるObservable<void>を返す
val refreshLayoutStream = RxSwipeRefreshLayout.refreshes(refreshLayout)

試してみる

LayoutにSwipeRefreshLayoutを追加

  • SwipeRefreshLayoutでListViewを囲みます。
    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/list_event"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

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

Activityに実装

  • サンプルとしてAtndのAPIを叩いてイベント情報をObservableで返すというものを作っています。下に引っ張ったらプログレスが表示されて次ページ分が読み込まれるというサンプルになっています。
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        val view = inflater.inflate(R.layout.fragment_item, container, false)

        // ListViewにAdaptorとリスナをセット
        mListView = view.findViewById(R.id.list_event) as AbsListView
        mListView?.adapter = mAdapter
        mListView?.onItemClickListener = this

        // Observerを作成
        val observer = Observers.create<AtndApi.Companion.Entity>(
                { t ->
                    // onNext
                    mAdapter?.add(t.title)
                    mAdapter?.notifyDataSetChanged()
                },
                { e ->
                    // onError
                    println("Error!! ${e.message}")
                },
                {
                    // onComplete
                    mAdapter?.notifyDataSetChanged()
                })

        // Observableを作成
        // 配信時は新しいスレッド
        // 監視者はメインスレッド
        val observable = AtndApi.request(mWordForSearch, 1)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())

        val refreshLayout = view.findViewById(R.id.refresh) as SwipeRefreshLayout

        // ローディング中のプログレスの色を設定
        refreshLayout.setColorSchemeColors(Color.RED, Color.GREEN, Color.BLUE)
        refreshLayout.setProgressBackgroundColorSchemeColor(Color.LTGRAY)

        val refreshLayoutRefreshing = RxSwipeRefreshLayout.refreshing(refreshLayout)
        val refreshLayoutStream = RxSwipeRefreshLayout.refreshes(refreshLayout)

        // 購読を開始

        // 初回のAPIコール
        mSubscriptions.add(observable.subscribe(observer))

        // RefreshLayoutを監視
        mSubscriptions.add(refreshLayoutStream.subscribe({

            // ローディングが始まったらAPIコール
            val subscription = AtndApi.request(mWordForSearch, mAdapter?.count!! + 1)
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .finallyDo({
                        // 読み込みが終わったらRefreshLayoutのローディング状態を解除
                        refreshLayoutRefreshing.call(false)
                    })
                    .subscribe(observer)

            mSubscriptions.add(subscription)
        }))

        return view
    }

    override fun onDestroyView() {
        super.onDestroyView()

        // 購読を解除する
        mSubscriptions.unsubscribe()
    }
  • プログレスはこんな感じで表示されます。

スクリーンショット 2015-11-28 10.15.36.png

8
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
11