Kotlin-Flow如何在Android项目中使用_android kt flow基本使用

75 阅读7分钟

import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.learn.base.ApiUserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_recycler_view.*

class ParallelNetworkCallsActivity : AppCompatActivity() {

private lateinit var viewModel: ParallelNetworkCallsViewModel
private lateinit var adapter: ApiUserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recycler_view)
    setupUI()
    setupViewModel()
    setupObserver()
}

private fun setupUI() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    adapter =
        ApiUserAdapter(
            arrayListOf()
        )
    recyclerView.addItemDecoration(
        DividerItemDecoration(
            recyclerView.context,
            (recyclerView.layoutManager as LinearLayoutManager).orientation
        )
    )
    recyclerView.adapter = adapter
}

private fun setupObserver() {
    viewModel.getUsers().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                it.data?.let { users -> renderList(users) }
                recyclerView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                recyclerView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun renderList(users: List<ApiUser>) {
    adapter.addData(users)
    adapter.notifyDataSetChanged()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(ParallelNetworkCallsViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.retrofit.parallel

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.zip import kotlinx.coroutines.launch

class ParallelNetworkCallsViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val users = MutableLiveData<Resource<List<ApiUser>>>()

init {
    fetchUsers()
}

private fun fetchUsers() {
    viewModelScope.launch {
        users.postValue(Resource.loading(null))
        apiHelper.getUsers()
            .zip(apiHelper.getMoreUsers()) { usersFromApi, moreUsersFromApi ->
                val allUsersFromApi = mutableListOf<ApiUser>()
                allUsersFromApi.addAll(usersFromApi)
                allUsersFromApi.addAll(moreUsersFromApi)
                return@zip allUsersFromApi
            }
            .flowOn(Dispatchers.Default)
            .catch { e ->
                users.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                users.postValue(Resource.success(it))
            }
    }
}

fun getUsers(): LiveData<Resource<List<ApiUser>>> {
    return users
}

}


* **Room数据库操作**:了解如何使用 Kotlin Flow 在数据库中获取或插入实体。当您在 Android 应用程序中使用房间数据库时,这很有用。
* 活动代码



package com.mindorks.kotlinFlow.learn.room

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.data.local.entity.User import com.mindorks.kotlinFlow.learn.base.UserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_recycler_view.*

class RoomDBActivity : AppCompatActivity() {

private lateinit var viewModel: RoomDBViewModel
private lateinit var adapter: UserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recycler_view)
    setupUI()
    setupViewModel()
    setupObserver()
}

private fun setupUI() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    adapter =
        UserAdapter(
            arrayListOf()
        )
    recyclerView.addItemDecoration(
        DividerItemDecoration(
            recyclerView.context,
            (recyclerView.layoutManager as LinearLayoutManager).orientation
        )
    )
    recyclerView.adapter = adapter
}

