android / architecture-components-samples

Samples for Android Architecture Components.
https://d.android.com/arch
Apache License 2.0
23.43k stars 8.29k forks source link

How to shere same instance of view model between activities? #29

Closed luna-vulpo closed 7 years ago

luna-vulpo commented 7 years ago

Is possible to share same instance of view model between activities similar to share same view model between fragments?

JoseAlcerreca commented 7 years ago

The idea is that there's a viewmodel per "screen", that's why in an activity with multiple fragments you can share the VM. If you want to persist data between screens you should use something else (a singleton, shared preferences, file, etc).

What type of data do you want to persist between activities?

yigit commented 7 years ago

FYI there are some projects solving this use case but nothing public yet.

yigit commented 7 years ago

We are considering a solution for this but it is scheduled for post 1.0 right now. Please report a bug on issuetracker.google.com if you would like to follow the progress.

naderz commented 6 years ago

@yigit Has this issue been addressed in the stable release yet?? @JoseAlcerreca My scenario is with the master detail design the ViewModel is shared perfectly between the master detail fragment when they are sharing the same activity. but when in portrait mode then they both have 2 different activities.. This is when it still make sense to share the view model between those 2 activities.

SourabhSNath commented 6 years ago

Anything yet?

MunishThakur commented 6 years ago

you can use factory to make viewmodel and this factor will return single object of view model.. As:

class ViewModelFactory() : ViewModelProvider.Factory {

override fun create(modelClass: Class): T {
    if (modelClass.isAssignableFrom(UserProfileViewModel::class.java)) {
    val key = "UserProfileViewModel"
    if(hashMapViewModel.containsKey(key)){
        return getViewModel(key) as T
    } else {
        addViewModel(key, UserProfileViewModel())
        return getViewModel(key) as T
    }
    }
    throw IllegalArgumentException("Unknown ViewModel class")
}

companion object {
    val hashMapViewModel = HashMap<String, ViewModel>()
    fun addViewModel(key: String, viewModel: ViewModel){
        hashMapViewModel.put(key, viewModel)
    }
    fun getViewModel(key: String): ViewModel? {
        return hashMapViewModel[key]
    }
}
}

In Activity:

viewModelFactory = Injection.provideViewModelFactory(this)

