简体   繁体   English

Android ViewModel设计/架构

[英]Android ViewModel design/architecture

I'm an android beginner, and just looking for some advice with regard to app architecture - specifically relating to using ViewModels. 我是一个Android初学者,只是寻找有关应用程序架构的一些建议 - 特别是与使用ViewModels有关。 There is no local database, each screen issues a new network request. 没有本地数据库,每个屏幕都会发出新的网络请求。 I'll look to implement room or something similar later. 我会期待稍后实施房间或类似的东西。

Main Activity (Movie List) 主要活动(电影列表)

I have an activity with a 100% size recycle view showing a list of movies, each movie in the recyclerview has a cover image that the user can touch on to be navigated to a player view. 我有一个100%大小的回收视图活动,显示电影列表,recyclerview中的每个电影都有一个封面图像,用户可以触摸该图像以导航到播放器视图。 The MainActivity (and it's recycler view) is backed by a ViewModel. MainActivity(以及它的回收站视图)由ViewModel支持。 The Movie object (wrapped by LiveData) has things you'd expect, like title, category, cover image, url to the mp4 file. Movie对象(由LiveData包装)具有您期望的内容,例如标题,类别,封面图像,mp4文件的URL。

private val movies = MutableLiveData<List<Movie>>()

To transition to PlayerActivity, the intent passes the ID of the selected movie as a string extra. 要转换为PlayerActivity,意图将所选影片的ID作为字符串额外传递。

PlayerActivity PlayerActivity

When a movie cell in the recycler view of the MainActivity is selected, I create a new intent to transition to the PlayerActivity where the movie is played. 当选择MainActivity的Recycler视图中的影片单元格时,我创建了一个新的意图,以转换到播放影片的PlayerActivity。 There is an imageView with the movie cover image displayed here too. 还有一个带有电影封面图像的imageView。 This view is also backed by a ViewModel. 此视图也由ViewModel支持。

private val selectedMovie = MutableLiveData<Movie>()

In OnCreate() I get the movie_id string extra from the intent, and create the ViewModel (and the ViewModel does a network request using the movie_id). 在OnCreate()中,我从intent获取额外的movie_id字符串,并创建ViewModel(并且ViewModel使用movie_id执行网络请求)。 This view also has a button that, when touched, transitions the user to a ScreenshotActivity. 该视图还有一个按钮,当触摸时,将用户转换为ScreenshotActivity。 The intent to transition to the ScreenshotActivity also passes the movie_id as a string extra. 转换到ScreenshotActivity的意图也将movie_id作为字符串额外传递。

ScreenshotActivity ScreenshotActivity

Has a recyclerview of screenshots for the movie displayed, and when touched, a network request is sent back to the server to update the cover image of the movie with one of those screenshots. 具有显示电影的屏幕截图的回收视图,并且当被触摸时,网络请求被发送回服务器以使用这些屏幕截图之一来更新电影的封面图像。 This activity takes the movie_id extra from the PlayerActivity intent to setup the view. 此活动从PlayerActivity意图获取movie_id extra以设置视图。

Questions 问题

  1. It's obviously pretty wasteful to do a network request each time, and I understand I should probably use something like room to cache this information locally. 每次做一个网络请求显然是相当浪费的,我知道我应该使用像空间这样的东西在本地缓存这些信息。 In the absense of a local database, is there a better way to do what I'm doing above with ViewModels? 在缺乏本地数据库的情况下,有没有更好的方法来完成我在ViewModel上面做的事情? Perhaps a single viewmodel that can be accessed by all of the 3 activities above? 也许是上面所有3个活动都可以访问的单个视图模型? In doing so, changes could be made directly to the movie object and syncd across all views? 这样做,可以直接对电影对象进行更改并在所有视图中同步? Any good examples on how to do this? 关于如何做到这一点的任何好例子?
  2. Given my current 3x ViewModels for 3x Activities, how can I notify the MainActivity to update the screenshot, and the PlayerActivity to update the coverimage (on the player) when a screenshot is updated in the ScreenshotActivity? 鉴于我当前的3x ViewModel for 3x Activities,如何在ScreenshotActivity中更新屏幕截图时通知MainActivity更新屏幕截图,以及PlayerActivity更新coverimage(在播放器上)?

It's obviously pretty wasteful to do a network request each time, and I understand I should probably use something like room to cache this information locally. 每次做一个网络请求显然是相当浪费的,我知道我应该使用像空间这样的东西在本地缓存这些信息。

Well it just depends on the size of your network requests. 那么它只取决于您的网络请求的大小。 Are they several megabytes? 它们几兆? Then yes, I would cache some of the images of the movie locally. 然后是的,我会在本地缓存一些电影的图像。

In the absense of a local database, is there a better way to do what I'm doing above with ViewModels? 在缺乏本地数据库的情况下,有没有更好的方法来完成我在ViewModel上面做的事情? Perhaps a single viewmodel that can be accessed by all of the 3 activities above? 也许是上面所有3个活动都可以访问的单个视图模型?

Well, I think that your current approach is not that bad at all, I think we should take a look at the API. 好吧,我认为你目前的做法并不是那么糟糕,我想我们应该看看API。 In your MovieList your get all data of the movies right? 在您的MovieList您可以获得所有电影数据吗? I think at that moment you should minify the data sent by the API. 我想在那一刻你应该缩小API发送的数据。 Then when selecting only one movie, download the content such as screenshots and cache it locally. 然后,当只选择一部电影时,下载屏幕截图等内容并在本地缓存。 If you can't edit the API, then yes, I would suggest you to download all the content you need and reuse that as much as possible. 如果您无法编辑API,那么我建议您下载所需的所有内容并尽可能地重复使用。

Since your data is already in private val movies = MutableLiveData<List<Movie>>() , why wouldn't you just pass the selected Movie to the PlayerActivity ? 由于您的数据已经在private val movies = MutableLiveData<List<Movie>>() ,为什么不将选定的Movie传递给PlayerActivity

Also note that I would not recommend you to use the same ViewModel for several Activities. 另请注意,我不建议您对多个活动使用相同的ViewModel Each Activity depends on it's own. 每个Activity取决于它自己。

In doing so, changes could be made directly to the movie object and syncd across all views? 这样做,可以直接对电影对象进行更改并在所有视图中同步? Any good examples on how to do this? 关于如何做到这一点的任何好例子?

Well the app Telegram has some nice ObserverPattern , I use it a lot in my apps. 应用程序Telegram有一些不错的ObserverPattern ,我在我的应用程序中使用了很多。 See this class: NotificationCenter.java . 请参阅此类: NotificationCenter.java This allows an Activity to subscribe to events. 这允许Activity订阅事件。 If another method calls an event all subscribers gets triggered. 如果另一个方法调用一个event则会触发所有订阅 This can help you to 'notify' activities to do some work. 这可以帮助您“通知”活动以完成一些工作。 You can browse the repository to see how you can use it. 您可以浏览存储库以了解如何使用它。

Basically, when you want to listen for events in your Activity , you need to implement NotificationCenter.NotificationCenterDelegate . 基本上,当您想要监听Activity events时,需要实现NotificationCenter.NotificationCenterDelegate Then override didReceivedNotification(int id, Object... args) , and (un) subscribe for events like this: 然后覆盖didReceivedNotification(int id, Object... args) ,并(un)订阅这样的events

NotificationCenter.getInstance().addObserver(this, NotificationCenter.scheduleReload);

Then you can notify the subscribed Activities anywhere by calling: 然后,您可以通过调用以下方式通知订阅的Activities

NotificationCenter.getInstance().postNotificationName(NotificationCenter.scheduleReload);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM