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
Related
When working with Bottom Sheets and Dialog how to perform operation:
Use a SharedViewModel with fragment that created this bottom sheet?
Don't use a ViewModel at all?
Creating a separate ViewModel for the BottomSheet?
Any other approach that is best practice
If the bottom sheet/dialog is tightly bound to your "host" fragment (it shares some specific live data), and it is never going to be created from some other fragment, then it's OK to use a shared view model.
If the dialog is dead simple (like one input + 2 buttons), then the viewmodel might not be needed
If the dialog really needs a viewmodel (i.e. it fetches and displays some dynamic data), then a separate viewmodel makes sense
I'll go with the first approach by using a ShareViewModel, but if you understand the underlying layer, shared ViewModel is also ViewModel it's just a name convention we gave it to them.
Also sometimes it becomes tedious to write separate ViewModel to deal with fragments and bottom sheet where a MainActivity ViewModel can also do the exact same thing.
What I meant, in order to avoid complexity I use one view model per activity. Now, whenever I want to execute something in fragment or bottom sheet I just pass the view model in the constructor itself. Many people will think this is bad practice but it's not coz as per the concept of view model it will only be created and destroyed in accordance with the activity's lifecycle and only one instance will be created all along. Also by doing this, I can use Dependency injection with the fragment (I don't think that DI works with navigation component but I think you got my point).
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 have a ViewPager which contains 3 fragment and each fragment contains a recyclerview.
When page launched -> FragmentA is selected by default and I check for a specific id inside FragmentA and the test is success.
Now i used swifeLeft() to navigate to FragmentB. It worked.
Now I am checking for a specific item in Fragment B. But It throws error as NoMatchingViewException. In View Hierarchy log, i'm seeing the view hierarchy of FragmentA only. Somehow after swipe the View Hierarchy is not updating.
Did someone faced the same issue?
Have you tried to add a sleep just after your swipe ? I can help.
Espresso is not able to detect asynchronous work so it might fail because your data is not yet loaded (because of slow network/database etc) when it check the view you want to interact with. So the best solution is to implement IdlingResource in order to make espresso aware of them.
You can take a look at this sample:
https://github.com/googlesamples/android-testing/tree/master/ui/espresso/IdlingResourceSample
I need to place a lot of different views where some of them need to be fragments in a Recyclerview. For example a MapFragment or a YoutubePlayerFragment.
Is there a good way to place them into viewholders for the recycler view so that the references are not leaking or should I simply not use a Recyclerview therefore? (the list can get very long, it's a message timeline in a messenger)
I'm using the MVP pattern so every the Fragments will have presenters that have to get recycled somehow aswell but that's a minor problem. The Bigger problem is to handle the lifecycle events of the fragments in the viewholders.
I am coming from iOS. I want to create a picture slider and instantiate it different activities. I want to reuse the code that controls the slide and detects the gestures, so I can just instantiate the same class in each activity.
In iOS I do that by just adding controller logic in a view that I instantiate. How would I do that in android?
Thanks
Ok, after a few days of googling and thinking outside of the iOS mindset I found the solution, which ironically was the same as iOS.
Extend the View class. You can also extend a fragment but that has its own tradeoffs, mainly being that you can't instantiate a fragment inside another fragment. So to not limit your reuse of the class extend views. The downside to that is that with views you need to manage states, meaning that if the user rotates the view, you need to be able to store and restore the state of your view items (text view contents for example).
These links might help you out
https://www.youtube.com/watch?v=YIArVywQe8k
http://www.vogella.com/tutorials/AndroidCustomViews/article.html
http://developer.android.com/training/custom-views/create-view.html