// Initialize Product View Model
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(
UserProfileViewModel::class.java)`

This will provide only single object of UserProfileViewModel which you can share between Activities.

herriojr commented 6 years ago

@MunishThakur My only possible issue with that approach is -> The ViewModel is expected to be cleared when onCleared() is called. Will onCleared() be called multiple times (answer: yes)? For example, if Activity A and B share a ViewModel and from Activity A, I start up Activity B, then close Activity B, onCleared() be called while Activity A still needs the ViewModel. I really feel this version of ViewModels wasn't designed to actually be used across multiple activities.

So for people looking at this, you shouldn't share ViewModels across Activities with the above method.

magician20 commented 6 years ago

I'm trying to share data between two fragments in different activities with ViewModel is this possible ? any Solution ?

herriojr commented 6 years ago

@magician20 Yes. Use the activity when creating the viewmodel instead of the fragment

mohamed6996 commented 6 years ago

did you solve it ? @yigit

herriojr commented 6 years ago

@magician20 sorry I thought you said same activity. You can't currently do it

EzimetYusup commented 6 years ago

@yigit do we have solution for this yet? it's already 1.1.0

pablichjenkov commented 6 years ago

I advice to use dagger2, then will create a data app module with application scope so each activity will have access to it.

rockyoung commented 6 years ago

Anyone tried AndroidViewModel?

Guang1234567 commented 6 years ago

@luna-vulpo

Hope it help you. but not under unit test.

1) Create sub class extends ShareViewModel


import android.arch.lifecycle.ViewModel;

import java.util.concurrent.atomic.AtomicInteger;

public abstract class ShareViewModel extends ViewModel {

    private final AtomicInteger mRefCounter;

    private final Runnable mOnShareCleared;

    protected ShareViewModel(Runnable onShareCleared) {
        mRefCounter = new AtomicInteger(0);
        mOnShareCleared = onShareCleared;
    }

    protected final void onCleared() {
        decRefCount();
    }

    protected abstract void onShareCleared();

    protected final int incRefCount() {
        return mRefCounter.incrementAndGet();
    }

    private final int decRefCount() {
        int counter = mRefCounter.decrementAndGet();
        if (counter == 0) {
            if (mOnShareCleared != null) {
                mOnShareCleared.run();
            }
            onShareCleared();
        } else if (counter < 0) {
            mRefCounter.set(0);
            counter = 0;
        }
        return counter;
    }
}

2) Using ShareViewModelFactory to provide your ShareViewModel


import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider;
import android.support.annotation.NonNull;

import com.example.sqlbrite.todo.model.ShareViewModel;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class ShareViewModelFactory extends ViewModelProvider.NewInstanceFactory {

    private final Map<Class<? extends ViewModel>, ViewModel> mShareCache = new HashMap<>();

    @NonNull
    @Override
    public <T extends ViewModel> T create(final @NonNull Class<T> modelClass) {
        if (ShareViewModel.class.isAssignableFrom(modelClass)) {
            ShareViewModel shareVM = null;

            if (mShareCache.containsKey(modelClass)) {
                shareVM = (ShareViewModel) mShareCache.get(modelClass);
            } else {
                try {
                    shareVM = (ShareViewModel) modelClass.getConstructor(Runnable.class).newInstance(new Runnable() {
                        @Override
                        public void run() {
                            mShareCache.remove(modelClass);
                        }
                    });
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InstantiationException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                }
                mShareCache.put(modelClass, shareVM);
            }

            shareVM.incRefCount();
            return (T) shareVM;
        }
        return super.create(modelClass);
    }
}

3) I think this solution only for some certain use cases? Such as to simplify the way that share data between [two fragments] in different activities with ViewModel when develop on Android Pad and Android Mobile with single code repo at the same time.

Because the code like below is too ugly:

//ResultFragmentB.java

private void postResult() {

    if( getActivity().isTwoPanel()) {
         mListener.onPostResut(resultFromB);
    } else {
        getActivity().setReslut(resultFromB)
        getActivity().finish();
    }

}

if you use ShareViewModel maybe like this:

//ResultFragmentB.java

private void postResult() {
    myShareViewModel.postResut(resultFromB);
    if(!getActivity().isTwoPanel()) {
        getActivity().finish();
    }
}
//FrontFragmentA.java

protected void onResume() {
    myShareViewModel.listenResut(new Listener() {
        @override
        public void onReciveResult( resultFromB) {
             // do sth here
        }
    });
}
alenz316 commented 6 years ago

Related bug on the issue tracker - https://issuetracker.google.com/issues/64988610

⭐️ if you agree with it

herriojr commented 6 years ago

@Luis, An activity can share its ViewModel to all child fragments of that activity. You just scope the ViewModel to the activity.

ViewModelsProvider.of(activity) scopes your ViewModel to the activity, so when you attempt to ask for your ViewModel, you will receive it in the Fragment.

class MyFragment : Fragment { interface IMyViewModel {} lateinit var viewModel: IMyViewModel open fun attachViewModel() { viewModel = ViewModelProviders.of(activity).get(MyViewModel::class) }

override fun onAttach(context: Context) {
    super.onAttach(context)
    attachViewModel()
}

}

On Fri, Aug 24, 2018 at 2:40 AM Luis Pereira notifications@github.com wrote:

IMO google needs a mechanism to share an activity ViewModel to all child fragments, if they don't want us to use a SingletonRepository... Having fragments aware of activity or vice versa is not that good to maintain, as MVVM says views should not communicate with each other, but we can have a View with many ViewModels, soooo we can observer multiple stuff on a fragmentA and the same stuff on fragmentB, but for that we need a singleton, since the view model is not shared. Am I seeing this incorrectly?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/googlesamples/android-architecture-components/issues/29#issuecomment-415708589, or mute the thread https://github.com/notifications/unsubscribe-auth/AAP3kHubQIUfcZ9wdjaXQO4Xq5EeWVoSks5uT8olgaJpZM4NmMT6 .

hendrawd commented 6 years ago

TLDR: What we can do now is make our multiple activities implementation into 1 activity that contain fragments to share 1 ViewModel between multiple screens

luispereira commented 6 years ago

@herriojr This way you can have multiple viewmodels for one view. For example, let's say that we have a generic fragment which has a webview. This fragment with webview is called from different activities. In this case we should implement a viewmodel for the webview which tells the webview state for example? If so, than we can have multiple viewmodels which are called or at least initialized to be observed in a single view. Is this a correct assumption?

herriojr commented 6 years ago

@luispereira what state are we talking about? I still don't understand how this example is useful. If you truly need this state to persist outside its lifecycle you likely should be storing it at the data layer. If you truly wanted to scope the viewmodel to the application, instantiate it as a singleton at the application scope without the provider. You can technically do that but I can't fathom in what situation this is better than saving the state in the data layer. You could technically create your own provider which has a concept of custom scope which is what it sounds like you want. You don't technically have to use their providers for the viewmodels.

rramprasad commented 6 years ago

The idea is that there's a viewmodel per "screen", that's why in an activity with multiple fragments you can share the VM. If you want to persist data between screens you should use something else (a singleton, shared preferences, file, etc).

What type of data do you want to persist between activities?

@JoseAlcerreca @yigit I am using Single Activity for whole app and multiple fragments. In this case, can I use different ViewModels for each fragment and a ViewModel for the single Activity(for fragment data communication only)? If we use same ViewModel for all fragments the ViewModel code becomes large.

hendrawd commented 6 years ago

@rramprasad I believe you can achieve that easily by passing the instance of your Fragment instead of your Activity inside your Fragment when creating ViewModel.

ViewModelProviders.of(this@YourFragment).get(YourViewModel::class.java)
rramprasad commented 6 years ago

@rramprasad I believe you can achieve that easily by passing the instance of your Fragment instead of your Activity inside your Fragment when creating ViewModel.

ViewModelProviders.of(this@YourFragment).get(YourViewModel::class.java)

No. Creating ViewModel inside a fragment is not a problem.It is a basic thing. My question is using separate ViewModel for each fragment and a single ViewModel for activity.

hendrawd commented 6 years ago

Yes you can @rramprasad Next time it is better to try it by yourself if your question starts with "Can I"

freddy24 commented 5 years ago

I found that somebody has solve this ,it works for me, here is the solution: https://medium.com/mindorks/how-to-communicate-between-fragments-and-activity-using-viewmodel-ca733233a51c

proRadwan commented 5 years ago

I have ViewModel that use in many activities I make live data as Singleton and ViewModel as Singleton and using viewModelFactory by extends ViewModelProvider.NewInstanceFactory

  ` private LookUpViewModel t;