private fun setupObserver() {
    viewModel.getUsers().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                it.data?.let { users -> renderList(users) }
                recyclerView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                recyclerView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun renderList(users: List<User>) {
    adapter.addData(users)
    adapter.notifyDataSetChanged()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(RoomDBViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.room

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.data.local.entity.User import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch

class RoomDBViewModel(private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper) : ViewModel() {

private val users = MutableLiveData<Resource<List<User>>>()

init {
    fetchUsers()
}

private fun fetchUsers() {
    viewModelScope.launch {
        users.postValue(Resource.loading(null))
        dbHelper.getUsers()
            .flatMapConcat { usersFromDb ->
                if (usersFromDb.isEmpty()) {
                    return@flatMapConcat apiHelper.getUsers()
                        .map { apiUserList ->
                            val userList = mutableListOf<User>()
                            for (apiUser in apiUserList) {
                                val user = User(
                                    apiUser.id,
                                    apiUser.name,
                                    apiUser.email,
                                    apiUser.avatar
                                )
                                userList.add(user)
                            }
                            userList
                        }
                        .flatMapConcat { usersToInsertInDB ->
                            dbHelper.insertAll(usersToInsertInDB)
                                .flatMapConcat {
                                    flow {
                                        emit(usersToInsertInDB)
                                    }
                                }
                        }
                } else {
                    return@flatMapConcat flow {
                        emit(usersFromDb)
                    }
                }
            }
            .flowOn(Dispatchers.Default)
            .catch { e ->
                users.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                users.postValue(Resource.success(it))
            }
    }
}

fun getUsers(): LiveData<Resource<List<User>>> {
    return users
}

}


* **长时间运行的任务**:了解如何使用 Kotlin Flow 执行长时间运行的任务。如果您想使用 Kotlin Flow 在后台线程中执行任何任务,那么这很有用。
* 活动代码



package com.mindorks.kotlinFlow.learn.task.onetask

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_long_running_task.* import kotlinx.android.synthetic.main.activity_recycler_view.progressBar

class LongRunningTaskActivity : AppCompatActivity() {

private lateinit var viewModel: LongRunningTaskViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_long_running_task)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startLongRunningTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(LongRunningTaskViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.task.onetask

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch

class LongRunningTaskViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

fun startLongRunningTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        // do a long running task
        doLongRunningTask()
            .flowOn(Dispatchers.Default)
            .catch {
                status.postValue(Resource.error("Something Went Wrong", null))
            }
            .collect {
                status.postValue(Resource.success("Task Completed"))
            }
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

private fun doLongRunningTask(): Flow<Int> {
    return flow {
        // your code for doing a long running task
        // Added delay to simulate
        delay(5000)
        emit(0)
    }
}

}


* **两个长时间运行的任务**:了解如何使用 Kotlin Flow 并行运行两个长时间运行的任务。
* 活动代码



package com.mindorks.kotlinFlow.learn.task.twotasks

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_long_running_task.* import kotlinx.android.synthetic.main.activity_recycler_view.progressBar

class TwoLongRunningTasksActivity : AppCompatActivity() {

private lateinit var viewModel: TwoLongRunningTasksViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_long_running_task)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startLongRunningTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(TwoLongRunningTasksViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.task.twotasks

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch

class TwoLongRunningTasksViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

fun startLongRunningTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        doLongRunningTaskOne()
            .zip(doLongRunningTaskTwo()) { resultOne, resultTwo ->
                return@zip resultOne + resultTwo
            }
            .flowOn(Dispatchers.Default)
            .catch { e ->
                status.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                status.postValue(Resource.success(it))
            }
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

private fun doLongRunningTaskTwo(): Flow<String> {
    return flow {
        // your code for doing a long running task
        // Added delay to simulate
        delay(5000)
        emit("Two")
    }
}

private fun doLongRunningTaskOne(): Flow<String> {
    return flow {
        // your code for doing a long running task
        // Added delay to simulate
        delay(5000)
        emit("One")
    }
}

}


* **Catch 错误处理**:了解如何使用 Catch 处理 Kotlin Flow 中的错误。
* 活动代码



package com.mindorks.kotlinFlow.learn.errorhandling.catch

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.learn.base.ApiUserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_recycler_view.*

class CatchActivity : AppCompatActivity() {

private lateinit var viewModel: CatchViewModel
private lateinit var adapter: ApiUserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recycler_view)
    setupUI()
    setupViewModel()
    setupObserver()
}

private fun setupUI() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    adapter =
        ApiUserAdapter(
            arrayListOf()
        )
    recyclerView.addItemDecoration(
        DividerItemDecoration(
            recyclerView.context,
            (recyclerView.layoutManager as LinearLayoutManager).orientation
        )
    )
    recyclerView.adapter = adapter
}

private fun setupObserver() {
    viewModel.getUsers().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                it.data?.let { users -> renderList(users) }
                recyclerView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                recyclerView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun renderList(users: List<ApiUser>) {
    adapter.addData(users)
    adapter.notifyDataSetChanged()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(CatchViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.errorhandling.catch

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch

class CatchViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val users = MutableLiveData<Resource<List<ApiUser>>>()

init {
    fetchUsers()
}

private fun fetchUsers() {
    viewModelScope.launch {
        users.postValue(Resource.loading(null))
        apiHelper.getUsersWithError()
            .catch { e ->
                users.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                users.postValue(Resource.success(it))
            }
    }
}

fun getUsers(): LiveData<Resource<List<ApiUser>>> {
    return users
}

}


* **EmitAll 错误处理**:了解如何使用 emitAll 处理 Kotlin Flow 中的错误。
* 活动代码



package com.mindorks.kotlinFlow.learn.errorhandling.emitall

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.learn.base.ApiUserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_recycler_view.*

class EmitAllActivity : AppCompatActivity() {

private lateinit var viewModel: EmitAllViewModel
private lateinit var adapter: ApiUserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recycler_view)
    setupUI()
    setupViewModel()
    setupObserver()
}

private fun setupUI() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    adapter =
        ApiUserAdapter(
            arrayListOf()
        )
    recyclerView.addItemDecoration(
        DividerItemDecoration(
            recyclerView.context,
            (recyclerView.layoutManager as LinearLayoutManager).orientation
        )
    )
    recyclerView.adapter = adapter
}

private fun setupObserver() {
    viewModel.getUsers().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                it.data?.let { users -> renderList(users) }
                recyclerView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                recyclerView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun renderList(users: List<ApiUser>) {
    adapter.addData(users)
    adapter.notifyDataSetChanged()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(EmitAllViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.errorhandling.emitall

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.data.model.ApiUser import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch

class EmitAllViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val users = MutableLiveData<Resource<List<ApiUser>>>()

init {
    fetchUsers()
}

private fun fetchUsers() {
    viewModelScope.launch {
        users.postValue(Resource.loading(null))
        apiHelper.getUsers()
            .zip(
                apiHelper.getUsersWithError()
                    .catch { emitAll(flowOf(emptyList())) }) { usersFromApi, moreUsersFromApi ->
                val allUsersFromApi = mutableListOf<ApiUser>()
                allUsersFromApi.addAll(usersFromApi)
                allUsersFromApi.addAll(moreUsersFromApi)
                return@zip allUsersFromApi
            }
            .flowOn(Dispatchers.Default)
            .catch { e ->
                users.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                users.postValue(Resource.success(it))
            }
    }
}

fun getUsers(): LiveData<Resource<List<ApiUser>>> {
    return users
}

}


* **完成:**
* 活动代码



package com.mindorks.kotlinFlow.learn.completion

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.learn.base.ApiUserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_long_running_task.* import kotlinx.android.synthetic.main.activity_recycler_view.progressBar

class CompletionActivity : AppCompatActivity() {

private lateinit var viewModel: CompletionViewModel
private lateinit var adapter: ApiUserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_completion)
    setupViewModel()
    setupObserver()
}

private fun setupObserver() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(CompletionViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.completion

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.launch

class CompletionViewModel( private val apiHelper: ApiHelper, private val dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

init{
    fetchUsers()
}
private fun fetchUsers() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        apiHelper.getUsers()
            .catch { e ->
                status.postValue(Resource.error(e.toString(), null))
            }
            .onCompletion {
                status.postValue(Resource.success("Task Completed"))
            }
            .collect {
            }
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

}


* **减少:**
* 活动代码



package com.mindorks.kotlinFlow.learn.reduce

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_long_running_task.*

class ReduceActivity : AppCompatActivity() {

private lateinit var viewModel: ReduceViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_long_running_task)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startReduceTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(ReduceViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.reduce

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.reduce import kotlinx.coroutines.launch

class ReduceViewModel( val apiHelper: ApiHelper, dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

fun startReduceTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        val result = (1..5).asFlow()
            .reduce { a, b -> a + b }

        status.postValue(Resource.success(result.toString()))
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

}


* **地图:**
* 活动代码



package com.mindorks.kotlinFlow.learn.map

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.data.local.entity.User import com.mindorks.kotlinFlow.learn.base.UserAdapter import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_recycler_view.*

class MapActivity : AppCompatActivity() {

private lateinit var viewModel: MapViewModel
private lateinit var adapter: UserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recycler_view)
    setupUI()
    setupViewModel()
    setupObserver()
}

private fun setupUI() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    adapter =
        UserAdapter(
            arrayListOf()
        )
    recyclerView.addItemDecoration(
        DividerItemDecoration(
            recyclerView.context,
            (recyclerView.layoutManager as LinearLayoutManager).orientation
        )
    )
    recyclerView.adapter = adapter
}

private fun setupObserver() {
    viewModel.getUsers().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                it.data?.let { users -> renderList(users) }
                recyclerView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                recyclerView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
}

private fun renderList(users: List<User>) {
    adapter.addData(users)
    adapter.notifyDataSetChanged()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(MapViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.map

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.data.local.entity.User import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch

class MapViewModel( val apiHelper: ApiHelper, dbHelper: DatabaseHelper ) : ViewModel() {

private val users = MutableLiveData<Resource<List<User>>>()

init {
    fetchUsers()
}

private fun fetchUsers() {
    viewModelScope.launch {
        users.postValue(Resource.loading(null))
        apiHelper.getUsers()
            .map { apiUserList ->
                val userList = mutableListOf<User>()
                for (apiUser in apiUserList) {
                    val user = User(
                        apiUser.id,
                        apiUser.name,
                        apiUser.email,
                        apiUser.avatar
                    )
                    userList.add(user)
                }
                userList
            }
            .catch { e ->
                users.postValue(Resource.error(e.toString(), null))
            }
            .collect {
                users.postValue(Resource.success(it))
            }
    }
}

fun getUsers(): LiveData<Resource<List<User>>> {
    return users
}

}


* **筛选:**
* 活动代码



package com.mindorks.kotlinFlow.learn.filter

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_long_running_task.* import kotlinx.android.synthetic.main.activity_recycler_view.progressBar

class FilterActivity : AppCompatActivity() {

private lateinit var viewModel: FilterViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_long_running_task)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startFilterTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(FilterViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.filter

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch

class FilterViewModel( apiHelper: ApiHelper, dbHelper: DatabaseHelper ) : ViewModel() { private val status = MutableLiveData<Resource>()

fun startFilterTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        val result = mutableListOf<Int>()
        (1..5).asFlow()
            .filter {
                it % 2 == 0
            }
            .toList(result)

        status.postValue(Resource.success(result.toString()))
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

}


* **搜索功能**:使用 Kotlin Flow Operators 实现搜索 - Debounce、Filter、DistinctUntilChanged、FlatMapLatest。


	+ 活动代码



package com.mindorks.kotlinFlow.learn.search

import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.utils.getQueryTextChangeStateFlow import kotlinx.android.synthetic.main.activity_search.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlin.coroutines.CoroutineContext

class SearchActivity : AppCompatActivity(), CoroutineScope {

override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job

private lateinit var job: Job

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_search)
    job = Job()
    setUpSearchStateFlow()
}

override fun onDestroy() {
    job.cancel()
    super.onDestroy()
}

private fun setUpSearchStateFlow() {
    launch {
        searchView.getQueryTextChangeStateFlow()
            .debounce(300)
            .filter { query ->
                if (query.isEmpty()) {
                    textViewResult.text = ""
                    return@filter false
                } else {
                    return@filter true
                }
            }
            .distinctUntilChanged()
            .flatMapLatest { query ->
                dataFromNetwork(query)
                    .catch {
                        emitAll(flowOf(""))
                    }
            }
            .flowOn(Dispatchers.Default)
            .collect { result ->
                textViewResult.text = result
            }
    }
}

/**
 * Simulation of network data
 */
private fun dataFromNetwork(query: String): Flow<String> {
    return flow {
        delay(2000)
        emit(query)
    }
}

}


* **重试:**
* 活动代码



package com.mindorks.kotlinFlow.learn.retry

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_retry.*

class RetryActivity : AppCompatActivity() {

private lateinit var viewModel: RetryViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_retry)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(RetryViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.retry

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import java.io.IOException

class RetryViewModel( val apiHelper: ApiHelper, dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

fun startTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        // do a long running task
        doLongRunningTask()
            .flowOn(Dispatchers.Default)
            .retry(retries = 3) { cause ->
                if (cause is IOException) {
                    delay(2000)
                    return@retry true
                } else {
                    return@retry false
                }
            }
            .catch {
                status.postValue(Resource.error("Something Went Wrong", null))
            }
            .collect {
                status.postValue(Resource.success("Task Completed"))
            }
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

private fun doLongRunningTask(): Flow<Int> {
    return flow {
        // your code for doing a long running task
        // Added delay, random number, and exception to simulate

        delay(2000)

        val randomNumber = (0..2).random()

        if (randomNumber == 0) {
            throw IOException()
        } else if (randomNumber == 1) {
            throw IndexOutOfBoundsException()
        }

        delay(2000)
        emit(0)
    }
}

}


* **重试时间:**
* 活动代码



package com.mindorks.kotlinFlow.learn.retrywhen

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_retry.*

class RetryWhenActivity : AppCompatActivity() {

private lateinit var viewModel: RetryWhenViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_retry)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(RetryWhenViewModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.retrywhen

import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mindorks.kotlinFlow.data.api.ApiHelper import com.mindorks.kotlinFlow.data.local.DatabaseHelper import com.mindorks.kotlinFlow.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import java.io.IOException

class RetryWhenViewModel( val apiHelper: ApiHelper, dbHelper: DatabaseHelper ) : ViewModel() {

private val status = MutableLiveData<Resource<String>>()

fun startTask() {
    viewModelScope.launch {
        status.postValue(Resource.loading(null))
        // do a long running task
        doLongRunningTask()
            .flowOn(Dispatchers.Default)
            .retryWhen { cause, attempt ->
                if (cause is IOException && attempt < 3) {
                    delay(2000)
                    return@retryWhen true
                } else {
                    return@retryWhen false
                }
            }
            .catch {
                status.postValue(Resource.error("Something Went Wrong", null))
            }
            .collect {
                status.postValue(Resource.success("Task Completed"))
            }
    }
}

fun getStatus(): LiveData<Resource<String>> {
    return status
}

private fun doLongRunningTask(): Flow<Int> {
    return flow {
        // your code for doing a long running task
        // Added delay, random number, and exception to simulate

        delay(2000)

        val randomNumber = (0..2).random()

        if (randomNumber == 0) {
            throw IOException()
        } else if (randomNumber == 1) {
            throw IndexOutOfBoundsException()
        }

        delay(2000)
        emit(0)
    }
}

}


* **使用指数退避重试:**
* 活动代码



package com.mindorks.kotlinFlow.learn.retryexponentialbackoff

import android.os.Bundle import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.mindorks.kotlinFlow.R import com.mindorks.kotlinFlow.data.api.ApiHelperImpl import com.mindorks.kotlinFlow.data.api.RetrofitBuilder import com.mindorks.kotlinFlow.data.local.DatabaseBuilder import com.mindorks.kotlinFlow.data.local.DatabaseHelperImpl import com.mindorks.kotlinFlow.utils.Status import com.mindorks.kotlinFlow.utils.ViewModelFactory import kotlinx.android.synthetic.main.activity_retry.*

class RetryExponentialBackoffActivity : AppCompatActivity() {

private lateinit var viewModel: RetryExponentialBackoffModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_retry)
    setupViewModel()
    setupLongRunningTask()
}

private fun setupLongRunningTask() {
    viewModel.getStatus().observe(this, Observer {
        when (it.status) {
            Status.SUCCESS -> {
                progressBar.visibility = View.GONE
                textView.text = it.data
                textView.visibility = View.VISIBLE
            }
            Status.LOADING -> {
                progressBar.visibility = View.VISIBLE
                textView.visibility = View.GONE
            }
            Status.ERROR -> {
                //Handle Error
                progressBar.visibility = View.GONE
                Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show()
            }
        }
    })
    viewModel.startTask()
}

private fun setupViewModel() {
    viewModel = ViewModelProviders.of(
        this,
        ViewModelFactory(
            ApiHelperImpl(RetrofitBuilder.apiService),
            DatabaseHelperImpl(DatabaseBuilder.getInstance(applicationContext))
        )
    ).get(RetryExponentialBackoffModel::class.java)
}

}


* 视图模型代码



package com.mindorks.kotlinFlow.learn.retryexponentialbackoff