How to use multiple viewmodels in single fragment in Android? - android-fragments

Let's say I have DashboadFragment which has its own ViewModel named DashboadViewModel. I have created separate layout for AutoCompleteTextView which is included in fragment_dashboard.xml file. I have created separate ViewModel for AutoCompleteTextView which is AutoCompleteTextViewViewModel. So here I have tried to observe the data which are typing in AutoCompleteTextView into DashboardFragment but it didn't worked.
I have recently started development in MVVM Pattern.

You can pass data between Fragment using the delegate viewModels
private val viewModel: ListViewModel by viewModels({requireParentFragment()})
it does mean that you will have in your dashboardFragment a AutoCompleteTextViewViewModel.
Another solution will be to use the setFragmentResult()API
See https://developer.android.com/guide/fragments/communicate#share_data_between_a_parent_and_child_fragment
and https://developer.android.com/guide/fragments/communicate#fragment-result for more informations

Related

how do I access ViewModel inside Work Manager

I'm trying to access ViewModel using hilt inside the worker class which I created but unable to do so, can anyone help please?
You should not try do such a thing in no way. They have totally different lifecycle and one is UI related - the other is not. You should create some other object, like a Singleton, and use it to share the data between the ViewModel and the Work. You can pull the data or use Observer pattern. VM has onCleared method so you can unregister there if you use Observer and observe the data from the VM in the Singleton.

Java FXML Application: unsuccessful calling method in controller class from external class

Working on a Java FXML application called EVIF VideoRouter. Main class is then VideoRouter.java and the controller class is called VideoRouterFXMLController.java.
I have a method in the VideoRouterFXMLController.java class that I need to be able to call from other external classes within the application. Based on extensive searching and reading, I altered the FXML loader code in the main VideoRouter.java class to be thus:
FXMLLoader EVIFloader = new FXMLLoader(this.getClass().getResource("VideoRouterFXML.fxml"));
Parent EVIFroot = (Parent) EVIFloader.load();
VideoRouterFXMLController EVIFcontroller = EVIFloader.getController();
Now, as I understand this process, I'm somehow supposed to create a getter in the main VideoRouter.java class that returns the EVIFcontroller instance I've created above? And then I can use that getter in other classes and call the method inside the returned instance?
If so, I'm having difficulty figuring out where exactly to place the getter. Does it go in the controller class, or the main class? In either case it doesn't seem to be able to see the controller instance in order to return it.
Again, I've searched extensively and the related posts I've found to not appear to address this specific problem I'm having. Any help?
Many thanks in advance!
You have already partly answered your problem: create VideoRouterFXMLController member variable in your VideoRouter class and a getter to expose it, then set it to the controller instance after you load the FXML like in the code snippet your provided.
Having said that, I would propose a different approach to your problem because this approach is generally not a good design due to high coupling between your classes. I would recommend Observer pattern as an alternative approach and EventBus as a library to do this.

How to implement MVVM in Xamarin.Forms with SQLite to populate a Listview who need INotifyPropertyChanged/Icommand in each row

I have my model A with some properties, i receive data from REST web service i use SQlite for local caching. With SQLite api i can use mi class A to automatically create tables and after retrieve data. Thats Ok
Now i need to get those data as a list to populate a listview, like a Todo-Item with a check (done - not done) to update a boolean every time user tap the "nice check image" so i need INotifyPropertyChanged by row
My option i think are:
1) Retrieve the whole list with SQlite api i will get a list. But i dont have INotifyPropertyChanged changes here. So i should convert the whole List to List who will have INotifyPropertyChanged and ICommand implemented. This will add extra process. but i think is the better i got
2) Inherit ViewModel directly from Model so i could achieve retrieve List directly from SQLite.net, but i should do another method in sqlite client for this specficic way to retrieve. and i will be accessing to SQLite from Model and ViewModel too, i think this should not be do it in this way
3) Add INotifyPropertyChanged and ICommand to the model...
i try approach to these 3 way but i really dont like the resulting code.
is there another way to do it or suggestion to improve the current options pls?
The best way out in your case would be to create a ViewModel for a list item, which would be implementing INotifyPropertyChanged and contain ICommand fields, and initialize it with data from a Model (whether through ctor or by creating a factory). This way you'll get a list of ViewModels implementing all required features.
This is a pretty common approach.

