Как использовать BindingAdapter для обновления RecyclerView?

Я использую MVVM и DataBindg в своем приложении. У меня проблема в том, что когда данные будут получены с сервера, мой адаптер recyclerView будет добавлять новые элементы без остановки.

Например, если я получил 15 предметов, recyclerview добавит 15, затем 30, затем 60, ...

Это мой фрагмент ViewModel:

public class ArticlesViewModel extends BaseObservable {

  // These observable fields will update Views automatically
  public final ObservableList<Article> items = new ObservableArrayList<>();

  public final ObservableBoolean dataLoading = new ObservableBoolean(false);


  private final AppRepository mTasksRepository;

  private final ObservableBoolean mIsDataLoadingError = new ObservableBoolean(false);

  private Context mContext; // To avoid leaks, this must be an Application Context.

  private static final String TAG = "ArticlesViewModel";
  public ArticlesViewModel(
    AppRepository repository,
    Context context) {
    mContext = context.getApplicationContext(); // Force use of Application Context.
    mTasksRepository = repository;
  }


  public void start() {
    loadTasks(false);
  }

  @Bindable
  public boolean isEmpty() {
    return items.isEmpty();
  }

  public void loadTasks(boolean forceUpdate) {
    loadTasks(forceUpdate, true);
  }


  public String getSnackbarText() {
    return snackbarText.get();
  }

  private void loadTasks(boolean forceUpdate, final boolean showLoadingUI) {

    if (showLoadingUI) {
      dataLoading.set(true);
    }

    mTasksRepository.getArticleList(0, new AppDataSource.LoadDefaultListCallback() {
      @Override
      public void onTasksLoaded(List list) {

        Log.d(TAG, "onTasksLoaded: ");

        if (showLoadingUI) {
          dataLoading.set(false);
        }
        mIsDataLoadingError.set(false);

        items.clear();
        items.addAll(list);
        notifyPropertyChanged(BR.empty); // It's a @Bindable so update manually
      }

      @Override
      public void onDataNotAvailable() {
        mIsDataLoadingError.set(true);
      }
    });
  }

}

Я проверил эту часть своего кода, и она будет выполнена один раз. А это XML этого фрагмента:

<?xml version = "1.0" encoding = "utf-8"?>
<layout xmlns:android = "http://schemas.android.com/apk/res/android"
        xmlns:app = "http://schemas.android.com/apk/res-auto">

  <data>

    <import type = "android.view.View"/>

    <variable
      name = "view"
      type = "project.article.ArticleFragment"/>

    <variable
      name = "viewmodel"
      type = "project.article.ArticlesViewModel"/>

  </data>


  <android.support.constraint.ConstraintLayout
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:orientation = "vertical">


    <android.support.v7.widget.RecyclerView
      android:id = "@+id/article_recycler_article"
      android:layout_width = "match_parent"
      android:layout_height = "0dp"
      android:layout_weight = "1"
      app:items = "@{viewmodel.items}"
      app:layout_constraintBottom_toBottomOf = "parent"
      app:layout_constraintLeft_toLeftOf = "parent"
      app:layout_constraintRight_toRightOf = "parent"
      app:layout_constraintTop_toBottomOf = "@+id/article_recycler_cat"/>

  </android.support.constraint.ConstraintLayout>

</layout>

Я также использую BindingAdapter для установки полученных данных в свой recyclerView. Это мой класс BindingAdapter:

public class TasksListBindings {

  private static final String TAG = "TasksListBindings";

  @SuppressWarnings("unchecked")
  @BindingAdapter("app:items")
  public static void setItems(RecyclerView recyclerView, List<Article> items) {

    RecyclerArticleAdapter adapter = (RecyclerArticleAdapter) recyclerView.getAdapter();
    Log.d(TAG, "setItems: " + items.size());
      adapter.swapData(items); //this part of code will call more than 20 times that makes application to crash.
  }
}

И, наконец, это мой адаптер recyclerView для установки в него полученных данных:

public class RecyclerArticleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

  private List<Article> mainList;

  private static final String TAG = "RecyclerArticleAdapter";

  public RecyclerArticleAdapter(List<Article> mainList) {
    this.mainList = mainList;
    Log.d(TAG, "RecyclerArticleAdapter: " + mainList.size());
  }


  public void swapData(List<Article> dataList) {

    if (mainList.size() == 0) {

      mainList = dataList;

    } else {

      mainList.addAll(dataList);
    }

    notifyDataSetChanged();
  }

  public List<Article> getList() {
    return mainList;
  }

  public class ItemViewHolder extends RecyclerView.ViewHolder {

    private Context context;
    private ArticleItemBinding articleItemBinding;

    public ItemViewHolder(
      ArticleItemBinding binding) {
      super(binding.getRoot());
      context = itemView.getContext();
      articleItemBinding = binding;
    }
  }

  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    ArticleItemBinding binding = DataBindingUtil.inflate(
      LayoutInflater.from(parent.getContext()),
      R.layout.article_item, parent, false);

    ItemViewHolder holder = new ItemViewHolder(binding);
    return holder;
  }


  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder rawHolder, final int position) {
    final ItemViewHolder holder = (ItemViewHolder) rawHolder;

    Article article = mainList.get(position);
    holder.articleItemBinding.setArticle(article);
  }

  @Override
  public int getItemCount() {
    return mainList.size();
  }

}

Я не могу понять, в чем проблема. Я очень ценю твои ответы.

Спасибо.

3
0
1 143
1

Ответы 1

Кажется, что к recyclerview не прикреплен менеджер по расположению. Вы должны установить менеджер компоновки recyclerview.

андроид: ориентация = "вертикальный" app: layoutManager = "android.support.v7.widget.LinearLayoutManager"

Нет, в recyclerView есть LayoutManager. Я установил это в своем фрагменте так: private void setupListAdapter() { RecyclerView recyclerArticle = mArticleFragBinding.articleRecyclerArticle; recyclerArticle.setLayoutManager(new LinearLayoutManager(getActivity())); mListAdapter = new RecyclerArticleAdapter(new ArrayList<Article>(0)); recyclerArticle.setAdapter(mListAdapter); }

Ehsan 22.07.2018 11:06

Другие вопросы по теме