private final Map<Class<? extends ViewModel>, ViewModel> mLookUpFactory = new HashMap<>();

public SingletonNameViewModelFactory(LookUpViewModel t) {
    this.t = t;
}

@NonNull
@Override
public <T extends ViewModel> T create(final @NonNull Class<T> modelClass) {
    mLookUpFactory.put(modelClass,t);

    if (LookUpViewModel.class.isAssignableFrom(modelClass)) {
        LookUpViewModel shareVM = null;

        if (mLookUpFactory.containsKey(modelClass)) {
            shareVM = (LookUpViewModel) mLookUpFactory.get(modelClass);
        } else {
            try {
                shareVM = (LookUpViewModel) modelClass.getConstructor(Runnable.class).newInstance(new Runnable() {
                    @Override
                    public void run() {
                        mLookUpFactory.remove(modelClass);
                    }
                });
            } catch (NoSuchMethodException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
            mLookUpFactory.put(modelClass, shareVM);
        }

        return (T) shareVM;
    }
    return super.create(modelClass);
}

`
and View Model class

` private MutableLiveData<List> mutableLiveData; private static LookUpViewModel lookUpViewModel; private LookUpViewModel() { RequestData(); } public static synchronized LookUpViewModel getInstance() { if (lookUpViewModel == null) { lookUpViewModel = new LookUpViewModel(); return lookUpViewModel; }

    return lookUpViewModel; // or throw error because trying to re-init
   }

  public MutableLiveData<List<AdditionsInformation>> getLookUp(){
    if(mutableLiveData==null){
        mutableLiveData = new MutableLiveData<>();
     }
    return mutableLiveData;

}`

Pecana commented 5 years ago

you can use factory to make viewmodel and this factor will return single object of view model.. As:

class ViewModelFactory() : ViewModelProvider.Factory {

override fun create(modelClass: Class): T {
    if (modelClass.isAssignableFrom(UserProfileViewModel::class.java)) {
    val key = "UserProfileViewModel"
    if(hashMapViewModel.containsKey(key)){
        return getViewModel(key) as T
    } else {
        addViewModel(key, UserProfileViewModel())
        return getViewModel(key) as T
    }
    }
    throw IllegalArgumentException("Unknown ViewModel class")
}

companion object {
    val hashMapViewModel = HashMap<String, ViewModel>()
    fun addViewModel(key: String, viewModel: ViewModel){
        hashMapViewModel.put(key, viewModel)
    }
    fun getViewModel(key: String): ViewModel? {
        return hashMapViewModel[key]
    }
}
}

In Activity:

viewModelFactory = Injection.provideViewModelFactory(this)

// Initialize Product View Model
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(
UserProfileViewModel::class.java)`

This will provide only single object of UserProfileViewModel which you can share between Activities.

How can this be done in Java ?

FarshadTahmasbi commented 5 years ago

Hi, I created a library for this purpose, you can share ViewModels between activities and even fragments with different host activity, also you can create ViewModels with application scope. https://github.com/FarshadTahmasbi/Vita

Antroid commented 5 years ago

I have a simple scenario, I have two activities (MainActivity and SettingsActivity). In MainActivity I have FragmentA while in SettingsActivity you have FragmentB(which is preferenceFragment). If I change one of the settings in the settings activity I would like to refresh the content of FragmentA.

I tried various solutions like: (this - inside of the fragment) ViewModelProviders.of(this, viewModelFactory).get(FragmentAViewModel::class.java).reload() or ViewModelProviders.of(activity, viewModelFactory).get(FragmentAViewModel::class.java).reload()

but I'm getting that the MutableLiveData.value is null for some reason(I think I'm getting a new instance of FragmentAViewModel), is it possible this issue related to the fact that I'm trying to share a view model between two activities and not two fragments that are related to one activity?

