We have a problem in mvvm design pattern with recyclerView:
We have a fragment with own view model (FragmentViewModel)
and a list adapter with it's own view model (ListViewModel)
the problems are these:
Inside our fragment's view model(FragmentViewModel), we get our data from api repository,How to set these values to our adapter's view model(ListViewModel)?
Inside of adapter's view model(ListViewModel),when row item clicked, How to call a function inside our fragments's view model(FragmentViewModel) to do something with fragment's view?
Notes:
- We use dagger to inject our viewModels and adapter.
- Our list adapter will reuse with other fragments.
My suggestion would be, /n
Never use Fragment own's ViewModel, instead used activity one with a key. which differentiate between different fragment.
ViewModelProviders.of(requireActivity(), factory).get(detail.getJobId(), TimelineActivityViewModel.class);
here detail.getJobId() is an ID.
Related
I am working on an android application which has a recycler view with multiple view types. It was originally a MVP based app, which I am trying to convert to MVVM based architecture with LiveData and ViewModels. I have a home screen with a list of different types of views inside a recycler view. Every view has its own ViewModel and corresponding Model, resulting it with a home screen having recycler view as a collection of different view models.
This is my first implementation of LiveData, so facing some issues with design. I see some options here -
I create a parent HomeViewModel for my home activity which holds a LiveData object, consisting a list of different child ViewModels (representing different view types), making activity to its life cycle owner. Then I update each view(elements of recycler view) from one observer to that LiveData object.
I create individual LiveData objects for every child view/view models and make home activity as life cycle owner for each model/live data and update their views independently from activity with respective observers.
I create individual LiveData objects for every child view/view models and make respective view holder classes as their lifecycle owners and update individual views in respective holder classes.
Please help me suggesting the better way to deal with this or if there is any other approach other than the specified ones.
Thanks
I agreed to create a parent viewmodel such as "HomeViewModel", but I think the creation of viewmodel for each view type seems a little over-engineering, because every time you need to create a new view type, you need to create a new ViewModel, and I dont see any requirement for the view in recyclerview to have a dedicated viewmodel. In my perspective, the best approach is only have 1 viewmodel. Then I suggest you to implement adapter factory pattern for your recyclerview like in this article https://proandroiddev.com/writing-better-adapters-1b09758407d2 . If you have adapter factory pattern like that, you can generalize your recyclerview data, for example you can call it "Visitable" like the post above. Then, your viewmodel can hold just 1 livedata of visitable list, which observed by the fragment/activity.
I'm trying to wrap my head around implementation of shared view transitions between fragments
The challenge is coming from the MVVP restricitons:
Adapter of RecycleView has knowledge of selected element and view attached via callback from View
Adapter is passing information about click to ViewModel stripping out all information about view, as it can't hold it. That's because of rule - no android imports in ViewModel except of *arch
ViewModel sends event to Fragment to open another Fragment
At this point Fragment doesn't know what view to use to start transition in .addSharedElement(..)
How to address this issue?
I was thinking about saving reference to clicked View inside Fragment instance but it looks like a cheating
Any ideas and suggestions are very welcome
I am having a situation in which as a List Item I want to inflate a Fragment, but It seems like a bad approach. As Fragments are processed/managed by Activity's FragmentManager or by child FragmentManager and list item views are by ListView & ListAdapter.
Any comments and research regarding this would be highly appreciated.
Thanks
Here are my views and questions in mind on your problem.
You want to use ListView with fragments, since you already have a fragment which does that job and you dont want code to become redundant.
Though you can definitely use fragment, but i suppose its not the best practice. Fragments have their own life cycle and you are not going to use fragment life cycle methods (I suppose). Thus semantically it would not fit into this usecase.
And also your adapter will always be dependent on activity to retrieve fragments. (could there be any problems with orientation change again?)
List items and adapters are finetuned to work really well with scrolling really long lists. While the list view items get recycled when using view holder pattern, while scrolling, does any of fragment lifecycle methods come in between? would that cause performance impact. (I suppose yes. Havent tested it out yet)
You can instead have your view code in different layout file and include this layout in both fragment and also list adapter.
<include layout="#layout/YOUR_COMMON_VIEW_CODE"/>
and have utility class which takes the context and this layout container. Have all the functionality exposed inside that utility class.
You can't use fragment as list item views because the API doesn't allow you - View and Fragment aren't even related so there's no way you can use it like that. Make custom views and use adapter getViewTypeCount and getView to use different list item behavior.
Fragment are managed by Activity's FragmentManager or by other Fragments child FragmentManager; while list item views are managed by ListView & ListAdapter. You can use ListViews in Fragments, but not the other way around.
I googled and got this.
I have a ViewPager with 2 Fragments, FragA and FragB. Inside each Fragment I have a RecyclerView. When a user presses a button inside the RecyclerView in FragB I would like to remove the respective Object from that RecyclerView's ArrayList and add it to the RecyclerView contained in FragA.
Can I directly pass the Object from one RecyclerView's Adapter to the other? Or do I need to pass the Object from the RecyclerView Adapter to FragB then to the Activity containing the ViewPager then to FragA before finally passing to the RecyclerView inside FragA?
Your fragments and activity is just to present data.
I think the best solution is to use good design, like MVC pattern, or at least some model class (model-view kind of pattern), wich will have referens to both lists and can have public method for moving object between lists.
Giving both lists to both fragments so they can move objects is bad design choise IMHO.
This question is not for adapter solution at all.
I have a MvvmCross Android application and let's say it contains some Fragment and ViewModel. I set the ViewModel for the Fragment inside OnCreate call of the Activity which hosts the fragment as it is shown at N+1 Fragments Sample All bindings inside the fragment work fine.
I also have another Activity with a view that contains MvxListView. The row template of the listview contains the fragment I described above. How can I set the ViewModel of the fragment so that bindings work correctly?
We have found that you can't get hold of the MvxListView in the OnCreateView method to bind to the ViewModel.
We have managed to get it work work if you use OnActivityCreated method and bind your ViewModel to the View there.