I open this thread to discuss about the architecture to follow in the Android app. As it is a big topic in itself, I think this is a good way of sharing ideas, diagrams, posts, etc.
@amCap1712 and me are working on the Android app as part of the GSoC 2019 project, but anyone with knowledge on the field is welcome to share ideas!!
I will link here posts and answers interesting for each section, so you don’t have to read all answers
Section: Artist
Architecture design (architecture, patterns…)
1 Like
Two livedata for Artist detail and releases
As there are many queries to make to fill an artist info, I propose an architecture something like this:
- When Activity receives the
MBID
in the Intent, asks the ViewModel to start fetching the artist data.
- ViewModel then will get the artist from the repository. Once it has the artist with its releases:
- Updates the
artist
LiveData, which will be observed by the Details Fragment to show name/birth_data/etc.
-
Transforms the stream by getting the releases and for each one queries the Repository to get the cover art URLs for each release. Then updates a different
releases
LiveData (that includes release info and cover URLs) that will be observed by Releases Fragment to render a list.
Other alternative:
Instead of querying all the releases for the URL, another alternative is returning releases like List<Pair<Release,Url>>
. And do something like if viewholder asks the viewModel to update release X with its cover art –> viewModel re-emits the same release list (but that release item will have URL info) –> notifies the recyclerview -> viewholder now binds an item that has URL inside on it.
@amCap1712 found this post in SO: How to observe LiveData in RecyclerView adapter in MVVM architecture?
We think it’s relevant for our purpose of showing releases cover arts on a list, but I wanted to try something different and instead of referencing the ViewModel in the adapter, do everything on the ViewModel and passing the adapter the final list of releases with the URL already embeded (instead of fetching the URL on the adapter)
Architecture design
Here are some interesting posts about architecture (not specifically Android):
@amCap1712 I’ve talked to an Android work mate and the best practise (and only) he suggests is when the release item is presented, ask the Repository to fetch the cover and update the release list item. Notify the recyclerView that data has been updated (with the URL for a release item) and, now that image exists, paint it with Picasso.
Something like this diagram:
As you see, both methods of the repository should update the same data, but the one that fetches the Cover Art includes the image URL for the selected release.
One problem with the diagram is that fetchArtistWithCoverForRelease()
would need the artist data (if not, it would have to fetch it before)
Thats fine but the problem is that there is no efficient way of using a viewmodel inside the activity. We need to pass in a context
and that will result in memory leaks. So the repository should directly return the data to the acitvity.
I have updated the diagram: I meant the ViewModel reference is passed to the Adapter and from there it asks the ViewModel to fetch the cover art (which would asynchronously and eventually notify of updated data to the recyclerView)
I think this SO answer is very close to what I propose (instead of passing the ViewModel, it loads it from context)
Could you explain more about the memory leaks by using the ViewModel inside of an Activity? Reading the official docs I though it was the best practice indeed…
In this SO answer it says that there’s no risk of memory leak to pass the Activity/Context to the adapter as it’s the RecyclerView who retains the reference.
The second SO answer removes my doubts. I believed we should use only global application context in an adapter but as it says, its fine to use.
Release screen
The idea is to keep as much info as possible in the main Release screen: release info on top (navigating to a exhaustive Links list and sliding between cover arts) and the list of tracks (with expandible credits)
Fashionably late here, but I suggest the following.
Create a main ViewModel that acts as a controller / mediator for other viewmodels, one for each responsibility. One controls master page, which is a combination of outputs of component VMs. LiveData to the controller viewmodel, call explicitly from master to sub.
-> == inject,
<< == get
+… created by right
…+ created by left
<… create& observe
Application …+{repositiry)
<< Activity / fragment … +(repository<-provider<-interactor)
A/F … +(subViewModels(repository–>provider-> interactor) )–>
MasterViewModel …> SubViewModels()
1 Like
Thanks for the answer. Can you provide more details?
→ == inject,
<< == get
+… created by right
…+ created by left
<… create& observe
Application …+{repositiry)
<< Activity / fragment … +(repository<-provider<-interactor)
A/F … +(subViewModels(repository–>provider-> interactor) )–>
It is unclear what you meant by this. I think you wanted to format this text but were unable to doso.
Hi @Tricknologic thanks for your proposal! I didn’t quite understand it all, but I am curious about what you meant. Please, could you make it more descriptive maybe by drawing it? Something like the drawings I attached at the top of this thread and I did using https://www.draw.io (free)
Let’s come with an elegant solution for Android architecture!