본문 바로가기

안드로이드

[Android] MVVM, RxJava, Paging 활용한 리스팅

package com.drimase.pilgrimage.view

import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.drimase.pilgrimage.R
import com.drimase.pilgrimage.TourPageAdapter
import com.drimase.pilgrimage.TourViewModel
import com.drimase.pilgrimage.source.TourDataSource
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_item_list.view.*

class TourListFragment : Fragment() {
    private val tourViewModel :TourViewModel by viewModels()
    private val tourPageAdapter : TourPageAdapter = TourPageAdapter()
    private val compositeDisposable = CompositeDisposable()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_item_list, container, false)
        val disposable = tourViewModel.getPageListObservable().subscribe {it->
            tourPageAdapter.submitList(it)
            view.recyclerView.adapter = tourPageAdapter
        }
        compositeDisposable.add(disposable)
        return view
    }

    override fun onPause() {
        super.onPause()
        TourDataSource.pageNo=1
    }

    override fun onDestroy() {
        super.onDestroy()
        compositeDisposable.clear()
    }

    companion object{
        const val TAG="LIST FRAGMENT"
    }
}

 

package com.drimase.pilgrimage

import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.paging.PagedList
import androidx.paging.RxPagedListBuilder
import com.drimase.pilgrimage.entity.Tour
import com.drimase.pilgrimage.source.TourDataSourceFactory
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable

class TourViewModel(application: Application) : AndroidViewModel(application) {
    private val repository = Repository(application)
    private val compositeDisposable = CompositeDisposable()
    private var tourDataSourceFactory :TourDataSourceFactory  = TourDataSourceFactory(repository,compositeDisposable)

    private val config = PagedList.Config.Builder()
            .setPageSize(10)
            .setInitialLoadSizeHint(10)
            .setPrefetchDistance(10)
            .setEnablePlaceholders(true)
            .build()

    private var pagedListObservable: Observable<PagedList<Tour>> =RxPagedListBuilder(tourDataSourceFactory,config).buildObservable()


    override fun onCleared() {
        compositeDisposable.clear()
        super.onCleared()
    }

    fun getPageListObservable() : Observable<PagedList<Tour>> = pagedListObservable

    companion object {
        const val TAG = "TourViewModel"
    }
}

 

package com.drimase.pilgrimage.data

import androidx.paging.DataSource
import com.drimase.pilgrimage.data.dto.Tour
import io.reactivex.disposables.CompositeDisposable

class TourDataSourceFactory(
        private val repository: Repository,
        private val compositeDisposable: CompositeDisposable
):DataSource.Factory<Int, Tour>(){
    override fun create(): DataSource<Int, Tour> {
        return TourDataSource(repository,compositeDisposable)
    }
}

 

package com.drimase.pilgrimage.source

import android.util.Log
import androidx.paging.PageKeyedDataSource
import com.drimase.pilgrimage.Repository
import com.drimase.pilgrimage.entity.Tour
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers

class TourDataSource(
        private val repository: Repository,
        private val compositeDisposable: CompositeDisposable)
    : PageKeyedDataSource<Int, Tour>(){

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Tour>) {
        val disposable = repository.getTours(pageNo)
                .subscribe{it ->
                    pageNo++
                    callback.onResult(it.body.items.item, null, pageNo)
                    Log.i(TAG,pageNo.toString())
                }
        compositeDisposable.add(disposable)
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Tour>) {
        //do nothing
        val disposable = repository.getTours(params.key)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { it->
                    pageNo--
                    callback.onResult(it.body.items.item, pageNo)
                    Log.i(TAG,pageNo.toString())
                }
        compositeDisposable.add(disposable)
    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Tour>) {
        val disposable = repository.getTours(params.key)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { it->
                    pageNo++
                    callback.onResult(it.body.items.item, pageNo)
                    Log.i(TAG,pageNo.toString())
                }
        compositeDisposable.add(disposable)
    }

    companion object{
        var pageNo =1
        const val TAG = "TourItemDataSource"
    }
}