This is my code for the viewmodelfactory

`@Singleton class ViewModelFactory @Inject constructor(private val creators: Map<Class, @JvmSuppressWildcards Provider>) : ViewModelProvider.Factory {

@NonNull
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(@NonNull modelClass: Class<T>): T {
    var creator: Provider<out ViewModel>? = creators[modelClass]
    if (creator == null) {
        for ((key, value) in creators) {
            if (modelClass.isAssignableFrom(key)) {
                creator = value
                break
            }
        }
    }
    requireNotNull(creator) { "unknown model class $modelClass" }
    try {
        return creator.get() as T
    } catch (e: Exception) {
        throw RuntimeException(e)
    }

}

}`

bahaa-kallas commented 4 years ago

@FarshadTahmasbi it seems its working , Thank You ❤️

JoelSalzesson commented 4 years ago

I think you're trying to solve wrong problem. ViewModel is about model for a single view. A view is an Activity. If you want to share ViewModel between multiple views then don't use ViewModel as it was not meant to be shared outside of a view (as its name suggests).

herriojr commented 4 years ago

I think you need to expand on that explanation a bit for people. Basically, if your "Views" are tightly coupled, they likely need to be Fragments and not Activities. If they are loosely coupled, being separate Activities is fine and the ViewModel won't be shared between them. View in this context isn't well defined. If you're doing a single-Activity multi-Fragment approach, anything at the Activity level is fairly useless. So I just want to reiterate, This isn't a Fragment vs Activity thing, this is whether your "Views" are tightly coupled or not.

