MutableLiveData 的观察者未被触发

Observer for MutableLiveData not being triggered

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

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

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;
    }
}

SearchProductFragment

    @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(),从中检索结果,并更新我的变量的值(到目前为止工作完美)时,观察者不会被触发。

额外信息:

有什么想法吗?

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

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

具体来说,您不需要在 getProductsList() 方法中进行空值检查,因为在创建视图模型时 listProducts 被初始化为 MutableLiveData 的新实例。

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