Should each view model be handled by a single ViewModelLocator?

I am starting to explore the MVVM light and start to design my different viemModels. I have browsed for long time to find out what I am looking for but I could not get it :-(.
One sample I have is based on a single MainViewModel, which is handled inside a ModelViewLocator. In most cases we will have more than one viewModel, so should all viewModels be defined in a single ViewModelLocator file or do I have to have one ViewModelLocator per view?
In other words do I need to get this :
MainViewModel -> MainViewModelLocator
PictureViewModel -> PictureViewModelLocator
Ok fine but sill one question:
let say that I have 3 viewModels that I have create as ViewModel1, 2 and 3
In ViewModelLocation, I have create same structure as the MainViewModel in order to create the instance of it and have create a main property to access Models instance.
The problem I have found is that If each of my Views corresponding to each viewModels is set to is own datacontext as ViewModelLocator.ViewModelx, the view instance is create at design time and it makes me trouble if during the constructor of my view I need to call an external class which get data from a WCF service. It generate an "instance creation error".
In an other hand if in each view I bind then NOT from ViewModelLocator.ViewModelx but instead as directly ViewModelx then I do not get that error and works better.
So what is the properway to do and the logic path :
1 - Does the MainViewModel should create all other viewModel's ?
2 - Does each View must be bound to it's own MainStatic propery in ViewModelLocator ?
3 - Does each View create their own Instance of ViewModel ?
The way I have done is that my View which return service data from an external class during ViewModel constructor creation works only if I bind it directly to the ViewModel, does it have trouble doing it so ?
Usually there is no need for multiple view model locators. The common way is to create one ViewModelLocator which you then add to Application.Resources in App.xaml so it's available to be used anywhere in the application. Just create a property in the ViewModelLocator for each ViewModel you're using.
Below is an example which is using the IoC container in MVVM Light 4 (beta) to instantiate view models. You could also do without the IoC container but in more complex scenarios it'll definitely simplify your code:
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<DetailsViewModel>();
}
public MainViewModel MainViewModel
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public DetailsViewModel DetailsViewModel
{
get
{
return ServiceLocator.Current.GetInstance<DetailsViewModel>();
}
}
}

flex sharing data between different components

i have in my flex application various mxml components that all need to show stats based on the same data. how can i go about doing that? do i need some mvc framework like cairngrom or puremvc for that or can i do it without them?
any design ideas?
You don't need any framework for that. Do you know about data-binding?
http://www.flexafterdark.com/docs/Flex-Binding
This way you can set your data as dataprovider for many components. For example to show your data in dataGrid you set in mxml it's attribute
dataProvider="{yourDataArrayCollectionIdentifier}"
and in your arrayCollection declaration you need to set metatag [Bindable]
[Bindable] var yourDataArrayCollectionIdentifier : ArrayCollection;
there are other datatypes you can use as dataprovider, just arrayCollection is the most common
There are a handful of approaches to this. For encapsulation purposes, you should isolate your shared data out into a separate class; possibly a Value Object although it does't have to be.
Then create a public variable property in each MXML Component of this classes type. When you create the instance of each mxml component, pass in your 'global' instance of the data class.
You don't need to use an MVC framework, but the Cairngorm Model Locator could also be used to address this problem. The Model Locator is a singleton. You'd store your data inside the singleton instance; and then each MXML Component would reference the singleton for the data. Creating an external dependency like this breaks encapsulation, though. I much prefer the parameter passing route for non-application specific components.
package
{
public class ApplicationViewModel
{
[Bindable] public var message:String = "";
}
}
You can now use this message across your MXML where you make the instance of that.
A singleton class is used in different scenarios where you want to hold some information of all states. A better example would be Chess Board, where your board is Singleton class and its state should never change as you have to keep track of all coins moved across the board and its position.
You are injecting this message variable in the views where you want to show the data.

Resources