【问题标题】:Observer for MutableLiveData not being triggered未触发 MutableLiveData 的观察者
【发布时间】:2019-10-26 20:31:52
【问题描述】:

我正在使用 MutableLiveData 开发一个活动,以使我的片段与从搜索中检索到的结果保持同步,但在结果列表更新后未触发观察者。

在主要活动中,我有一个 EditText,我在其中键入要搜索的内容,在它的正下方,有一个带有三个选项的 ViewPager 小部件,其中结果被细分为三个类别(在三个不同的片段上)。当我第一次进入活动时,我运行初始搜索以检索数据并填充三个片段。这非常有效。

SearchActivity.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        mViewModel = ViewModelProviders.of(this).get(SearchViewModel.class);

        /* Init TabMenu */
        TabLayout tabSearchMenu = findViewById(R.id.tabSearchMenu);
        ViewPager vpSearch = findViewById(R.id.vpSearchResult);

        TabSearchPageAdapter tabSearchPageAdapter = new TabSearchPageAdapter(getSupportFragmentManager(), tabSearchMenu.getTabCount());
        vpSearch.setAdapter(tabSearchPageAdapter);
        vpSearch.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabSearchMenu));


        /* Init Search */
        etxtSearch = findViewById(R.id.etxtSearch);
        etxtSearch.setOnEditorActionListener((textView, actionId, keyEvent) -> {
            if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE
                    || keyEvent.getAction() == KeyEvent.ACTION_DOWN || keyEvent.getAction() == KeyEvent.KEYCODE_ENTER) {

                mViewModel.searchText(etxtSearch.getText().toString());
            }

            return false;
        });
    }

SearchViewModel.java

public class SearchViewModel extends ViewModel {
    private MutableLiveData<List<ProductItemModel>> listProducts = new MutableLiveData<>(new ArrayList<>());
    private List<ProductItemModel> mProducts = new ArrayList<>();

    [...]

    public void searchText(String text) {
        // make search... 
        // ...
        // ...

        // Process Json result.
        CompletionHandler completionHandler = (content, error) -> {
            if (content != null && content.length() > 0) {
                Log.d(TAG, content.toString());
                Log.d(TAG, "searchText: found result.");

                listProducts = new MutableLiveData<>(new ArrayList<>());

                mProducts = new ArrayList<>();

                try {
                    JSONArray products = content.getJSONArray("hits");

                    for (int i = 0; i < products.length(); i++) {
                        JSONObject prodObject = products.getJSONObject(i);
                        ProductItemModel prodItem = new ProductItemModel(prodObject);

                        mProducts.add(prodItem);

                        Log.d(TAG, "searchText: " + prodObject.toString());
                    }

                    listProducts.setValue(mProducts);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                Log.d(TAG, "searchText: no hits");
            }
        };
    }

    [...]

    MutableLiveData<List<ProductItemModel>> getProductList() {
        if (listProducts == null)
            return new MutableLiveData<>(new ArrayList<>());

        return listProducts;
    }
}

搜索产品片段

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        InitFragment();
    }

    [...]

    private void InitFragment() {
        mViewModel = ViewModelProviders.of(Objects.requireNonNull(getActivity())).get(SearchViewModel.class);
        mViewModel.SearchProducts();

        final Observer<List<ProductItemModel>> listObserver = result -> {
            Log.d(TAG, "listObserver: observer modified.");
            if (result.size() > 0) {
                InitProductList(result);
            }
        };

        mViewModel.getProductList().observe(getActivity(), listObserver);
    }

已经尝试将片段内的方法InitFragment() 移动到OnActivityCreated,但也没有成功。 我知道一个事实是,观察者没有被触发是行不通的。我已经用断点进行了测试。

正如你们所看到的,当片段初始化时,方法SearchProducts() 被调用,结果完美地发送到 MutableLiveData 并触发观察者。但是每当我运行调用函数searchText() 的搜索,从中检索结果,并更新我的变量的值(到目前为止工作完美),观察者不会被触发。

额外信息:

  • 我尝试在 查看页面。两者都不起作用。

有什么想法吗?

【问题讨论】:

  • 我不能 100% 确定,但我相信 Android 团队的 this video 谈到了您面临的问题。

标签: java android mvvm mutablelivedata


【解决方案1】:

问题是您正在返回 MutableLiveData 的不同实例,但您的片段仅观察它在您的 InitFragment() 方法中获得的第一个实例。

您还将listProducts 设置为MutableLiveData 的多个实例(首先在其声明站点,然后在searchText() 方法中),而不仅仅是更新它所拥有的值。

详细说明,您不需要在 getProductsList() 方法中检查 null,因为在创建视图模型时 listProducts 被初始化为 MutableLiveData 的新实例。

现在,MutableLiveData 的该实例所持有的值可能为 null.. 您应该通过 setValue() 更新该值。对MutableLiveData 的值的任何空检查都可以在您在片段中创建的Observer 中完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多