当前位置: 首页 > 知识库问答 >
问题:

Android LiveData-如何在不同的活动上重用相同的ViewModel?

束志业
2023-03-14

示例视图模型:

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);

我想在第二个活动中调用 mModel.getCurrentName().setValue(otherName); 并使 MainActivity 接收更改。这可能吗?

共有3个答案

端木兴国
2023-03-14

只需创建ViewModel的实例,在本例中为NameViewModel

您的ViewModel Factory是这样的

class ViewModelFactory : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>) =
        with(modelClass){
            when {
                isAssignableFrom(NameViewModel::class.java) -> NameViewModel.getInstance()
                else -> throw IllegalArgumentException("Unknown viewModel class $modelClass")
            }
        } as T


    companion object {
        private var instance : ViewModelFactory? = null
        fun getInstance() =
            instance ?: synchronized(ViewModelFactory::class.java){
                instance ?: ViewModelFactory().also { instance = it }
            }
    }
}

你的视图模型呢

class NameViewModel : ViewModel() {

    //your liveData objects and many more...

    companion object {
        private var instance : NameViewModel? = null
        fun getInstance() =
            instance ?: synchronized(NameViewModel::class.java){
                instance ?: NameViewModel().also { instance = it }
            }
    }
}

现在您可以使用ViewModelProviders获取ViewModel的相同实例以在任何活动中使用

ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(NameViewModel::class.java)

运筹学

创建扩展函数以方便访问

fun <T : ViewModel> AppCompatActivity.getViewModel(viewModelClass: Class<T>) =
    ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(viewModelClass)
柴霖
2023-03-14

当使用ViewModelProviders获取视图模型时,您将作为生命周期所有者传递MainActivity,这将为该活动提供视图模型。在第二个活动中,您将获得该ViewModel的另一个实例,这次是第二个“活动”。第二个模型将有第二个实时数据。

您可以做的是在不同的层中维护数据,比如存储库,它可能是单例的,这样您就可以使用相同的视图模型。

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
...
}
景高杰
2023-03-14

当您调用 ViewModelProviders.of(this) 时,您实际上创建/保留绑定到的 ViewModelStore,因此不同的活动具有不同的 ViewModelStore,并且每个 ViewModelStore 使用给定的工厂创建 ViewModel 的不同实例,因此您不能在不同的 ViewModelStore 中具有相同的 ViewModel 实例。

但是,您可以通过传递自定义ViewModel工厂的单个实例来实现这一点,该工厂充当单例工厂,因此它将始终在不同的活动之间传递ViewModel的同一实例。

例如:

public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {


    NameViewModel t;

    public SingletonNameViewModelFactory() {
      //  t = provideNameViewModelSomeHowUsingDependencyInjection
    }

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

因此,您需要制作<code>SingletonNameViewModelFactory</code>singleton(例如,使用Dagger)并如下使用:

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

注意:

在不同作用域之间保留ViewModel是一种反模式。强烈建议保留数据层对象(例如,使DataSource或Repository成为单例),并在不同的范围(Activities)之间保留数据。

阅读这篇文章了解详细信息。

 类似资料:
  • 问题内容: 示例ViewModel: 主要活动: 我想调用第二个活动并使MainActivity接收更改。那可能吗? 问题答案: 调用时,您实际上创建/保留了绑定到的,因此不同的Activity具有不同的特性,并且每个Activity 使用给定的工厂创建a的不同实例,因此您不能在不同的s中具有相同的a实例。 但是,您可以通过传递自定义ViewModel工厂的单个实例(充当单例工厂)来实现此目的,因

  • 嗨,我正在开发一个android应用程序,有两个实际上相同的活动,但加载不同的数据。我目前有两个活动有很多重复的代码,我觉得我可以通过只使用一个活动来优化它。

  • 我正在使用以下项目 https://github.com/akotoe/android-slide-out-menu.git开发滑出菜单应用程序。 如何通过单击幻灯片菜单中的列表在同一视图中运行不同的活动。 例如,如果我单击项目1,我想在一个单独的活动中解析一个XML文件,并将该活动作为子项添加到此父视图中。因为在每一项单击上,我希望解析一个单独的XML文件,并且我希望在一个单独的布局文件中表示解

  • 问题内容: 在JavaFx中,我使用以下代码创建一个StackedBarChart: 结果是从1到8的系列具有不同的颜色。9-10系列与1-2系列具有相同的颜色。我试图在style.css文件中为条形图指定默认颜色,但似乎9-10系列实际上使用了颜色0和1。我认为这是一个错误。有谁知道解决方法? 问题答案: 颜色在8个系列之后被回收(原因是必须对定义的颜色数量进行一定的硬编码限制:JavaFX C

  • 我使应用程序有两个活动。 2 ExitText(登录名和密码) 第二个: 2 TextView(获取登录名和密码与共享首选项); 按钮(清除共享首选项上的数据,意图优先活动)。 如何下一步:当SharedReferences上有一些数据时-应用程序将从第二个屏幕启动。 例如,我提出: if(用户!=null 但是,从技术上讲,它首先运行第一个活动,然后再运行第二个活动。若有一些方法可以用另一个活动

  • 我有两项活动。我想用第一个活动(如)读卡,第二个活动写卡。因为在发现卡时,活动需要处于活动状态。因此,我对这两项活动都使用了以下设置: 然而,我的问题是,当我在第二个活动中扫描NFC卡时,手机会显示第一个和第二个活动的意向选择器。 那么,当我在第二个活动(反之亦然)中时,如何通过代码禁用第一个活动的intent过滤器? 这是完整的AndroidManifest文件:

  • 我使用了著名的Dagger ViewModelFactory模式,以便能够为所有活动中的所有视图模型注入工厂。 我遇到的问题是,当我将工厂注入到匕首时失败了,因为我不打算使用的对象的提供者并不总是可访问的。他们不是因为包含提供者的模块没有添加。 例如,我有一个LogIn活动和一个SignUp活动,这是我为它们添加子组件的方式: 请注意,当我为SignUpActivity创建子组件时,我没有添加模块

  • 我有类别片段和子类片段用于输入要查看的类别子类。我在导航图xml中有操作来打开子类片段。如果我打开任何根类别并单击其任何子类别,那么如果单击的子曲库有子曲库,那么当用户单击它的子曲库时,我应该打开子类片段。有像树一样的方案: 根类别片段: 子类别片段: 下一个子类别片段: 当我单击最后一个子类别片段,其中与前一个父片段相同的片段(相同的操作)时,我得到以下错误: 此处导航xml: 有人知道如何在N