Android 如何根据屏幕旋转连接视图和视图模型?

Android 如何根据屏幕旋转连接视图和视图模型?,android,android-viewmodel,Android,Android Viewmodel,ViewModel的一个承诺是,它可以在屏幕旋转等情况下生存。我仍在努力想办法在实践中组织起来 在模型的某些事件上,视图应该更新。有两个主要的选择: ViewModel将更新视图 视图观察ViewModel并更新自身 在第一种情况下,ViewModel需要指向视图的链接。我可以将视图注入ViewModel,但我的感觉是将VieModel注入视图会更好 加入他们最好的方式是什么 然后在旋转之后,再次调用onCreate()方法,再次触发ViewModel的初始化。我需要检查这一点,否则我将面临两次

ViewModel的一个承诺是,它可以在屏幕旋转等情况下生存。我仍在努力想办法在实践中组织起来

在模型的某些事件上,视图应该更新。有两个主要的选择:

  • ViewModel将更新视图
  • 视图观察ViewModel并更新自身
  • 在第一种情况下,ViewModel需要指向视图的链接。我可以将视图注入ViewModel,但我的感觉是将VieModel注入视图会更好

    加入他们最好的方式是什么

    然后在旋转之后,再次调用onCreate()方法,再次触发ViewModel的初始化。我需要检查这一点,否则我将面临两次、三次向实际模型注册侦听器以及类似问题的危险。我甚至可能需要首先清理与旧观点的关系

    这种检查感觉有点不干净。如果这是一种标准做法,我希望在ViewModel中为此提供一个专用API。如果没有,我会觉得自己走错了路


    什么样的好模式可以以干净的标准方式处理此问题?

    Soo。。你真的不必连接ViewModel和“关于屏幕旋转”的活动/片段,你可以免费获得它——这是一个额外的好处

    这个官员真的很好

    您可以在
    onCreate()
    中通过以下方式将ViewModel连接到视图

    public class MyActivity extends AppCompatActivity {
    
        public void onCreate(Bundle savedInstanceState) {
            MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
            model.getUsers().observe(this, users -> {
                updateUI()
            });
        }
    }
    
    虽然正如您所说,方向更改将再次触发
    onCreate()
    ,但这不会创建新的ViewModel。
    MyViewModel
    仅在
    onCreate
    中第一次创建。重新创建的活动接收由第一个活动创建的相同的
    MyViewModel
    实例。这甚至适用于引用同一ViewModel的不同片段/活动

    永远不要将视图注入ViewModel。这相当于溺水的小狗。如果需要ViewModel中的上下文,请扩展
    AndroidViewModel
    (并将其传递给
    应用程序

    您要做的是创建一个保存所有状态的ViewModel。并处理从网络或磁盘或其他地方获取数据。所有与UI无关的内容都会进入ViewModel(根据经验)。所有视图更新内容都进入活动/片段

    上面示例中的ViewModel可能如下所示

    public class MyViewModel extends ViewModel {
    
        private MutableLiveData<List<User>> users;
    
        public LiveData<List<User>> getUsers() {
            if (users == null) {
                users = new MutableLiveData<List<Users>>();
                loadUsers();
            }
            return users;
        }
    
        private void loadUsers() {
            // Do an asynchronous operation to fetch users.
        }
    }
    
    公共类MyViewModel扩展了ViewModel{
    私有可变LiveData用户;
    公共LiveData getUsers(){
    如果(用户==null){
    用户=新的可变LiveData();
    loadUsers();
    }
    返回用户;
    }
    私有void loadUsers(){
    //执行异步操作以获取用户。
    }
    }
    

    这通常意味着可能应该将单击事件传递到ViewModel中,以便它能够对数据进行处理。视图只会对更新的(经过处理的)数据做出反应

    Soo。。你真的不必连接ViewModel和“关于屏幕旋转”的活动/片段,你可以免费获得它——这是一个额外的好处

    这个官员真的很好

    您可以在
    onCreate()
    中通过以下方式将ViewModel连接到视图

    public class MyActivity extends AppCompatActivity {
    
        public void onCreate(Bundle savedInstanceState) {
            MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
            model.getUsers().observe(this, users -> {
                updateUI()
            });
        }
    }
    
    虽然正如您所说,方向更改将再次触发
    onCreate()
    ,但这不会创建新的ViewModel。
    MyViewModel
    仅在
    onCreate
    中第一次创建。重新创建的活动接收由第一个活动创建的相同的
    MyViewModel
    实例。这甚至适用于引用同一ViewModel的不同片段/活动

    永远不要将视图注入ViewModel。这相当于溺水的小狗。如果需要ViewModel中的上下文,请扩展
    AndroidViewModel
    (并将其传递给
    应用程序

    您要做的是创建一个保存所有状态的ViewModel。并处理从网络或磁盘或其他地方获取数据。所有与UI无关的内容都会进入ViewModel(根据经验)。所有视图更新内容都进入活动/片段

    上面示例中的ViewModel可能如下所示

    public class MyViewModel extends ViewModel {
    
        private MutableLiveData<List<User>> users;
    
        public LiveData<List<User>> getUsers() {
            if (users == null) {
                users = new MutableLiveData<List<Users>>();
                loadUsers();
            }
            return users;
        }
    
        private void loadUsers() {
            // Do an asynchronous operation to fetch users.
        }
    }
    
    公共类MyViewModel扩展了ViewModel{
    私有可变LiveData用户;
    公共LiveData getUsers(){
    如果(用户==null){
    用户=新的可变LiveData();
    loadUsers();
    }
    返回用户;
    }
    私有void loadUsers(){
    //执行异步操作以获取用户。
    }
    }
    

    这通常意味着可能应该将单击事件传递到ViewModel中,以便它能够对数据进行处理。视图只会对更新的(经过处理的)数据做出反应

    你好!!它不是第二次创建的。观察员被第二次注册。根据
    getUsers().observe()
    的实现,回调
    updateUI()
    可能在第一次旋转后调用两次,在第二次旋转后调用三次。然后调用
    .getUsers()
    将模型的逻辑绘制到视图中。这是第二个原因,为什么我认为这是官方文件中一个相当糟糕的例子。在我看来,他们教坏习惯。现在,我们需要找出最佳实践,至少是更好的实践。哦,如果我误解了,对不起。但我看不出有什么问题。如果您旋转屏幕,您的活动将通过其
    onDestroy
    。因此,您当然希望再次注册观察者,以便获得数据以再次更新UI—因为没有更多的UI。或者您是说您正在连续获得3次更新?我不明白您使用
    的意思。getUsers()
    将模型的逻辑绘制到视图中。观察者只应画入(观察)待观察模型的一部分