On Sat, Feb 1, 2020 at 2:55 AM JoelSalzesson notifications@github.com wrote:

I think you're trying to solve wrong problem. ViewModel https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing_data_between_fragments is about model for a single view. A view is an Activity. If you want to share ViewModel https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing_data_between_fragments between multiple views then don't use ViewModel https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing_data_between_fragments as it was not meant to be shared outside of a view (as its name suggests).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/android/architecture-components-samples/issues/29?email_source=notifications&email_token=AAB7PEGLD6PDYSECF4YMVW3RAVIKZA5CNFSM4DMYYT5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKQ2EGQ#issuecomment-581018138, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB7PEAAPE3ETSZI6RYOST3RAVIKZANCNFSM4DMYYT5A .

rmirabelle commented 4 years ago

Behold, all this confusion because the very concept of a shared ViewModel is fundamentally an oxymoron. ViewModel INSTANCES are in fact, never shared.

Every time you call ViewModelProviders.of or the newer ViewModelProvider or the EVEN NEWER by viewModels() or byActivityViewModels(), Android spins up a NEW INSTANCE of your ViewModel. You're not getting a reference to your ViewModel, as documentation worldwide implies. You're getting a new instance.

Even if the LiveData in the ViewModel IS in fact, shared between instances, the instances themselves are NOT.

I do wish the Net wasn't filled to the brim with the very misleading phrase: "shared view model", because I've wasted far too much time wondering why my supposedly "shared" view models were doing things like reconnecting to data stores and re-fetching data.

Android team: Developers need a ViewModel whose INSTANCE can in fact, be shared!

herriojr commented 4 years ago

ViewModels can be shared when in the same activity between different fragments. You cannot share between activities unless you explicitly instantiate the viewmodel outside of the provider factory, which is bad. You can share between fragments in the same activity by instantiating them with the activity context.

On Fri, Mar 20, 2020 at 12:15 PM Robert Mirabelle notifications@github.com wrote:

Behold, all this confusion because the very concept of a shared ViewModel is fundamentally an oxymoron. ViewModel INSTANCES are in fact, never shared.

Every time you call ViewModelProviders.of or the newer ViewModelProvider or the EVEN NEWER by viewModels() or byActivityViewModels(), Android spins up a NEW INSTANCE of your ViewModel. You're not getting a reference to your ViewModel, as documentation worldwide implies. You're getting a new instance.

Even if the LiveData in the ViewModel IS in fact, shared between instances, the instances themselves are NOT.

I do wish the Net wasn't filled to the brim with the very misleading phrase: "shared view model", because I've wasted far too much time wondering why my supposedly "shared" view models were doing things like reconnecting to data stores and re-fetching data.

Android team: Developers need a ViewModel whose INSTANCE can in fact, be shared!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/android/architecture-components-samples/issues/29#issuecomment-601869362, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB7PEETL5DZYQXWDMPNHRLRIO6EXANCNFSM4DMYYT5A .

alenz316 commented 4 years ago

@rmirabelle That is incorrect about the instance sharing, they are in fact shared within a particular scope. ViewModelProvider relies on a ViewModelStoreOwner, for example AppCompatActivity is passing along its ViewModelStore via getLastNonConfigurationInstance() to keep the instance of ViewModelStore and the ViewModels across configuration changes.

rmirabelle commented 4 years ago

@alenz316 @herriojr

