web-dev-qa-db-ja.com

Android LiveData-異なるアクティビティで同じViewModelを再利用する方法は?

ViewModelの例:

_public class NameViewModel extends ViewModel {
    // Create a LiveData with a String
    private MutableLiveData<String> mCurrentName;

    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = new MutableLiveData<>();
        }
        return mCurrentName;
    }

}
_

主な活動:

_mModel = ViewModelProviders.of(this).get(NameViewModel.class);

// Create the observer which updates the UI.
final Observer<String> nameObserver = textView::setText;

// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
_

2番目のアクティビティでmModel.getCurrentName().setValue(anotherName);を呼び出して、MainActivityが変更を受信するようにします。それは可能ですか?

14
user1209216

ViewModelProviders.of(this)を呼び出すと、実際にViewModelStoreにバインドされているthisを作成/保持するため、アクティビティごとに異なるViewModelStoreと各ViewModelStoreは、指定されたファクトリを使用してViewModelの異なるインスタンスを作成するため、異なるViewModelsにViewModelStoreの同じインスタンスを持つことはできません。

ただし、シングルトンファクトリとして機能するカスタムViewModelファクトリの単一インスタンスを渡すことでこれを実現できます。したがって、異なるアクティビティ間でViewModelの同じインスタンスを常に渡します。

例えば:

public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {


    NameViewModel t;

    public SingletonNameViewModelFactory() {
      //  t = provideNameViewModelSomeHowUsingDependencyInjection
    }

    @Override
    public NameViewModel create(Class<NameViewModel> modelClass) {
        return t;
    }
}

したがって、必要なのはSingletonNameViewModelFactoryシングルトンを作成し(たとえばDaggerを使用)、次のように使用することです。

mModel = ViewModelProviders.of(this,myFactory).get(NameViewModel.class);

注:

ViewModelsを異なるスコープ間で保持することはアンチパターンです。データ層オブジェクトを保持すること(データソースまたはリポジトリをシングルトンにするなど)と、異なるスコープ(アクティビティ)間でデータを保持することを強くお勧めします。

詳細については、 this の記事を参照してください。

28
Saeed Masoumi

ライフサイクルオーナーとしてMainActivityを渡すViewModelProvidersを使用してビューモデルを取得すると、そのアクティビティのビューモデルが提供されます。 2番目のアクティビティでは、そのViewModelの異なるインスタンスを取得しますが、今回は2番目のアクティビティです。 2番目のモデルには、2番目のライブデータがあります。

できることは、データをリポジトリなどの別のレイヤーに保持することです。これは、シングルトンである可能性があり、同じビューモデルを使用できます。

enter image description here

public class NameViewModel extends ViewModel {
    // Create a LiveData with a String
    private MutableLiveData<String> mCurrentName;

    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = DataRepository.getInstance().getCurrentName();
        }
        return mCurrentName;
    }
}

//SingleTon
public class DataRepository     

    private MutableLiveData<String> mCurrentName;

    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = new MutableLiveData<>();
        }
        return mCurrentName;
    }
//Singleton code
...
}
9