MutableLiveData的观察者未触发

时间:2019-10-26 20:31:52

标签: java android mvvm mutablelivedata

我正在使用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;
    }
}

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()的搜索,从中检索结果并更新变量的值(到现在为止都可以正常工作)时,观察器就不会触发。

其他信息:

  • 我尝试过在片段上启用和关闭搜索 ViewPager。两者都不起作用。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

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

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

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

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