实现ViewModel
的建议方法是通过将LiveData
个对象用于活动,片段和视图来公开更改的数据。有些情况下,LiveData
不是理想答案或根本没有答案。
自然的替代方案是,将观察者模式应用于ViewModel
,使其成为可观察的。将观察者注册到ViewModel
时,ViewModel
将保留回调引用以通知观察者。
文档说,ViewModel
不得包含对活动,片段或视图的引用。我发现“为什么”这个问题的唯一答案是,这可能会导致内存泄漏。然后如何清理引用以避免内存泄漏?
对于观点来说,这是一个难点。当视图消失时,没有确定的时刻。但是活动和片段具有已定义的生命周期。因此,有些地方可以作为观察员取消注册。
你怎么看?如果您注意始终取消注册它们,将活动注册为ViewModels
是否有效?您是否找到了有关此问题的任何有效信息?
我为最佳答案设定了一个小奖励。这不是因为我认为它是推荐的解决方案(因为它不适用于视图)。我只想知道并扩展我的选择。
public class ExampleViewModel extends ViewModel {
public interface OnEndListener {
public void onEnd();
}
private List<OnEndListener> onEndListeners = new ArrayList<>();
public void setOnEndListener(OnEndListener onEndListener) {
onEndListeners.add(onEndListener);
}
public void removeOnEndListener(OnEndListener onEndListener) {
onEndListeners.remove(onEndListener);
}
public void somethingHappens() {
for (OnEndListener onEndListener: new ArrayList<OnEndListener>(onEndListeners) ) {
onEndListener.onEnd();
}
}
}
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
ExampleViewModel.OnEndListener onEndListener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onEndListener = new ExampleViewModel.OnEndListener() {
@Override
public void onEnd() {
finish();
}
};
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.setOnEndListener(onEndListener);
}
@Override
protected void onDestroy() {
super.onDestroy();
exampleViewModel.removeOnEndListener(onEndListener);
}
}
答案 0 :(得分:0)
问“我被允许......”并不是一个真正有用的问题,IMO。文档很清楚,你所暗示的是劝阻和原因。也就是说,我希望您的代码可能会按预期工作,因此“允许”(即不受技术限制)。
一个可能出现的问题:ExampleActivity
的InstanceA已启动并启动ExampleViewModel
上的一些长期运行任务。然后,在任务完成之前,由于配置更改,设备将被轮换并且InstanceA将被销毁。然后,在销毁InstanceA和创建新InstanceB之间的,长时间运行的任务完成,您的视图模型调用onEndListener.onEnd()
。除外:哦不! onEndListener
为null
,因为当InstanceA被销毁且尚未由InstanceB设置时它已被清除:NullPointerException
ViewModel
被设计为(部分)精确地来处理边缘情况,如上面的陷阱场景。因此,为什么不使用它提供的工具和ViewModel
来完成同样的事情,而不是反对LiveData
的预期用途? (并且代码越少,我可能会添加。)
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.getOnEndLive().observe(this, new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean onEnd) {
if (onEnd != null && onEnd) {
finish();
}
}
});
}
}
public class ExampleViewModel extends ViewModel {
private MutableLiveData<Boolean> onEndLive = new MutableLiveData<>();
public MutableLiveData<Boolean> getOnEndLive() {
return onEndLive;
}
public void somethingHappens() {
onEndLive.setValue(true);
}
}
在这种情况下,将LiveData视为实际的“数据”本身,而不是您可以从ViewModel传递到Activity的信号。我一直都在使用这种模式。