New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way to have a sharedViewModel for a Fragment's Scope? #593
Comments
sharedViewModel
for a Fragment's Scope?
Yes, you can set the scope like this: In my case I have ViewPager, and i use the same viewModel for internal Fragments like: |
I'm trying to pass a scope that I've created in the The way that you uses it, doesn't work for me, once the So what I need is to have a way to get a sharedViewModel for a specific scope. |
Perhaps more check around a dedicated scope, not something tied to a Fragment nor an activity. You can create a scope instance by hand, and retrieve it elsewhere by its id. |
About that, I'm trying to define the scope in my module, like this:
And retrieve it like this:
But it's not working. |
More details? |
I'm getting an exception when I try to retrieve the viewModel instance from this scope:
With this I'm getting this exception: The I'll edit the previous message to add this line. [EDIT] I Figured out the exception. Looks like I can't pass the Before changing to Android Navigation, it was an After some digging I found that using a Scope will help me with this problem, and in fact helped, I'm, able to create a new instance of the viewModel every time I launch this Fragment, now I want to know how to retrieve this instance in the other Fragments. |
@arnaudgiuliani Any idea? |
Can you pass again your complete code, your case is a bit complex :) |
Store a weak reference to the fragment in the activity in the onCreated function.
use it to create the sharedViewModel in other fragments
As long as the fragment is in the back stack I believe its pretty much guaranteed to be alive. The alternative is to have a regular unscoped (Activity) sharedViewModel then call a reset() and init(my constructor params) function on the model before navigating to the desired fragment --- Edit In the end, sharing data between fragments is just a huge pain on android. And ultimately, dumb. |
We found out a way to overcome this issue, with NavigationComponent we have access to the ViewModelStoreOwner for a graph, so we created a new graph for this flow in order to get the right ViewModel with: |
I think I'm facing a kinda similar problem as @arctouch-carlosottoboni I have Fragment A and B. And Fragment A is using ViewModel A and Fragment B is using ViewModel B. (Note: I'll be navigating from Fragment A to B) So in my 'di' it structured kinda like this. val module = module { I get the viewModel using: This is so far so good. But here comes the problem. The moment I want to access the ViewModel A on my Fragment B, I write this code on my Fragment B. val scope = getKoin().getScope("some_unique_id") // no problem, I get the same scope I get on Fragment A val expectingSameViewModelA = scope.viewModel(this) Note: I'm inside the same activity and navigating Fragment A -> Fragment B I did fix the problem with a trick, but I think this could be better. I changed my 'di' like this: Previously: Now: I've replaced the 'viewModel' with 'scoped'. And I can get the ViewModel with the same code previously mentioned. But now I'm missing out things like: viewModelScope.launch() is not working when I switch tabs on my application (If I replace scope with viewModel I know I won't be facing this issue). It would be great if @arnaudgiuliani can help me tackle this issue. |
Does this still work? I have the exact same usecase. |
Hi, currently I'm using: Koin 2.1.0-beta-1 So, try to do like this :
To more deep understanding how it works, please check the package org.koin.androidx.viewmodel.ext.android of Koin library |
@krasavello13 Thank you for the reply. Any ideas what could cause this? EDIT: Nevermind, I took the code from your original comment from the email notification I got. Your updated code works! Thank you!! |
Oh, excellent |
Will it works with Navigation Library? |
I guess it depends on your own use case, but I am using it with the
Navigation library without issue
…On Tue, Feb 25, 2020, 1:47 PM igorka48 ***@***.***> wrote:
Will it works with Navigation Library?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#593?email_source=notifications&email_token=AGEYEHHRJZNQ6LXI2AIRQW3REUAOHA5CNFSM4I5IWM6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEM3VDEQ#issuecomment-590827922>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGEYEHEWF5K7Y3H6QQ27H3LREUAOHANCNFSM4I5IWM6A>
.
|
No, its will work only if you have parent and child fragments For correct work with navigation features (as nested navigation graph)use this extension:
|
thnx |
No problem, if you will have some question, please let me know |
looks awful |
The feature request #442 would achieve the desired outcome |
I have 3 fragments in an activity in the order A -> B -> C and I need to use a particular viewmodel shared between two fragments B and C. If I use shared view model in the activity even when I go back to the first fragment (A) the viewmodel instance is retained. How do I tackle this? Can I use scope for this and if so, how? All the fragments are created from the activity, so requireParentFragment won't work. |
#442 will be considered |
@aldrinjoemathew use |
@Wokrey findFragmentByTag on what? parentFragmentManager? |
@NahroTo First time I'm hearing about parentFragmentManager). I guess just fragmentManager is enough |
Aren't these solutions too complicated? Can't we just use UPD: How it looks: In ChildFragment: How it works:
|
I tried this and it was working, BUT it creates two separate instances of the ViewModel.... |
We solved this in our app for Koin v3.1.2 like this: import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import org.koin.android.ext.android.getDefaultScope
import org.koin.androidx.viewmodel.ViewModelOwner.Companion.from
import org.koin.androidx.viewmodel.scope.getViewModel
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
/** Creates or retrieves a viewmodel, whose lifecycle is scoped to a relative fragment of type [F]. */
inline fun <reified VM : ViewModel, reified F : Fragment> Fragment.sharedViewModel(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
): Lazy<VM> = lazy(LazyThreadSafetyMode.NONE) {
getDefaultScope().getViewModel(qualifier, null, { from(findRelative<F>()) }, VM::class, parameters)
}
/** Finds a relative fragment of type [F] via BFS. */
inline fun <reified F : Fragment> Fragment.findRelative(): F {
val visited = mutableListOf<Fragment>()
val queued = mutableListOf(this.rootFragment)
while (queued.isNotEmpty()) {
val current = queued.removeFirst()
when {
current is F -> return current
visited.contains(current) -> continue
}
visited.add(current)
queued.addAll(current.childFragmentManager.fragments)
}
throw IllegalStateException("Fragment does not have a relative fragment of type ${F::class.java}")
}
val Fragment.rootFragment: Fragment
get() {
var root = this
while (root.parentFragment != null)
root = root.requireParentFragment()
return root
} Usage example (sharing a viewmodel between a fragment and dialog): class LoginFragment : Fragment() {
private val viewModel: LoginViewModel by viewModel()
// ...
}
class LoginDialog : BottomSheetDialogFragment() {
private val viewModel by sharedViewModel<LoginViewModel, LoginFragment>()
// ...
} Edit: Feel free to use this (Apache 2.0). |
This right here is the most elegant solution for this issue I've seen. Thank you for sharing;) |
@Tetr4 Hi, how can we use this with Navigation Library from Jetpack? |
@Diegolotr99 Hi, this is working for me as well. Are you sure about the two separate instances? Do you know if this is still an issue or could you provide me more info on how you found out about this so I can test this myself? I've used the Android Studio debugger, but to me it seems that there's only one instance created. 🤔 |
I'm using Android Navigation Component, in a Single-Activity App, there is a ViewModel that I want to be re-created and it's shared between some DialogFragments that compose this specific flow. I want to know if there is a way to have a
sharedViewModel
tied to this FragmentScopeI would like to use a Scoped
sharedViewModel
, I think that this will improve the library capacitiesAs an alternative, I would like to know if there is a way to clear a viewModel instance when the fragment is destroyed
koin-android
The text was updated successfully, but these errors were encountered: