implement viewmodel, domain layer and view layer for userlist

This commit is contained in:
Carlos Martinez
2020-02-03 13:01:55 -03:00
parent 7d4432278e
commit 259955ed5d
26 changed files with 305 additions and 76 deletions

View File

@@ -0,0 +1,17 @@
package com.hako.friendlist.di
import com.hako.base.domain.network.RemoteClient
import com.hako.friendlist.domain.datasource.UserlistDatasource
import com.hako.friendlist.domain.datasource.UserlistRemoteApi
import com.hako.friendlist.domain.usecase.GetUsers
import com.hako.friendlist.viewmodel.UserlistViewmodel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val userlistModules = module {
factory { get<RemoteClient>().getClient(UserlistRemoteApi::class.java) }
factory { UserlistDatasource() }
factory { GetUsers(get()) }
viewModel { UserlistViewmodel() }
}

View File

@@ -0,0 +1,13 @@
package com.hako.friendlist.domain.datasource
import com.hako.friendlist.model.User
import io.reactivex.Single
import org.koin.core.KoinComponent
import org.koin.core.get
class UserlistDatasource : KoinComponent, UserlistRemoteApi {
private val api: UserlistRemoteApi = get()
override fun getUsers(): Single<List<User>> = api.getUsers()
}

View File

@@ -0,0 +1,11 @@
package com.hako.friendlist.domain.datasource
import com.hako.friendlist.model.User
import io.reactivex.Single
import retrofit2.http.GET
interface UserlistRemoteApi {
@GET("/users")
fun getUsers(): Single<List<User>>
}

View File

@@ -0,0 +1,43 @@
package com.hako.friendlist.domain.usecase
import com.hako.base.domain.UseCase
import com.hako.base.domain.database.dao.UserDao
import com.hako.friendlist.domain.datasource.UserlistDatasource
import com.hako.friendlist.model.UserViewable
import com.hako.friendlist.model.toUserEntity
import com.hako.friendlist.model.toUserViewable
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import org.koin.core.KoinComponent
import org.koin.core.get
class GetUsers(private val dao: UserDao) : KoinComponent,
UseCase<UserViewable> {
private val api: UserlistDatasource = get()
override fun execute(
onSuccess: (List<UserViewable>) -> Unit,
onError: (Throwable) -> Unit,
onLoading: () -> Unit
) {
Single.fromCallable { dao.getAllUsers() }
.subscribeOn(Schedulers.io())
.doOnError { onError(it) }
.doOnSuccess { dbUsers ->
if (dbUsers.isEmpty() || dbUsers.count() == 0) {
api.getUsers()
.doOnSuccess {
dao.saveAll(it.map { user -> user.toUserEntity() })
onSuccess(dao.getAllUsers().map { user -> user.toUserViewable() })
}
.doOnSubscribe { onLoading() }
.subscribeOn(Schedulers.io())
.subscribe({}, { onError(it) })
} else {
onSuccess(dbUsers.map { it.toUserViewable() })
}
}
.subscribe()
}
}

View File

