Обозреватель для MutableLiveData не запускается - PullRequest
0 голосов
/ 26 октября 2019

Я разрабатываю действие, используя MutableLiveData, чтобы мои фрагменты были в курсе последних результатов поиска, но Observer не запускается после обновления списка результатов.

У меня естьна основном задании - 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 Ответ

1 голос
/ 27 октября 2019

Проблема в том, что вы возвращаете разные экземпляры MutableLiveData, но ваш фрагмент наблюдает только первый экземпляр, который он получает в вашем методе InitFragment().

Вы также устанавливаете listProductsдля нескольких экземпляров MutableLiveData (сначала на сайте объявления, а затем в методе searchText()), а не просто для обновления значения, которое оно содержит.

Для уточнения вам не нужна проверка на нулевое значениеметод getProductsList(), поскольку listProducts инициализируется новым экземпляром MutableLiveData при создании модели представления.

Теперь значение этого экземпляра MutableLiveData может быть нулевым ... иэто только то значение, которое вы должны обновлять через setValue(). Любые нулевые проверки значения MutableLiveData могут быть выполнены в Observer, который вы создали в своем фрагменте.

...