class MySharedViewModel(app:Application): AndroidViewModel(app) {
    init {
        Log.d("MySharedViewModel", "INIT CALLED")
    }
}

Activity:

private val viewModel: MySharedViewModel by viewModels()

In a child Fragment:

private val viewModel: MySharedViewModel by activityViewModels()

INIT CALLED will be logged twice. Also tried this with the older ViewModelProvider syntax

herriojr commented 4 years ago

I have no issue w/ this that I just wrote which only has INIT logged once:

package com.bymason.viewmodeltest

import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.viewModels import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.fragment.app.activityViewModels import androidx.lifecycle.ViewModel

class MyViewModel : ViewModel() { init { Log.d("BLAH", "INIT") } }

class MyFragment : Fragment() { private val model: MyViewModel by activityViewModels()

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    Log.d("BLAH", "fragment $model")
}

}

class MainActivity : FragmentActivity() {

private val model: MyViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    if (savedInstanceState == null) {
        supportFragmentManager.beginTransaction().add(R.id.mylayout,

MyFragment(), "").commit() } Log.d("BLAH", "activity $model") } }

Logs from logcat including w/ rotation: 2020-03-20 22:07:19.646 8258-8258/com.bymason.viewmodeltest D/BLAH: INIT 2020-03-20 22:07:19.646 8258-8258/com.bymason.viewmodeltest D/BLAH: activity com.bymason.viewmodeltest.MyViewModel@361a877 2020-03-20 22:07:19.675 8258-8258/com.bymason.viewmodeltest D/BLAH: fragment com.bymason.viewmodeltest.MyViewModel@361a877 2020-03-20 22:10:55.567 8258-8258/com.bymason.viewmodeltest D/BLAH: activity com.bymason.viewmodeltest.MyViewModel@361a877 2020-03-20 22:10:55.586 8258-8258/com.bymason.viewmodeltest D/BLAH: fragment com.bymason.viewmodeltest.MyViewModel@361a877

Lastly, as a suggestion, all this code is open source. Please read through it as the code itself for ViewModels is not that complex and you will have a much better understanding.

On Fri, Mar 20, 2020 at 6:56 PM Robert Mirabelle notifications@github.com wrote:

@alenz316 https://github.com/alenz316 @herriojr https://github.com/herriojr

class MySharedViewModel(app:Application): AndroidViewModel(app) { init { Log.d("MySharedViewModel", "INIT CALLED") } }

Activity:

private val viewModel: MySharedViewModel by viewModels()

In a child Fragment:

private val viewModel: MySharedViewModel by activityViewModels()

INIT CALLED will be logged twice. Also tried this with the older ViewModelProvider syntax

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/android/architecture-components-samples/issues/29#issuecomment-601976819, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB7PEAKHTZ7HLDZAT4FI4LRIQNF5ANCNFSM4DMYYT5A .

rmirabelle commented 4 years ago

@herriojr Thanks for taking the time to craft a test! I'll do a new test of my own and see how it turns out. If, in fact, obtaining a reference to a ViewModel works as expected, I'll be mightily relieved. If my second test fails, I'll chime back in. Thanks again!

Edit: Tested using your base code and the ViewModel is initted only once! But in my project, I use a FramentStatePagerAdapter with a TabLayout to render my Fragments, rather than instantiating them directly from my Activity. I wonder if my "double init" problem is lurking there.

an-analyst-zz commented 4 years ago

@MunishThakur My only possible issue with that approach is -> The ViewModel is expected to be cleared when onCleared() is called. Will onCleared() be called multiple times (answer: yes)? For example, if Activity A and B share a ViewModel and from Activity A, I start up Activity B, then close Activity B, onCleared() be called while Activity A still needs the ViewModel. I really feel this version of ViewModels wasn't designed to actually be used across multiple activities.

So for people looking at this, you shouldn't share ViewModels across Activities with the above method.

I agree

d2luu commented 3 years ago

@FarshadTahmasbi Your library works like a champ, thank you 🎉