Android MVVM + DataBinding RecyclerView - android

i'm trying to implement MVVM architecture + DataBinding + RxJava.
i have an activity with RecyclerView.
as i understand the ViewModel should not have a reference to the View.
what's the correct way in MVVM to pass the data list from the ViewModel to the RecyclerView in the activity?
pass the data via interface like in MVP?

You should add data binding to your ViewHolder. You can read some articles like this to make it more clear.
By the way I faced problem when using MVVM + Databinding Library when trying to apply animations or for example trying to implement postdelayed. Of course you can create tons of custom binding adapters, but it a lot easier to use view directly, so sometimes you have to use MVP like connections between ViewModel and View.

You can see my repository where I did everything using DataBinding! Visit https://github.com/xyarim/android-architecture

Related

Call notifiyDataSetChanged() from android viewmodel

I'm making a reactive app with a lot of data using Android MVVM. There are a lot of cases where I push data to firestore documents in my app, but i also want this change in data to be reflected locally in my app. So I also add the data to the local copy (data class) of the firestore document. I do this in my viewmodel.
The problem here is that I won't see change until I restart the app. So I need a way to call adapter.notifyDataSetChanged() from my viewmodel so the recyclerviews are updated immediately. Whats the best way to do this? Please help.
As you change and update data frequently, adapter.notifyDataSetChanged isn't helpful in this case because even if you update one item it will update the whole list even when the rest not touched!
So A better way to make your adapter
1- extend ListAdapter<data_model, view_holder>(diff_callback).
this Uses AsyncListDiffer under the hood to calculate and update the changed items only
2-whenever you need to update your data in viewmodel call:
adapter.submitList()
For more information on how to do that:
check doc: https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter
Yours ViewModel should't call adapter.notifyDataSetChanged() directly for two reasons:
Adapter is Android dependency. And if you want to write unit tests to yours view model you should avoid use android framework dependencies
I think adapter.notifyDataSetChanged() is UI logic implementation detail. And will be better if we move this logic to our view layer (fragment/activity/custom views)
You could solve this problem by encapsulate notifyDataSetChanged logic in yours adapter like this:
// Observe live data changes and set it to yours adapter
viewModel.state().observe(this, Observer {
newData: List<....> ->
adapter.setData(newData)
})
// Encapsulate notifyDataSetChanged at yours adapter:
class YoursAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
fun setData(data: List<.....>) {
......
notifyDataSetChanged()
}
}
In this case it's very easy to change adapter implementation from notifyDataSetChanged() to more precise updates like notifyItemInserted() later for example.
But I'm also recommend do not use notifyDataSetChanged() function and prefer DiffUtil. Or use libraries that can help with recycler view boilerplate and already have DiffUtil support under the hood. For example I like to use Groupie in my projects

Best practice to combine android ViewModel and data binding