@@ -6,14 +6,20 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.hako.base.domain.network.RequestStatus
import com.hako.base.extensions.observeNonNull
import com.hako.base.extensions.toast
import com.hako.friendlist.model.UserViewable
import com.hako.friendlist.viewmodel.UserlistViewmodel
import com.hako.friendlist.widget.UserlistAdapter
import com.hako.friendlist_userlist.R
import kotlinx.android.synthetic.main.fragment_userlist.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber
class UserlistFragment : Fragment() {
private val viewModel: UserlistViewmodel by viewModel()
private val chatAdapter by lazy { UserlistAdapter() }
override fun onCreateView(
@@ -23,37 +29,37 @@ class UserlistFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setRecycler()
setObservers()
viewModel.fetchUsers()
}
private fun setObservers() {
viewModel.data.observeNonNull(this) {
it.either(::handleFetchError, ::handleFetchSuccess)
}
viewModel.requestStatus.observeNonNull(this) {
when (it) {
RequestStatus.Ready -> { context?.toast("Ready") }
RequestStatus.Loading -> { context?.toast("Loading") }
RequestStatus.Errored -> { context?.toast("Errored") }
}
}
}
private fun handleFetchError(throwable: Throwable) {
context?.toast("Could't get data")
Timber.e(throwable)
}
private fun handleFetchSuccess(users: List<UserViewable>) {
chatAdapter.addAll(users)
}
private fun setRecycler() {
fragment_userlist_recycler_container.apply {
layoutManager = LinearLayoutManager(context)
adapter = chatAdapter.apply {
addAll(
listOf(
UserViewable(1, "Carlos Martinez", "carlitos"),
UserViewable(2, "Carlos Martinez", "carlitos"),
UserViewable(3, "Carlos Martinez", "carlitos"),
UserViewable(4, "Carlos Martinez", "carlitos"),
UserViewable(5, "Carlos Martinez", "carlitos"),
UserViewable(6, "Carlos Martinez", "carlitos"),
UserViewable(7, "Carlos Martinez", "carlitos"),
UserViewable(8, "Carlos Martinez", "carlitos"),
UserViewable(9, "Carlos Martinez", "carlitos"),
UserViewable(10, "Carlos Martinez", "carlitos"),
UserViewable(11, "Carlos Martinez", "carlitos"),
UserViewable(12, "Carlos Martinez", "carlitos"),
UserViewable(13, "Carlos Martinez", "carlitos"),
UserViewable(14, "Carlos Martinez", "carlitos"),
UserViewable(15, "Carlos Martinez", "carlitos"),
UserViewable(16, "Carlos Martinez", "carlitos"),
UserViewable(17, "Carlos Martinez", "carlitos"),
UserViewable(18, "Carlos Martinez", "carlitos"),
UserViewable(19, "Carlos Martinez", "carlitos"),
UserViewable(20, "Carlos Martinez", "carlitos")
)
)
onItemClick = {
context.toast(it.realName)
}

View File

@@ -2,7 +2,7 @@ package com.hako.friendlist.model
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import com.hako.base.room.entities.UserEntity
import com.hako.base.domain.database.entities.UserEntity
import kotlinx.android.parcel.Parcelize
@Parcelize
@@ -20,9 +20,9 @@ data class UserViewable(
val realName: String,
val userName: String,
var isFavorite: Boolean = false
) {
fun User.toUserViewable() = UserViewable(this.id, this.realName, this.userName)
)
fun UserEntity.toUserViewable() = UserViewable(this.id, this.realName, this.userName)
}
fun User.toUserEntity() = UserEntity(this.id, this.realName, this.userName, this.email, this.phone, this.website)
fun UserEntity.toUserViewable() = UserViewable(this.id, this.realName, this.userName)

View File

@@ -0,0 +1,36 @@
package com.hako.friendlist.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.hako.base.domain.network.RequestStatus
import com.hako.base.domain.network.RequestStatus.Ready
import com.hako.base.domain.network.RequestStatus.Loading
import com.hako.base.domain.network.RequestStatus.Errored
import com.hako.base.domain.Either
import com.hako.friendlist.domain.usecase.GetUsers
import com.hako.friendlist.model.UserViewable
import org.koin.core.KoinComponent
import org.koin.core.get
class UserlistViewmodel : ViewModel(), KoinComponent {
val data = MutableLiveData<Either<Throwable, List<UserViewable>>>()
val requestStatus = MutableLiveData<RequestStatus>()
private val getUsers: GetUsers = get()
fun fetchUsers() {
getUsers.execute(
onSuccess = {
requestStatus.postValue(Ready)
data.postValue(Either.Right(it))
},
onLoading = {
requestStatus.postValue(Loading)
},
onError = {
requestStatus.postValue(Errored)
data.postValue(Either.Left(it))
})
}
}