android - 实现 MVVM LiveData RxJava Dagger 数据绑定(bind)的正确结构?

标签 android data-binding rx-java2 android-livedata dagger

主 Activity

class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var mainViewModelFactory: mainViewModelFactory
    private lateinit var mainActivityBinding: ActivityMainBinding
    private lateinit var mainViewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mainActivityBinding = DataBindingUtil.setContentView(
                this,
                R.layout.activity_main
        )

        mainActivityBinding.rvmainRepos.adapter = mainAdapter
        AndroidInjection.inject(this)
        mainViewModel =
                ViewModelProviders.of(
                        this@MainActivity,
                        mainViewModelFactory
                )[mainViewModel::class.java]
        mainActivityBinding.viewmodel = mainViewModel
        mainActivityBinding.lifecycleOwner = this
        mainViewModel.mainRepoReponse.observe(this, Observer<Response> {
            repoList.clear()
            it.success?.let { response ->
                if (!response.isEmpty()) {
                    //     mainViewModel.saveDataToDb(response)
                    //     mainViewModel.createWorkerForClearingDb()
                }
            }
        })
    }
}

MainViewModelFactory

class MainViewModelFactory @Inject constructor(
        val mainRepository: mainRepository
) : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>) =
            with(modelClass) {
                when {
                    isAssignableFrom(mainViewModel::class.java) -> mainViewModel(
                            mainRepository = mainRepository
                    )
                    else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
                }
            } as T
}

主视图模型

class MainViewModel(
        val mainRepository: mainRepository
) : ViewModel() {

    private val compositeDisposable = CompositeDisposable()
    val mainRepoReponse = MutableLiveData<Response>()
    val loadingProgress: MutableLiveData<Boolean> = MutableLiveData()
    val _loadingProgress: LiveData<Boolean> = loadingProgress
    val loadingFailed: MutableLiveData<Boolean> = MutableLiveData()
    val _loadingFailed: LiveData<Boolean> = loadingFailed
    var isConnected: Boolean = false

    fun fetchmainRepos() {
        if (isConnected) {
            loadingProgress.value = true
            compositeDisposable.add(
                    mainRepository.getmainRepos().subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe({ response ->
                                run {
                                    saveDataToDb(response)
                                    )
                                }
                            },
                                    { error ->
                                        processResponse(Response(AppConstants.Status.SUCCESS, null, error))
                                    }
                            )
            )
        } else {
            fetchFromLocal()
        }
    }

    private fun saveDataToDb(response: List<mainRepo>) {
        mainRepository.insertmainUsers(response)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(object : DisposableCompletableObserver() {
                    override fun onComplete() {
                        Log.d("Status", "Save Success")
                    }

                    override fun onError(e: Throwable) {
                        Log.d("Status", "error ${e.localizedMessage}")
                    }
                })
    }
}

主存储库

interface MainRepository {

    fun getmainRepos(): Single<List<mainRepo>>

    fun getAllLocalRecords(): Single<List<mainRepo>>

    fun insertmainUsers(repoList: List<mainRepo>): Completable
}

MainRepositoryImpl

class mainRepositoryImpl @Inject constructor(
        val apiService: GitHubApi,
        val mainDao: AppDao
) : MainRepository {

    override fun getAllLocalRecords(): Single<List<mainRepo>> = mainDao.getAllRepos()

    override fun insertmainUsers(repoList: List<mainRepo>) :Completable{
        return   mainDao.insertAllRepos(repoList)
    }

    override fun getmainRepos(): Single<List<mainRepo>> {
        return apiService.getmainGits()
    }
}

我对使用 LiveData 和 Rxjava 实现 MVVM 感到很困惑,在我的 MainViewModel 中我调用接口(interface)方法并在 ViewModel 中实现它,同样在响应中我将响应保存到 db。但是,这是一种私有(private)方法,无法以适当的方式在单元测试中对其进行测试(因为它是私有(private)的)。在一个方法完成时调用其他方法的最佳做法是什么,或者我必须在使用该接口(interface)的实现类中实现所有方法。

最佳答案

如果您尝试遵循干净的架构模式,您的 ViewModel 不应该关心您如何获取数据。在最坏的情况下,从本地或远程源获取数据的逻辑应该在存储库中,您还可以在存储库中保存响应。在那种情况下,由于您有这些方法的联系人,您可以轻松地测试它们。理想情况下,您可以进一步分解它 - 添加用例/交互器。

关于android - 实现 MVVM LiveData RxJava Dagger 数据绑定(bind)的正确结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58109723/

相关文章:

android - 进行 rxJava 网络调用并根据响应在 UI 线程上推进工作的最佳方法是什么

wpf - 字符串格式整数,带逗号,无小数位,无0值

c# - 如何使用 INotifyPropertyChanged 更新列表框项目

java - Android 数据与库模块中的 <include> 标签绑定(bind)

找不到android对命令(无线调试)

java - RX Java 2,接受要添加的新值的 Observable

android - 带 RxJava2 的房间 -(可流动、可能、存储库模式)

android - 如何以编程方式访问设备设置?

android - 如何解决此错误 : ClassCastException: com. android.layoutlib.bridge.MockView cannot be cast to android.view.ViewGroup

android - Google Play 的隐私政策链接