Skip to content

Commit

Permalink
feat: Add Pagination[skip ci]
Browse files Browse the repository at this point in the history
  • Loading branch information
aggarwalpulkit596 committed Apr 28, 2019
1 parent 2041862 commit 622903d
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 32 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'

//Paging
implementation "android.arch.paging:runtime:1.0.0-alpha5"

// Picasso
implementation 'com.squareup.picasso:picasso:2.71828'

Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/org/fossasia/openevent/general/di/Modules.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.fossasia.openevent.general.di

import androidx.paging.PagedList
import androidx.room.Room
import com.facebook.stetho.okhttp3.StethoInterceptor
import com.fasterxml.jackson.databind.DeserializationFeature
Expand Down Expand Up @@ -215,6 +216,16 @@ val networkModule = module {
objectMapper
}

single {
PagedList
.Config
.Builder()
.setPageSize(10)
.setInitialLoadSizeHint(10)
.setEnablePlaceholders(false)
.build()
}

single { RequestAuthenticator(get()) as Interceptor }

single {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ interface EventApi {
@GET("events?include=event-sub-topic,event-topic,event-type")
fun searchEvents(@Query("sort") sort: String, @Query("filter") eventName: String): Single<List<Event>>

@GET("events?include=event-sub-topic,event-topic,event-type")
fun searchEventsPaged(@Query("sort") sort: String, @Query("filter") eventName: String,@Query("page[number]") page: Int): Single<List<Event>>

@GET
fun getEvent(id: Long): Single<Event>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class EventService(
}
}


fun getFavoriteEvents(): Flowable<List<Event>> {
return eventDao.getFavoriteEvents()
}
Expand All @@ -100,6 +101,17 @@ class EventService(
}
}

fun getEventsByLocationPaged(locationName: String?,page:Int): Single<List<Event>> {
val query = "[{\"name\":\"location-name\",\"op\":\"ilike\",\"val\":\"%$locationName%\"}]"
return eventApi.searchEventsPaged("name", query,page).flatMap { apiList ->
val eventIds = apiList.map { it.id }.toList()
eventTopicsDao.insertEventTopics(getEventTopicList(apiList))
eventDao.getFavoriteEventWithinIds(eventIds).flatMap { favIds ->
updateFavorites(apiList, favIds)
}
}
}

