android - 实现 MVVM LiveData RxJava Dagger Databinding 的正确结构?
问题描述
主要活动
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()
}
}
})
}
}
主视图模型工厂
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 中我调用接口方法并在 ViewModel 中实现它,也在响应中我将响应保存到 db。但是,这是一种私有方法,在单元测试中不能以适当的方式进行测试(因为它是私有的)。在完成一种方法时调用其他方法的最佳做法是什么,或者我必须在使用该接口的实现类中实现所有方法。
解决方案
如果您尝试遵循干净的架构模式,您的 ViewModel 不应该关心您如何获取数据。从本地或远程源获取数据的逻辑应该在存储库中,在最坏的情况下您还可以保存响应。在这种情况下,由于您有方法的联系人,您可以轻松地测试它们。理想情况下,您可以将其分解得更多——添加用例/交互器。
推荐阅读
- html - 如何叠加两张图像但将其定位为看起来像一张?
- c# - 什么是自定义修饰符?
- reactjs - 如何在 Reacjs 的输入中重置 defaultValue
- amazon-web-services - 如何设置 API Gateway 和集成私有 API 端点之间的连接
- json - 使用 ADF 数据流对大型 json 文件进行分区
- sql - 使用 string_to_array() 将字符串放在引号内
- python - Ursina 场景变化
- sql - 我需要构建一个可执行文件,我从哪里开始
- c# - Openiddict NET 4.8 ASP WebForm客户端,OWIN启动实现
- reporting-services - 具有固定源表达式的 SSRS LOOKUP