更好地理解关注点的分离.安卓系统



我是一名只有5个月经验的Android开发人员。我仍在学习,并努力做到最好。

现在我对Separation of concerns的概念很感兴趣。我确实理解它的含义,我正在尽我最大的努力在我的android开发中遵循它,然而,当我开始学习Clean Architecture时,我发现自己有点困惑。

我想展示我的代码,如果可能的话,当涉及到Separation of concerns时,我想得到一些关于我的实现及其正确性的反馈

代码[注意:我在这个应用程序中使用MVVM]:

PopularMoviesFragment:

class MoviesPopularFragment : Fragment() {
private val moviesViewModel: MoviesViewModel by activityViewModels()
private val adapter = PopularMoviesRecyclerAdapter()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = FragmentMoviesPopularBinding.inflate(inflater, container, false)
binding.viewModel = moviesViewModel
binding.popularMoviesRV.layoutManager = GridLayoutManager(requireContext(), 2)
binding.popularMoviesRV.adapter = adapter
moviesViewModel.popularMoviesState.observe(viewLifecycleOwner, { state ->
when (state) {
is PopularMoviesState.Content -> {
// TODO: Find a way to deal with this via DataBinding
binding.popularMoviesSwipeRefresh.isRefreshing = false
binding.progressBarLayout.visibility = View.GONE
binding.pageNavigation.visibility = View.VISIBLE
adapter.submitList(state.response.results)
}
is PopularMoviesState.Failure -> {
// TODO: Find a way to deal with this via DataBinding
binding.popularMoviesSwipeRefresh.isRefreshing = false
binding.progressBarLayout.visibility = View.GONE
binding.pageNavigation.visibility = View.VISIBLE
adapter.submitList(state.cachedListOfMovies)
showSnackbar(requireView(), getString(R.string.movies_popular_message_viewing_cached_content), Snackbar.LENGTH_INDEFINITE)
}
}
})
// TODO: Look into implementing this via DataBinding
binding.popularMoviesSwipeRefresh.setOnRefreshListener {
binding.popularMoviesSwipeRefresh.isRefreshing = true
moviesViewModel.fetchPopularMovies()
}
return binding.root
}
private fun showSnackbar(view: View, message: String, length: Int) {
val snackbar = Snackbar.make(view, message, length)
snackbar.animationMode = Snackbar.ANIMATION_MODE_SLIDE
snackbar.setAction(view.context.getString(R.string.alert_dialog_default_button_ok)) { snackbar.dismiss() }
snackbar.show()
}
}

电影ViewModel.kt:

fun fetchPopularMovies(page: Int = currentPage) {
viewModelScope.launch {
val result = MainRepository.fetchPopularMovies(page = page)
_popularMoviesState.value = when (result) {
is PopularMoviesState.Loading -> PopularMoviesState.Loading
is PopularMoviesState.Content -> {
//TODO: Perhaps find a way to work with pages in a better, more isolated way.
currentPage = result.response.page
PopularMoviesState.Content(result.response)
}
is PopularMoviesState.Failure -> {
PopularMoviesState.Failure(result.errorMessage, result.cachedListOfMovies)
}
}
}
}

主存储库.kt

suspend fun fetchPopularMovies(page: Int = 1) = try {
val response = IPopularMovies.getInstance().getMovies(page = page)
if (response.code() == 200) {
savePopularMoviesToCache(response.body()!!.results)
PopularMoviesState.Content(response.body()!!)
} else {
PopularMoviesState.Failure(response.body()!!.status_message, popularMovieDao.getMovies() ?: listOf())
}
} catch (error: Throwable) {
PopularMoviesState.Failure(error.localizedMessage!!, popularMovieDao.getMovies() ?: listOf())
}
private suspend fun savePopularMoviesToCache(listOfMovies: List<PopularMovie>) {
popularMovieDao.clearTable()
popularMovieDao.addMovies(listOfMovies)
}

我最感兴趣的是MainRepository及其对fetchPopularMovies的实现正如你所看到的,这个函数并不是只有一个作业,事实上,它根据所处的情况做很多事情

  1. 它使用改装接口获取电影->它应该做什么然后它要么:2.1.将电影保存到缓存或2.2.从缓存中获取电影

因此,如果我理解正确,如果我们遵循Separation of concerns,它并没有真正起到应有的作用。

以下是我认为正确的实现方式:

  1. 在MainRepository中,创建两个独立的函数。1用于将电影保存到缓存,1用于从缓存获取电影

  2. 在ViewModel中执行相同的操作并创建两个独立的函数。1用于保存到缓存。1用于从缓存中获取

  3. 在片段中,我们观察到。如果成功->调用ViewModel中的saveCache函数如果失败->调用ViewModel 中的getCache

请就我的思考过程给我一些反馈。我真的很感激!

存储库模块处理数据操作。这就是数据输入和输出,如果你这样想的话,关注点分离并不合适,因为这是两个单独的任务,但如果你把存储库看作数据和应用程序之间的媒介,那么这就是一个任务,关注点隔离是有意义的。

最新更新