如何获取 ViewModel?

How to get a ViewModel?

我只想在我的 Fragment(扩展 Fragment)中获取对我的 ViewModel.class(从 AndroidViewModel 扩展)的引用。到处都是这样描述的:

UserModel userModel = ViewModelProviders.of(getActivity()).get(UserModel.class);

description on Android Developer

...,但是 ViewModelProviders 早就被弃用了。

*此 class 在 API 级别 1.1.0 中已弃用。 *

我无法通过以下方式导入 class: android.arch.lifecycle.[ViewModelProviders]

它只提供 ViewModelProvider 和其他东西。


我如何获得我的 UserModel.class 的实例?

but ViewModelProviders is deprecated since long ago

ViewModelProviders 未弃用。所以,使用 ViewModelProviders:

ViewModelProviders.of(yourFragment).get(UserModel.class)

ViewModelProviders 中有 部分 被弃用,例如它的构造函数,但 class 总体上没有。

更新:2020-05-28 现在 ViewModelProviders 已弃用。在 Kotlin 中,使用 by viewModels() 和相关的 属性 代表。在 Java 中,使用 new ViewModelProvider(...).get(UserModel.class)(对于 ... 的各种值,具体取决于那些视图模型的范围)。

下面是如何写 ViewModel

public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
    if (users == null) {
        users = new MutableLiveData<List<User>>();
        loadUsers();
    }
    return users;
}

private void loadUsers() {
    // Do an asynchronous operation to fetch users.
}
}

然后在你的活动中使用它做这样的事情

public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
    // Create a ViewModel the first time the system calls an activity's onCreate() method.
    // Re-created activities receive the same MyViewModel instance created by the first activity.

    MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
    model.getUsers().observe(this, users -> {
        // update UI
    });
}
}

将 Kotlin 与最新的 Android 架构组件一起使用,您应该像这样使用 by viewModels() Kotlin 属性 委托:

class YourFragment : Fragment() {
   private val viewModel by viewModels<YourViewModel>()
}

更多信息here

class ViewModelProviders 已弃用! 使用ViewModelProvider明白了。

MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

编码愉快:)

在深入研究之后,我通过将以下方法添加到我的活动中解决了我的类似问题:

protected final <T extends ViewModel> T obtainViewModel(@NonNull AppCompatActivity activity, @NonNull Class<T> modelClass) {
    ViewModelProvider.AndroidViewModelFactory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(activity.getApplication());
    return new ViewModelProvider(activity, factory).get(modelClass);
}

然后我在我的 Fragments 中这样做了:

protected final <T extends ViewModel> T obtainFragmentViewModel(@NonNull FragmentActivity fragment, @NonNull Class<T> modelClass) {
    ViewModelProvider.AndroidViewModelFactory factory = ViewModelProvider.AndroidViewModelFactory.getInstance(fragment.getApplication());
    return new ViewModelProvider(fragment, factory).get(modelClass);
}

我已经有一些抽象的超级 类 用于菜单用途,所以我将方法隐藏在那里,这样我就不必在每个 activity 中重复它。这就是他们受到保护的原因。我相信如果你把它们放在你需要它们的每个 activity 或片段中,它们可能是私有的。

为了尽可能清楚,我会在 activity 的 onCreate() 中调用方法来分配我的视图模型,它看起来像这样

private MyViewModel myViewModel;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    myViewModel = obtainViewModel(this, MyViewModel.class);
}

或片段

private MyViewModel myViewModel;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getActivity() != null) {
        myViewModel = obtainFragmentViewModel(getActivity(), MyViewModel.class);
    }
}

的 Kotlin 版本是

val vm = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)