Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.59 KB | None | 0 0
  1. package me.alhaz.tutorial.architecturecomponent.helper
  2.  
  3. import androidx.annotation.MainThread
  4. import androidx.annotation.WorkerThread
  5. import androidx.lifecycle.LiveData
  6. import androidx.lifecycle.MediatorLiveData
  7. import me.alhaz.tutorial.architecturecomponent.helper.valueobject.ApiResponse
  8. import me.alhaz.tutorial.architecturecomponent.helper.valueobject.Resource
  9. import me.alhaz.tutorial.architecturecomponent.helper.valueobject.Status.SUCCESS
  10. import me.alhaz.tutorial.architecturecomponent.helper.valueobject.Status.ERROR
  11. import me.alhaz.tutorial.architecturecomponent.helper.valueobject.Status.EMPTY
  12.  
  13. abstract class NetworkBoundResource<ResultType, RequestType>
  14. @MainThread constructor(private val appExecutor: AppExecutors){
  15.  
  16. private val result = MediatorLiveData<Resource<ResultType>>()
  17.  
  18. init {
  19. result.value = Resource.empty(null)
  20. @Suppress("LeakingThis")
  21. val dbSource = loadFromDb()
  22. result.addSource(dbSource) { data ->
  23. result.removeSource(dbSource)
  24. if (shouldFetch(data)) {
  25. fetchFromNetwork(dbSource)
  26. }
  27. else {
  28. result.addSource(dbSource) { newData ->
  29. setValue(Resource.success(newData))
  30. }
  31. }
  32. }
  33. }
  34.  
  35. @MainThread
  36. private fun setValue(newValue: Resource<ResultType>) {
  37. if (result.value != newValue) {
  38. result.value = newValue
  39. }
  40. }
  41.  
  42. private fun fetchFromNetwork(dbSource: LiveData<ResultType>) {
  43.  
  44. val apiResponse: LiveData<ApiResponse<RequestType>> = createCall()
  45.  
  46. // we re-attach dbSource as a new source, it will dispatch its latest value quickly
  47. result.addSource(dbSource) { newData ->
  48. setValue(Resource.empty(newData))
  49. }
  50.  
  51. result.addSource(apiResponse) { response ->
  52.  
  53. result.removeSource(apiResponse)
  54. result.removeSource(dbSource)
  55.  
  56. when (response.status) {
  57.  
  58. EMPTY -> {
  59. appExecutor.mainThread().execute {
  60. result.addSource(loadFromDb()) { newData ->
  61. setValue(Resource.success(newData))
  62. }
  63. }
  64. }
  65.  
  66. SUCCESS -> {
  67. appExecutor.diskIO().execute {
  68. saveCallResult(response.body)
  69. appExecutor.mainThread().execute {
  70. result.addSource(loadFromDb()) { newData ->
  71. setValue(Resource.success(newData))
  72. }
  73. }
  74. }
  75. }
  76.  
  77. EMPTY -> {
  78. appExecutor.mainThread().execute {
  79. result.addSource(loadFromDb()) { newData ->
  80. setValue(Resource.success(newData))
  81. }
  82. }
  83. }
  84.  
  85. ERROR -> {
  86. onFetchFailed()
  87. result.addSource(dbSource) { newData ->
  88. setValue(Resource.error(response.message, newData))
  89. }
  90. }
  91. }
  92. }
  93. }
  94.  
  95. protected open fun onFetchFailed() {}
  96.  
  97. fun asLiveData() = result as LiveData<Resource<ResultType>>
  98.  
  99. @MainThread
  100. protected abstract fun loadFromDb(): LiveData<ResultType>
  101.  
  102. @MainThread
  103. protected abstract fun shouldFetch(data: ResultType?): Boolean
  104.  
  105. @MainThread
  106. protected abstract fun createCall(): LiveData<ApiResponse<RequestType>>
  107.  
  108. @WorkerThread
  109. protected abstract fun saveCallResult(item: RequestType)
  110.  
  111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement