繁体   English   中英

LiveData 的变化<list<obj> &gt; 不显示在 recyclerView 中,它在 LiveData 上订阅<list></list></list<obj>

[英]Changes in LiveData<List<Obj>> aren't shown in recyclerView, which is subscrived on the LiveData<List>

当我单击一个项目时, OnItemListener.onItemClick (参见适配器代码)工作,并从 LiveData<List> mListLivedata 中删除相应的(参见 ViewModel )。 问题是这不会更新 recyclerView,尽管事实上有一个观察者订阅了这个 LiveData。 recyclerView 中仍然有 4 个视图,但是如果我单击视图中的最后一个项目(在之前已经单击过任何项目之后),它会崩溃,因为 Livedata<List<>> 中的 object 已经少了一个(导致之前的点击已删除一个对象)。 因此,单击后 LiveData 中的对象数量减少了一个(这是我需要的),但视图中的项目数量保持不变(这是错误,我不明白我的错误在哪里)。 我的错误在哪里,解决方案是什么?

在视图模型中:

public class PersonViewModel extends AndroidViewModel {
    private PersonRepository mRepository;
    private CompositeDisposable composite = new CompositeDisposable();
    private Single<List<Person>> mThreePersons;
    private ArrayList<Person> mList = new ArrayList<>();
    private MutableLiveData<List<Person>> mListLivedata = new MutableLiveData<>();

    public PersonViewModel(@NonNull Application application) {
        super(application);
        mRepository = new PersonRepository(application);
        mThreePersons = mRepository.getThreePersons();
        mThreePersons.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SingleObserver<List<Person>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe(Disposable d): called");
                        composite.add(d);
                    }

                    @Override
                    public void onSuccess(List<Person> people) {
                        Log.d(TAG, "onSuccess: called");
                        mList.addAll(people);
                        mListLivedata.setValue(mList);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: called");
                        Toast.makeText(application, "NO DATA", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    LiveData<List<Person>> getListLivedata() {
        return mListLivedata;
    }

    public void removePerson(Person person) {
        mList.remove(person);
        mListLivedata.setValue(mList);
        Log.d(TAG, "removePerson: called");
    }
}

在活动中:

public class PersonRecyclerActivity extends AppCompatActivity implements PersonRecyclerAdapter.OnItemListener {

    private PersonViewModel personRecyclerViewModel;
    private PersonRecyclerAdapter personRecyclerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recycler_simple_layout);

        RecyclerView personRecyclerView = findViewById(R.id.recycler_view);
        personRecyclerAdapter =
                new MudakRecyclerAdapter(new PersonRecyclerAdapter.PersonRecyclerDiff(), this);
        personRecyclerView.setAdapter(personRecyclerAdapter);
        personRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        personRecyclerViewModel = new ViewModelProvider(this,
                ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()))
                .get(PersonViewModel.class);
        personRecyclerViewModel.getListLivedata().observe(this, personList -> personRecyclerAdapter.submitList(personList));

    }

    @Override
    public void onItemClick(int position) {
        Log.d(TAG, "onItemClick: called for " + personRecyclerAdapter.getPersonAt(position).getName() + ", at the position " + position);
        personRecyclerViewModel.removePerson(personRecyclerAdapter.getPersonAt(position));
    }
}

在适配器中:

public class PersonRecyclerAdapter extends ListAdapter<Person, PersonRecyclerAdapter.PersonRecyclerViewHolder> {

    private OnItemListener mOnItemListener;

    public interface OnItemListener {
        void onItemClick(int position);
    }

    protected PersonRecyclerAdapter(@NonNull DiffUtil.ItemCallback<Person> diffCallback, OnItemListener onItemListener) {
        super(diffCallback);
        mOnItemListener = onItemListener;
    }

    public class PersonRecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private final TextView mrName;
        private final TextView mrStatus;
        OnItemListener onItemListener;

        public PersonRecyclerViewHolder(@NonNull View itemView, OnItemListener onItemListener) {
            super(itemView);
            mrName = itemView.findViewById(R.id.tv_rec_name);
            mrStatus = itemView.findViewById(R.id.tv_rec_status);
            this.onItemListener = onItemListener;

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            onItemListener.onItemClick(getAdapterPosition());
        }
    }

    public Person getPersonAt(int position) {
        return getItem(position);
    }

    @NonNull
    @Override
    public MudakRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycler_simple_item, parent, false);
        return new MudakRecyclerAdapter.MudakRecyclerViewHolder(view, mOnItemListener);
    }

    @Override
    public void onBindViewHolder(@NonNull MudakRecyclerViewHolder holder, int position) {
        Person currentPerson = getItem(position);
        holder.mrName.setText(currentPerson.getName());
        holder.mrStatus.setText(currentPerson.getStatus());
    }

    static class PersonRecyclerDiff extends DiffUtil.ItemCallback<Person> {

        @Override
        public boolean areItemsTheSame(@NonNull Person oldItem, @NonNull Person newItem) {
            return oldItem == newItem;
        }

        @Override
        public boolean areContentsTheSame(@NonNull Person oldItem, @NonNull Person newItem) {
            return oldItem.getName().equals(newItem.getName());
        }
    }
}

如果您向它提交以前使用的相同列表实例,ListAdapter 将不会做任何事情,因为它旨在比较两个不同列表之间的差异。 您应该让removePerson()方法创建一个新的 List 实例,并删除项目并将其传递给 LiveData。

例子:

    public void removePerson(Person person) {
        mList = new ArrayList(mList); // create a new list with same contents
        mList.remove(person); // remove the item from the new list.
        mListLivedata.setValue(mList);
        Log.d(TAG, "removePerson: called");
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM