Обновляйте RecyclerView только тогда, когда происходит изменение в наборе данных - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть набор данных ресторанов и представление переработчика, где они отображаются. В зависимости от нескольких параметров, они должны или не должны быть видны: время открытия, тип пищи и т. Д. c.

Прямо сейчас каждый раз, когда открывается операция с представлением рециркулятора, я запускаю adapter.updateDataset(), которая идет изнутри по всему набору данных создает подмножество, основанное на всех возможных фильтрах, а затем выполняет notifyDataSetChanged().

. Как мне сделать так, чтобы мне нужно было запускать adapter.updateDataset() только тогда, когда изменение действительно происходит? Поскольку эти изменения происходят в контексте, отличном от действия RecyclerView, я не могу просто вызвать функцию там. Какая у меня альтернатива для улучшения производительности?

1 Ответ

1 голос
/ 29 апреля 2020

Вам, вероятно, следует использовать список LiveData объектов из комнаты или сетевого ресурса и связать его с вашей моделью представления. Затем вы будете наблюдать за изменениями в вашем фрагменте / деятельности. Когда изменение произойдет, обновите список данных адаптеров и не забудьте использовать DiffUtil для обновления только измененных элементов. Хороший пример - Google примеры кодов об использовании базы данных комнаты.

В вашем запросе Room Dao оно должно выглядеть следующим образом:

@Query("SELECT * FROM products")
LiveData<List<ProductEntity>> loadProducts();

Тогда в вашей модели представления:

public class ProductListViewModel extends AndroidViewModel {
    // MediatorLiveData can observe other LiveData objects and react on their emissions.
    private final MediatorLiveData<List<ProductEntity>> observableProducts;

    public ProductListViewModel(@NonNull Application application) {
        super(application);
        observableProducts = new MediatorLiveData<>();
        // set by default null, until we get data from the database.
        observableProducts.setValue(null);

        LiveData<List<ProductEntity>> products = ((YourBaseApp) application).getRepository()
                .loadProducts();
        observableProducts.addSource(products, observableProducts::setValue);
    }

    public static class Factory extends ViewModelProvider.NewInstanceFactory {

        @NonNull
        private final Application mApplication;

        public Factory(@NonNull Application application) {
            mApplication = application;
        }

        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {
            //noinspection unchecked
            return (T) new ProductListViewModel(mApplication);
        }
    }

    public LiveData<List<ProductEntity>> getProductList() {
        return observableProducts;
    }

}

Затем в своей деятельности / фрагменте onCreate вы можете вызвать такую ​​примерную функцию и начать наблюдать за вашими данными:

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        // Binding is of type ProductListLayoutBinding
        // you need to declare it on tope of your fragment
        binding = DataBindingUtil.inflate(inflater, R.layout.product_list_layout, container, false); 

        // your other stuff if needed..

        productAdapter = new ProductAdapter(/*...Your parameters if any*/);
        binding.yourRecylerViewId.setAdapter(productAdapter);

        return binding.getRoot();
    }

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

        //...
        //...
        // do your normal stuff above
        ProductListViewModel.Factory factory = new ProductListViewModel.Factory(
                YourBaseApp.getInstance());
        final ProductListViewModel viewModel =
                new ViewModelProvider(this, factory).get(ProductListViewModel.class);
        subscribeUi(viewModel);

    }

    private void subscribeUi(ProductListViewModel viewModel) {
            // Update the list when the data changes
            viewModel.getProductList().observe(this, new Observer<List<ProductEntity>>() {
                @Override
                public void onChanged(@Nullable List<ProductEntity> myProducts) {
                    if (myProducts != null) {
                        if (myProducts.size() == 0) {
                            binding.setIsLoading(true);
                        } else {
                            binding.setIsLoading(false);
                            productAdapter.setProductList(myProducts);
                        }
                    } else {
                        binding.setIsLoading(true);
                    }
                    binding.executePendingBindings();
                }

            });
        }

Наконец, на вашем адаптере:

public void setProductList(final List<? extends Product> inProductList) {
        if (productList == null) {
            productList = inproductList;
            notifyItemRangeInserted(0, productList.size());
        } else {
            DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
                @Override
                public int getOldListSize() {
                    return productList.size();
                }

                @Override
                public int getNewListSize() {
                    return inproductList.size();
                }

                @Override
                public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                    return productList.get(oldItemPosition).getId() == inproductList.get(newItemPosition).getId();
                }

                @Override
                public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
                    productList newProduct = inproductList.get(newItemPosition);
                    productList oldProduct = productList.get(oldItemPosition);
                    return newProduct.getId() == oldProduct.getId()
                            && Objects.equals(newProduct.getDefinition(), oldProduct.getDefinition())
                            //... compare other properties
                            //...
                            ;
                }
            });
            productList = inproductList;
            result.dispatchUpdatesTo(this);
        }

    }

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...