首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从片段返回时,ViewModel onchange被多次调用

从片段返回时,ViewModel onchange被多次调用
EN

Stack Overflow用户
提问于 2018-02-22 03:51:02
回答 10查看 31.3K关注 0票数 36

我正在使用Android架构组件。我想要的是当用户在Edittext中键入"0“并点击按钮来替换新的片段时,如果键入任何其他内容,则发布Toast错误消息。问题是,当我从新的Fragment(BlankFragment)返回并再次单击按钮并再次键入"0“并单击时,会多次调用onchange(),因此会多次创建片段

FragmentExample.class:

代码语言:javascript
复制
     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        manager = getActivity().getSupportFragmentManager();
        viewmModel = ViewModelProviders.of(getActivity(), viewModelFactory)
                .get(VModel.class);

        View v = inflater.inflate(R.layout.fragment_list, container, false);   
        b = (Button) v.findViewById(R.id.b);
        et = (EditText) v.findViewById(R.id.et);

        viewmModel.observeData().observe(getActivity(), new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {

                if(s.equals("0")) {
                    BlankFragment fragment = (BlankFragment) manager.findFragmentByTag(DETAIL_FRAG);
                    if (fragment == null) {
                        fragment = BlankFragment.newInstance();
                    }
                    addFragmentToActivity(manager,
                            fragment,
                            R.id.root_activity_detail,
                            DETAIL_FRAG
                    );
                } else {
                    Toast.makeText(getContext(), "Wrong text", Toast.LENGTH_SHORT).show();
                }
            }
        });

        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewmModel.setData(et.getText().toString());
            }
        });
        return v;
    }
    private void addFragmentToActivity(FragmentManager fragmentManager, BlankFragment fragment, int root_activity_detail, String detailFrag) {
        android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(root_activity_detail, fragment, detailFrag).addToBackStack(detailFrag);
        transaction.commit();
    }

存储库类:

代码语言:javascript
复制
    public class Repository {
    MutableLiveData<String> dataLive = new MutableLiveData<>();  

    public Repository() {

    }

    public void setListData(String data) {
       dataLive.setValue(data);
    }

    public MutableLiveData<String> getData() {
        return dataLive;
    }
}

BlankFragment.class:

代码语言:javascript
复制
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        listItemViewModel = ViewModelProviders.of(this, viewModelFactory)
                .get(VModel.class);
        listItemViewModel.setData("");
        return inflater.inflate(R.layout.fragment_blank, container, false);
    }
EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2018-03-07 14:30:33

这里的问题是,当您将片段从活动中分离出来时,片段及其视图模型都不会被销毁。当您返回时,当旧的观察者仍然在相同的片段中时,您将一个新的观察者添加到livedata中(如果您在onCreateView()中添加该观察者)。有一个article (实际上甚至是一个SO线程)在谈论它(有解决方案)。

修复它的简单方法(也在本文中)是在向其添加观察者之前从livedata中删除任何观察者。

更新:在support lib v28中,一个名为ViewLifeCycleOwner的新LifeCycleOwner应该会修复here中的更多信息

票数 21
EN

Stack Overflow用户

发布于 2018-05-09 02:33:11

您应该使用LifecycleOwner,而不是使用getActivity作为片段。

变化

代码语言:javascript
复制
viewModel.observeData().observe(getActivity(), new Observer<String>() {

代码语言:javascript
复制
viewModel.observeData().removeObservers(this);
viewModel.observeData().observe(this, new Observer<String>() {
票数 10
EN

Stack Overflow用户

发布于 2018-03-07 07:37:54

您不应该在onCreateView中创建viewmModel,而应该在onCreate中创建,这样就不会在每次创建视图时都向数据添加侦听器。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48914311

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档