【问题标题】:ViewModel method name conventionViewModel 方法名称约定
【发布时间】:2018-05-29 10:52:39
【问题描述】:

ViewModel 类中命名方法的最佳方式是什么?基于其动作/行为或 Activity/Fragment 的生命周期?

例如:

以其动作命名的方法

override fun onResume() {
    super.onResume()
    viewModel.connect()
}

override fun onPause() {
    super.onPause()
    viewModel.disconnect()
}

override fun onItemCheckedChanged(task: Task, value: Boolean) =
    viewModel.updateTaskStatus(task, value)

Android 生命周期命名的方法

override fun onResume() {
    super.onResume()
    viewModel.onResume()
}

override fun onPause() {
    super.onPause()
    viewModel.onPause()
}

override fun onItemCheckedChanged(task: Task, value: Boolean) =
    viewModel.onItemCheckedChanged(task, value)

网上有几个例子,两种方法都用到了。

在我看来,方法应该和生命周期相关,这样View不需要知道ViewModel背后的逻辑,只需要知道需要调用一个生命周期方法即可。

最好的方法是什么?

【问题讨论】:

  • 依赖 onPause/onResume 意味着在多窗口模式下,当另一个应用有焦点时,你的应用“停止接收东西”:最好只使用 Jetpack 提供的 LiveData
  • @EpicPandaForce,是的,我在实际项目中使用 LiveData 并使用 Lifecycle 来控制状态。这只是一个示例名称约定的 sn-p。 :)
  • 在这种情况下,您实际上不需要连接或断开连接,因为您公开了 LiveData 并在它们上调用 observe

标签: android mvvm kotlin viewmodel convention


【解决方案1】:

没有正确的方法,只要代码干净且易于阅读/理解即可。但是,如果您查看 examples Android give,它们显示的方法与您发布的方法相似。

1) 一种方法是使用由 Android 生命周期命名的方法(您提到的)拥有一个对象。

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}

每个函数都是在生命周期所有者中手动调用的,如下所示:

@Override
public void onStart() {
    super.onStart();
    myLocationListener.start();
    // manage other components that need to respond
    // to the activity lifecycle
}

@Override
public void onStop() {
    super.onStop();
    myLocationListener.stop();
    // manage other components that need to respond
    // to the activity lifecycle
}

2) 但是,如果你想通过它们的动作来命名方法,你可以在它们旁边加上 OnLifecycleEvent 注释,这是在Android Jetpack 中令人兴奋地带给我们的!比如:

public class MyLocationListener implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}

现在这些方法在 LifecycleObserver 的帮助下自动调用,LifecycleOwner 可以观察到:

myLifecycleOwner.getLifecycle().addObserver(new MyLocationListener());

LifecycleOwner 通常是ActivityFragment。由你决定,但我更喜欢LifecycleObserver,因为它需要更少的代码,我认为这使它看起来更干净。

如果您对良好的 Android 实践和一些帮助您一路走来的提示感兴趣,我会推荐一些好的页面:

- Android best practices

- Android tips & tricks

- Android must have libraries

【讨论】:

  • 那么如果我们使用LifecycleObserverLifecycleObserverViewModel 之间的正确关系是什么? 1) ViewModel 实现 LifecycleObserver 2) ViewModel 具有 LifecycleObserver 作为属性 3) 自定义 LiveData 拥有 ViewModel 作为属性 4) ViewModel 拥有自定义 @987654347 @ 作为属性
【解决方案2】:

IMO 最好的方法是使用生命周期的名称,原因如下:

  1. 它使视图(片段)更笨拙。实际上,只要您将函数命名为 connect(),视图就会做出连接的决定(逻辑)。
  2. 如果您现在想在onResume() 中执行其他操作,例如刷新数据,会发生什么情况?您是否添加了另一个名为refreshData() 的函数并在connect() 之后调用它?还是在connect() 之前调用它,因为您知道必须刷新数据才能连接。糟糕,您已向视图添加了更多隐式逻辑,仅对视图模型的测试将无法捕获。最好打电话给fun onResume() { refreshData(); connect(); }
  3. 一般来说,您应该按照“发生在我身上的事情”来命名所有视图事件。例如。 didPressDowload() orderConfirmed() 等。如果您将其命名为 orderPizza(),这就像一个命令,如果您想像 fun orderPizza() { if (orderEmpty) return ....} 这样的命令失败,那么该函数将不再执行名称中所说的操作。 有时它是很小的语义,但有时它确实可以为您节省错误并让您对如何仅将逻辑保留在视图模型中感到困惑。 请参阅 https://redux.js.org/style-guide/style-guide#model-actions-as-events-not-setters 以获取来自网络世界的类似建​​议。

【讨论】:

    猜你喜欢
    • 2019-11-10
    • 2017-02-27
    • 2021-02-17
    • 2023-04-02
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多