有关Android体系结构组件中每个组件的职责的问题

时间:2019-04-19 08:12:36

标签: android android-architecture-components android-mvp android-mvvm

我使用MVP已有很长时间了,我开始转移到MVP和MVVM之间的混合状态

详细地,我的应用将像这样:

  • 每个活动都有0到x个表示其视图的片段
  • 每个Fragment都将请求Activity的ViewModel,以便他们可以使用LiveData检索数据
  • 该活动将有一个单独的ViewModel,它将充当演示者。创建后,将向ViewModel注入带有LiveData的Activity的ViewModel,以便可以根据需要更新UI
  • 演示者将获得发送到数据ViewModel的消息,并将结果发送回给它

我的问题:

  1. 在演示者ViewModel中保留对数据ViewModel的引用会导致内存泄漏或诸如内存泄漏之类的不利影响吗?
  2. 业务逻辑应该在哪里?在演示者中还是在模型部分中?

例如,假设我有一个项目列表,而用户长按一个项目列表,则该体系结构的哪个部分应负责检查用户是否有权执行此操作,并让他们编辑该项目或显示错误消息?

  1. 片段是否有办法只获得Activity的ViewModel的一部分?

例如,假设活动下有3个片段,并且有一个ViewModel可以满足这些需求

我可以使用类似的东西吗

class MainViewModel : ViewModel() , IFragmentA, IFragmentB, IFragmentC

,然后当我尝试在片段中获取ViewModel时,我可以编写如下内容:

lateinit var viewModel: IFragmentA

override fun onAttach(context: Context?) {
    super.onAttach(context)
    vm = ViewModelProviders.of(context as AppCompatActivity).get(IFragmentA::class.java)
}

注意:我知道上面的代码不起作用,我要问的是,是否有一种类似的方法可以起作用

  1. 将消息发送回活动SingleEvents的正确方法是吗?

例如,如果用户尝试删除条目,而我希望他们输入密码,则流程为:

  • 片段将要删除的消息发送到其ViewModel
  • ViewModel将其传递给Presenter
  • 演示者决定继续进行操作之前需要密码验证
  • 演示者在ViewModel中设置SingleEvent的值
  • ViewModel通知事件的订阅者(在本例中为MainActivity)他们应该显示一个对话框,要求输入密码

感谢您提供的任何帮助

1 个答案:

答案 0 :(得分:4)

我最近将我的应用程序之一从MVP移植到了MVVM体系结构。不管是部分完成还是全部完成,您都在朝着美观大方的方向发展,并且您会喜欢它。

在查看答案之前,请先查看此MVVM架构图以及其中的一些要做与不要做的事情

MVVM Architecture

让我们在这里查看每个类的角色。

活动/片段:

-监听MutableLiveData Obeservers并将Data设置为视图,这里没有其他逻辑。

ViewModel

  • 用户输入验证(用户名,密码为空或为空检查)
  • 设置您的mutableLive
  • 询问存储库以使用回调启动任务网络或localdatastorage(sqlite)。

存储库

  • 缓存所需数据。
  • 不应保留对ViewModel的任何引用,否则将创建循环依赖项。
  • 决定要做什么-是进行网络呼叫还是从本地存储加载数据。对接收到的数据进行处理(业务逻辑)。
  • 使用从ViewModel收到的回调将数据更新到viewModel,严格不直接通信。

RemoteDataSource

  • 进行网络调用,并将接收到的数据返回给存储库。

LocalDataSource

  • 处理所有与SQLite相关的内容,并通过回调提供请求的数据。

google中有一个待办事项应用示例项目,该项目使用MVVM。请参考它,将非常有帮助。

  1. 没有演示者-检查用户在viewmodel上的输入,并使用存储库进行通信,并使用MutableLiveData进行通信。
  2. 在存储库中执行业务逻辑,将其更像是mvp模式中的模型。
  3. 您可以为活动及其片段使用单个viewModel。您所有的片段都通过一个viewModel进行通信。因此,每个片段只会对其侦听的LiveDataObserver做出反应。

在MVVM的Google示例项目中,实际上有此用例的示例。

AddEditTaskActivity.java

public static AddEditTaskViewModel obtainViewModel(FragmentActivity activity) {
       // Use a Factory to inject dependencies into the ViewModel        
 ViewModelFactoryfactory= ViewModelFactory.getInstance(activity.getApplication());
 return ViewModelProviders.of(activity, factory).get(AddEditTaskViewModel.class);
   }

AddEditTaskFragment.java

 @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.addtask_frag, container, false);
        if (mViewDataBinding == null) {
            mViewDataBinding = AddtaskFragBinding.bind(root);
        }

        mViewModel = AddEditTaskActivity.obtainViewModel(getActivity());

        mViewDataBinding.setViewmodel(mViewModel);
        mViewDataBinding.setLifecycleOwner(getActivity());

        setHasOptionsMenu(true);
        setRetainInstance(false);

        return mViewDataBinding.getRoot();
    }

  1. 密码验证流程:
    • 片段要求ViewModel删除条目。
    • 询问存储库,以确定是否有必要使用我们已经拥有的数据或与本地数据源进行通信进行验证。
    • ViewModel从存储库收到一个回调,要求进行验证,ViewModel更新各自的MutableLiveData showVerification.postValue(true);。
    • 当活动正在监听showVerificationObserver时,它会显示验证UI。

希望有帮助。