I am a little confused about how to combine 2 techniques in android, namely
ViewModel (https://developer.android.com/topic/libraries/architecture/viewmodel) and
Data Binding Library (https://developer.android.com/topic/libraries/data-binding)
ViewModel should handle business logic, the layer behind the actual view and send data to the view with something like LiveData. The view observes to this LiveData and updates itself on changes
Data Binding Library exists to make it easier to bind to the view and interact with the view on another level (for example by updating some properties of some class)
The questions:
Should the properties / model property of Data Binding Library be kept inside of ViewModel class (A) or in the view (activity, fragment) (B)
If (A) : If the Data Binding Library properties / models are kept in ViewModel class, is it considered bad practice that view logic is executed inside ViewModel by changing data from the data binding library?
Is there a good code example (some GitHub repo) where there is an example of a decent combination of those 2 concepts?
Update: Found official documentation for my issue. Here is the link:
https://developer.android.com/topic/libraries/data-binding/architecture#viewmodel
How data binding works
Consider using LiveData, it lives inside the ViewModel and is how the data binding library knows that you must update for example the string of a TextView.
What data binding actually does is something similar to what you would explicitly do in your fragment:
Subscribe from your Kotlin code (Fragment/Activity) to a LiveData property that lives within the ViewModel but in this case, data binding will update the view values for you since you will indicate it before from your XML Layout.
So the answer is (A):
You could have a ViewModel class with properties of type LiveData<T> and from your Layout, you can use them directly without subscribing explicitly from your kotlin code as I mentioned before, which continues to guarantee that the ViewModel continues being the provider of information for the user's view, the difference is that instead of you are doing it explicitly, data binding will do it for you.
class MyViewModel : ViewModel {
// view model doesn't know if Fragment/Activity is using data binding or not, it just continues providing info as normal.
val myString : MutableLiveData<String> = MutableLiveData()
init {
myString.value = "a value that data binding will print in a TextView for you"
}
private fun changeMyString() {
// Change the value in the future when you want and then data binding will print the text in your TextView for you.
myString.value = "other value to that TextView"
}
}
Layout:
<TextView
android:text="#{myViewModel.myString}" />
Resources
This Google Codelab is pretty useful, it helped me when I started with data binding because it is prepared to teach.
If you just want to go directly to code, android/sunflower is a repository that uses data binding and in general provides useful samples of jetpack features.

MVP with Rx is same as MVVM or not

In the case of MVP, the Presenter holds a view object. While in the case of MVVM, VM does not hold View object because view updated via data binding/live data. I want to know that if I use RxJava/Data binding in the case of MVP then no need to hold view object by the presenter. Now there is any diff in MVP and MVVM? Any valuable suggestions, please?
One clear diff I can see is that in the case of MVVM, VM holds data while activity recreated. While there is no such advantage in MVP.
https://medium.com/#prajvalprabhakar/mvp-vs-mvvm-93657494106b
https://www.vogella.com/tutorials/AndroidArchitecture/article.html
i think no if we use rx with mvp than we can say its reactive programing but not exactly mvvm becuase if we see mvvm arch. it's not only include reactive things or live data its also include data biniding and many more and yes main thing it's also use repository concepts for data call (API + local), thats why we can not say that mvp with rx its same as mvvm

MVP. How to pass data between models?

I'm learning MVP structure and I trying to figure out:
How to pass data between models?
Each model represents one action and if I need to send data from one
model to another one, how can I properly make it? Should I pass data
through presenter, like
firstModel -> commonPresenter -> secondModel
OR
send data between models, like
firstModel -> secondModel?
And what if these models interact with different presenters?
The Model View Presenter pattern, like most architectural patterns, is quite open to experimentation. The important thing to keep in mind is to separate the View from the domain logic and data handling.
Particularly in Android, it's useful to keep the code as far as possible from Framework specific classes like Activities and Fragments.
In my experience, it's best to let Models communicate amongst themselves, as Observers of each other. The same goes for Views and Presenters, or, in general, any component in the same architectural layer.
AFAIK you have to convert your Domain models to your Ui models in presenter so you have to call a method or a constructor like this in presenter:
ModelOne modelOne = new ModelOne(modelTwo);
please consider DRY principals and do NOT assign each field in presenter itself like this
modelOne.title = modelTwo.title;
modelOne.id = modelTwo.id;
but if you want convert a Domain layer model to another Domain layer model you have to do it in other layers. read this for more info:
http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/
"the presenter communicates with model layer, converts the data to UI friendly format, and updates the view"
also you can find above sentence in this link:
http://iyadagha.com/using-mvp-ios-swift/

MVVM - Where to load data from internet

I'm trying to use this MVVM for my android app. I've done many apps, but I'm trying to step up on another level and trying to use the MVVM. But I need to understand where I should load the data from internet. I'm using RxJava, but I'm not sure if I should load data only in ViewModel. If so then where do I set the data. I'm using Databinding from google, but I don't wanna set data in xml through viewModel. I want to set it from the java file.
I'm sorry if I miswrote something, post an answer and I will try to fill out any required informations.
"Triggering a DataLoad" is part of presentation logic. Hence, this should belong in ViewModel.
Details about "How data is loaded" for example, networking logic, does not belong to the ViewModel layer. I highly recommend using Retrofit as you are already using RxJava.
As rx.Observableand databinding.ObservableField are very similar, you can convert them from one form to another. I have written a library that allows you to do this. See FieldUtils.java for an implementation.
Either ways, assuming you have a DataService interface/class:
public interface DataService {
Observable<String> loadSomeData();
}
you can build your ViewModel as follows:
public class ExampleViewModel {
ObservableField<String> title;
public ExampleViewModel(DataService dataService) {
this.title = FieldUtils.toField(dataService.loadSomeData());
}
}
Then, you can display this in your View using Data Binding syntax
<TextView
android:text="#{viewModel.title}" />
I recently blogged about using RxJava with MVVM. I showed an app which loads a list of events from Github using Retrofit and displays them in a RecyclerView. This has been implemented in MVVM.
Article link:
MVVM using RxJava + Data Binding example: Loading data using Retrofit
A more complicated example which also shows a loading indicator and error: DataLoadingViewModel.java.
There is two similar architectural patterns - MVP and MVVM. The main difference is that in MVP parttern Presenter desides how to display data, but in MVVM pattern View receives Model and renders itself (takes data from model). Classical MVVM example is view bindig. But the point is - nomatter what pattern you use, you should obtain all data in Model - and place all your business logic in Model too.

Categories

Resources