Android MVVM。生命周期感知模型是代码味道还是适当的设计?
Android MVVM. Is life-cycle aware Model a code smell or a proper design?
对于我的 activity,我需要知道 phone 的连接状态。
由于这是我的 UI 需要响应的数据,因此它属于 MVVM 的模型领域(如果您不同意,请告诉我)。
为了在不需要时不执行代码,我的模型代码当前正在订阅 onCreate()
中的 phone 连接更改,并通过实施 LifecycleObserver
在 onDestroy()
中取消注册
为此,我在 Activity 代码中用 viewModel 实例化并连接了我的模型。
总感觉不对。
在理想的世界中,Activity 将成为视图层(MVVM 中的 V)的一部分,并且应该只知道 viewModel,但在上述情况下,生命周期意识使 activity 也了解模型。
那么,生命周期感知模型是一个恰当的概念吗?还是我应该重新考虑设计?
我真的很喜欢那个图案。在全局可共享对象中实现状态监听的示例是
public class WifiState {
private static WifiState instance;
public static synchronized WifiState getInstance(Context context) {
if (instance == null) instance = new WifiState(context.getApplicationContext());
return instance;
}
private final Context context;
private final WifiManager wm;
private WifiState(Context context) {
this.context = context;
wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
wifiStateLiveData.setValue(state);
}
};
public LiveData<Integer> wifiState() { return wifiStateLiveData; }
private final MutableLiveData<Integer> wifiStateLiveData = new MutableLiveData<Integer>() {
@Override
protected void onActive() {
setValue(wm.getWifiState()); // update immediately
context.registerReceiver(receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
}
@Override
protected void onInactive() {
context.unregisterReceiver(receiver);
}
@Override
public void setValue(Integer value) { // debounce non-change
Integer old = getValue();
if (old == null && value != null || old != null && !old.equals(value)) {
super.setValue(value);
}
}
};
}
这允许您同时从多个地方使用相同的源,而无需创建多个广播接收器等的开销
public class SomeActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WifiState.getInstance(this).wifiState().observe(this, state -> {
if (state != WifiManager.WIFI_STATE_ENABLED) {
Toast.makeText(this, "Please enable WIFI", Toast.LENGTH_LONG);
}
});
}
}
使用生命周期功能的一大优势是您不必在代码中使用 onStart / onStop 调用,而且您不会再错过 onStop 调用和泄漏接收器等。奇迹发生在某些库中,您的代码可以变得相当简单和干净。无论您实施 LifecycleObserver
还是使用 LiveData
,如果操作得当,您最终会得到更简洁的代码。
让框架处理您的 ViewModel
的生命周期也很好,但它在 MV* 架构方面并没有太大变化,因为您之前以某种方式拥有 ViewModel。您可能直接在 Activity / Fragment 中计算了属性。这里的新功能是框架现在会在适当的时间内为您保留该模型。您之前可以使用保留的 Fragment 来完成此操作,而这正是现在发生的事情。
对于我的 activity,我需要知道 phone 的连接状态。 由于这是我的 UI 需要响应的数据,因此它属于 MVVM 的模型领域(如果您不同意,请告诉我)。
为了在不需要时不执行代码,我的模型代码当前正在订阅 onCreate()
中的 phone 连接更改,并通过实施 LifecycleObserver
在 onDestroy()
中取消注册
为此,我在 Activity 代码中用 viewModel 实例化并连接了我的模型。
总感觉不对。
在理想的世界中,Activity 将成为视图层(MVVM 中的 V)的一部分,并且应该只知道 viewModel,但在上述情况下,生命周期意识使 activity 也了解模型。
那么,生命周期感知模型是一个恰当的概念吗?还是我应该重新考虑设计?
我真的很喜欢那个图案。在全局可共享对象中实现状态监听的示例是
public class WifiState {
private static WifiState instance;
public static synchronized WifiState getInstance(Context context) {
if (instance == null) instance = new WifiState(context.getApplicationContext());
return instance;
}
private final Context context;
private final WifiManager wm;
private WifiState(Context context) {
this.context = context;
wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
wifiStateLiveData.setValue(state);
}
};
public LiveData<Integer> wifiState() { return wifiStateLiveData; }
private final MutableLiveData<Integer> wifiStateLiveData = new MutableLiveData<Integer>() {
@Override
protected void onActive() {
setValue(wm.getWifiState()); // update immediately
context.registerReceiver(receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
}
@Override
protected void onInactive() {
context.unregisterReceiver(receiver);
}
@Override
public void setValue(Integer value) { // debounce non-change
Integer old = getValue();
if (old == null && value != null || old != null && !old.equals(value)) {
super.setValue(value);
}
}
};
}
这允许您同时从多个地方使用相同的源,而无需创建多个广播接收器等的开销
public class SomeActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WifiState.getInstance(this).wifiState().observe(this, state -> {
if (state != WifiManager.WIFI_STATE_ENABLED) {
Toast.makeText(this, "Please enable WIFI", Toast.LENGTH_LONG);
}
});
}
}
使用生命周期功能的一大优势是您不必在代码中使用 onStart / onStop 调用,而且您不会再错过 onStop 调用和泄漏接收器等。奇迹发生在某些库中,您的代码可以变得相当简单和干净。无论您实施 LifecycleObserver
还是使用 LiveData
,如果操作得当,您最终会得到更简洁的代码。
让框架处理您的 ViewModel
的生命周期也很好,但它在 MV* 架构方面并没有太大变化,因为您之前以某种方式拥有 ViewModel。您可能直接在 Activity / Fragment 中计算了属性。这里的新功能是框架现在会在适当的时间内为您保留该模型。您之前可以使用保留的 Fragment 来完成此操作,而这正是现在发生的事情。