如何使用临时子视图生成组合视图模型? [英] How to generate composed view models with temporary sub views?

查看:24
本文介绍了如何使用临时子视图生成组合视图模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个测验生成器,它生成一系列不同类别的测验.序列长度不限.

I have a quizz generator, which generates a sequence of quizzes of different classes. The sequence is of unlimited length.

测验生成器有一个视图模型.每种类型的测验都有一个视图模型.测验生成器视图模型应根据测验的类创建测验的视图模型.

There is a view model for the quizz generator. There is a view model for each type of a quizz. The quizz generator view model should create the view models of the quizzes depending on their classes.

视图模型不能包含对生命周期的引用,但我需要生命周期来创建视图模型.

A view model must not hold a reference to the lifecycle, but I need the lifecycle to create view models.

ViewModelProviders.of(lifecycle).get(classForQuizzType);

问题

在哪里创建测验的子视图模型?

Questions

Where do I create the sub view models of the quizzes?

我能想到的一个解决方案是每次从活动中注入子视图模型.这是绕道而行,尤其是在涉及嵌套视图时.

The one solution I can think of is to inject the sub view model from the activity each time. This is a detour, especially if nested views are involved.

另一种解决方案是在嵌套视图中创建视图模型,这看起来也很丑陋,因为从视图内部访问生命周期并不常见.

The other solution is to create the view model in the nested view, which seems ugly either, as it is not common practice to access the lifecycle from inside a view.

如果没有干净的解决方案,我的架构方法有什么问题?我应该在这种场景中使用片段吗?

If there is no clean solution, what's wrong with my approach of architecture? Should I use fragments for this kind of scenario?

推荐答案

如果没有干净的解决方案,我的方法有什么问题建筑学?我应该在这种场景中使用片段吗?

If there is no clean solution, what's wrong with my approach of architecture? Should I use fragments for this kind of scenario?

是的,片段是正确的选择

总结:

  1. 除了通过 LiveData 绑定 Views 之外,没有真正的替代方法.
  2. 如果使用 LiveData,则需要 LifeCycle.
  3. 如果序列中子视图的生命周期应该短于 Activity 的生命周期,那么片段就是要走的路.
  1. There is no real alternative to binding Views by LiveData.
  2. If using LiveData a LifeCycle is required.
  3. If the lifecycle of a sub views in a sequence should be shorter than the lifecycle of the activity, then fragments are the way to go.

详情

除了通过 LiveData 绑定 Views 之外,没有真正的替代方法.

视图模型不应包含对视图的未终止引用,否则只要视图模型存在,视图就会存在,从而导致内存泄漏.共有三种观察者模式来讨论视图如何观察视图模型.

Details

There is no real alternative to binding Views by LiveData.

View models should not hold unterminated references to views, else the views exists as long as the view model exists causing memory leaks. There are three observer patterns to discuss how views could observe view models.

a.) MutableLiveData

a.) MutableLiveData

它们需要一个生命周期.当生命周期结束时,引用会自动清理.这是推荐的解决方案.

They require a lifecycle. The references are cleaned up automatically, when the lifecycle ends. This is the recommended solution.

b.) 弱引用

理论上这应该可行.当对视图的最后一个硬引用消失时,垃圾收集器应该清除弱引用.在实践中,解决方案是不稳定的,引用有时会过早地消失.

In theory this should work. The weak reference should be cleaned up by the garbage collector, when the last hard reference to the view is gone. In practice the solution is unstable and references sometime go away prematurely.

c.) 手工观察者

手工观察者必须调用remove方法.不幸的是,当视图消失时,没有定义的破坏钩子.视图中没有调用 remove 方法的地方.

A handmade observer must call a remove method. Unfortunately there is no defined destruction hook, when a view goes away. There is no place to call the remove method in a view.

因此,根据我的经验,a.) 是唯一可能的解决方案.

As a result a.) is the only possible solution according to my experience.

这里提到的子视图是按顺序创建的.如果我们将它们绑定到 Activity,它们会一直堆积直到 Activity 消失,尽管它们只在一小段时间内被依次需要.

The sub views mentioned here are created in a sequence. If we would bind them to the activity, they would pile up until the activity goes away although they are only needed for a small interval of time in sequence.

片段可以存在于活动时间的子部分.它们是将序列的子视图绑定到它们的正确解决方案.

Fragments can exist for a subpart of the time of the activity. They are the right solution to bind the sub views of the sequence to them.

这里的测验称为挑战.FragmentManger 始终是活动的,而 LifecycleOwner 是活动或片段.

The quizzes are called challenges here. The FragmentManger is always that of the activity, while the LifecycleOwner is either the activity or a fragment.

# A view model acceptor interface for views

public interface ViewModelAcceptor<T extends  ViewModel> {
    void plugViewModel(
        T viewModel,
        LifecycleOwner lifecycleOwner,
        FragmentManager fragmentManager
    );
}

# In the parent view class of the challenges new challenges are created
# in sequence

ChallengeFragment challengeFragment = new ChallengeFragment();
challengeFragment.setChallengeViewModel(challengeViewModel);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(this.getId(), challengeFragment);
fragmentTransaction.commit();

# ChallengeFragment

public class ChallengeFragment extends Fragment {

    private ChallengeViewModel challengeViewModel;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        return new ChallengeView(getActivity(), null);
    }

    public void setChallengeViewModel(ChallengeViewModel challengeViewModel) {
        this.challengeViewModel = challengeViewModel;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ChallengeView challengeView = (ChallengeView) getView();
        Objects.requireNonNull(challengeView)
                .plugViewModel(challengeViewModel, this, getFragmentManager());
    }

}
# Challenge views are the child views of the sequence

public class ChallengeView extends ConstraintLayout implements ViewModelAcceptor<ChallengeViewModel> {
  [...]
}

这篇关于如何使用临时子视图生成组合视图模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