fun updateFavorites(apiEvents: List<Event>, favEventIds: List<Long>): Single<List<Event>> {
apiEvents.map { if (favEventIds.contains(it.id)) it.favorite = true }
eventDao.insertEvents(apiEvents)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.fossasia.openevent.general.event

import androidx.lifecycle.MutableLiveData
import androidx.paging.DataSource
import io.reactivex.disposables.CompositeDisposable
import org.fossasia.openevent.general.event.faq.EventsDataSource

class EventsDataSourceFactory(private val compositeDisposable: CompositeDisposable,
private val eventService: EventService,
private val query:String?)
: DataSource.Factory<Int, Event>() {

val usersDataSourceLiveData = MutableLiveData<EventsDataSource>()

override fun create(): DataSource<Int, Event> {
val usersDataSource = EventsDataSource(eventService, compositeDisposable,query)
usersDataSourceLiveData.postValue(usersDataSource)
return usersDataSource
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package org.fossasia.openevent.general.event

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
`import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel
import androidx.paging.LivePagedListBuilder
import androidx.paging.PagedList
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
Expand All @@ -11,6 +14,7 @@ import org.fossasia.openevent.general.common.SingleLiveEvent
import org.fossasia.openevent.general.connectivity.MutableConnectionLiveData
import org.fossasia.openevent.general.data.Preference
import org.fossasia.openevent.general.data.Resource
import org.fossasia.openevent.general.event.faq.EventsDataSource
import org.fossasia.openevent.general.search.SAVED_LOCATION
import timber.log.Timber

Expand All @@ -28,37 +32,49 @@ class EventsViewModel(
val progress: LiveData<Boolean> = mutableProgress
private val mutableEvents = MutableLiveData<List<Event>>()
val events: LiveData<List<Event>> = mutableEvents
private val mutableEventsPaged = MutableLiveData<PagedList<Event>>()
val eventsPaged: LiveData<PagedList<Event>> = mutableEventsPaged
private val mutableError = SingleLiveEvent<String>()
val error: LiveData<String> = mutableError
private val mutableShowShimmerEvents = MutableLiveData<Boolean>()
val showShimmerEvents: LiveData<Boolean> = mutableShowShimmerEvents
var lastSearch = ""
private val mutableSavedLocation = MutableLiveData<String>()
val savedLocation: LiveData<String> = mutableSavedLocation
private lateinit var sourceFactory: EventsDataSourceFactory

fun loadLocation() {
mutableSavedLocation.value = preference.getString(SAVED_LOCATION)
}

fun loadLocationEvents() {
val config = PagedList.Config.Builder()
.setPageSize(20)
.setInitialLoadSizeHint(20)
.setEnablePlaceholders(true)
.build()
if (lastSearch != savedLocation.value) {
compositeDisposable.add(eventService.getEventsByLocation(mutableSavedLocation.value)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
mutableShowShimmerEvents.value = true
}
.doFinally {
mutableProgress.value = false
mutableShowShimmerEvents.value = false
lastSearch = mutableSavedLocation.value ?: ""
}.subscribe({
mutableEvents.value = it
}, {
Timber.e(it, "Error fetching events")
mutableError.value = resource.getString(R.string.error_fetching_events_message)
})
)
sourceFactory = EventsDataSourceFactory(compositeDisposable,eventService,mutableSavedLocation.value)
mutableEventsPaged = LivePagedListBuilder<Int, Event>(sourceFactory, config).build()

// compositeDisposable.add(eventService.getEventsByLocation(mutableSavedLocation.value)
// .subscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .doOnSubscribe {
// mutableShowShimmerEvents.value = true
// }
// .doFinally {
// mutableProgress.value = false
// mutableShowShimmerEvents.value = false
// lastSearch = mutableSavedLocation.value ?: ""
// }.subscribe({
// mutableEvents.value = it
// }, {
// Timber.e(it, "Error fetching events")
// mutableError.value = resource.getString(R.string.error_fetching_events_message)
// })
// )

} else {
mutableProgress.value = false
}
Expand All @@ -74,23 +90,20 @@ class EventsViewModel(
lastSearch = ""
}

fun loadEvents() {
compositeDisposable.add(eventService.getEvents()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
mutableProgress.value = true
}.doFinally {
mutableProgress.value = false
}.subscribe({
mutableEvents.value = it
}, {
Timber.e(it, "Error fetching events")
mutableError.value = resource.getString(R.string.error_fetching_events_message)
})
)
fun retry() {
sourceFactory.usersDataSourceLiveData.value!!.retry()
}

fun refresh() {
sourceFactory.usersDataSourceLiveData.value!!.invalidate()
}

fun getNetworkState(): LiveData<NetworkState> = Transformations.switchMap<EventsDataSource, NetworkState>(
sourceFactory.usersDataSourceLiveData) { it.networkState }

fun getRefreshState(): LiveData<NetworkState> = Transformations.switchMap<EventsDataSource, NetworkState>(
sourceFactory.usersDataSourceLiveData) { it.initialLoad }

fun setFavorite(eventId: Long, favorite: Boolean) {
compositeDisposable.add(eventService.setFavorite(eventId, favorite)
.subscribeOn(Schedulers.io())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.fossasia.openevent.general.event.faq

import androidx.paging.PageKeyedDataSource
import io.reactivex.disposables.CompositeDisposable
import org.fossasia.openevent.general.event.Event
import org.fossasia.openevent.general.event.EventService

class EventsDataSource(
private val eventsService: EventService,
private val compositeDisposable: CompositeDisposable,
val query:String?)
: PageKeyedDataSource<Int, Event>() {
private var sourceIndex: Int = 1
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Event>) {
compositeDisposable.add(eventsService.getEventsByLocationPaged(query,1).subscribe({ users ->
sourceIndex++
callback.onResult(users,null,sourceIndex)
}, { throwable ->}))
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Event>) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Event>) {
// // ignored, since we only ever append to our initial load
}
// override fun loadInitial(params: LoadInitialParams<Long>, callback: LoadInitialCallback<Event>) {

// }
//
// override fun loadAfter(params: LoadParams<Long>, callback: LoadCallback<User>) {
// //get the users from the api after id
// compositeDisposable.add(githubService.getUsers(params.key, params.requestedLoadSize).subscribe({ users ->
// callback.onResult(users)
// }, { throwable -> }))
// }
//
// override fun loadBefore(params: LoadParams<Long>, callback: LoadCallback<User>) {
// // ignored, since we only ever append to our initial load
// }
//
// override fun getKey(item: User): Long {
// return item.id
// }

}

0 comments on commit 622903d

Please sign in to comment.