如何使用列表适配器在回收器视图中修改列表?

时间:2019-12-22 05:28:29

标签: android kotlin android-recyclerview listadapter

因此,当我从互联网上获取数据时(例如,当我们不断滚动并进行分页时,就像Youtube),我试图在回收器视图的最后一个索引中添加加载项。像这样

enter image description here

现在我的回收站视图扩展了ListAdapter,不再使用RecyclerView.Adapter<RecyclerView.ViewHolder>

如果使用RecyclerView.Adapter<RecyclerView.ViewHolder>(旧方式),我将为适配器编写如下代码:

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

    private static final int ITEM = 0;
    private static final int LOADING = 1;
    private static final String BASE_URL_IMG = "https://image.tmdb.org/t/p/w150";

    private List<Movie> movieResults;
    private Context context;

    private boolean isLoadingAdded = false;

    public PaginationAdapter(Context context) {
        this.context = context;
        movieResults = new ArrayList<>();
    }

    public List<Movie> getMovies() {
        return movieResults;
    }

    public void setMovies(List<Movie> movieResults) {
        this.movieResults = movieResults;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case ITEM:
                viewHolder = getViewHolder(parent, inflater);
                break;
            case LOADING:
                View v2 = inflater.inflate(R.layout.item_progress, parent, false);
                viewHolder = new LoadingVH(v2);
                break;
        }
        return viewHolder;
    }

    @NonNull
    private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
        RecyclerView.ViewHolder viewHolder;
        View v1 = inflater.inflate(R.layout.item_list, parent, false);
        viewHolder = new MovieVH(v1);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        Movie result = movieResults.get(position); // Movie

        switch (getItemViewType(position)) {
            case ITEM:

              // some code here

                break;

            case LOADING:
              //  Do nothing
                break;
        }

    }

    @Override
    public int getItemCount() {
        return movieResults == null ? 0 : movieResults.size();
    }

    @Override
    public int getItemViewType(int position) {
        return (position == movieResults.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
    }





    public void addLoadingFooter() {
        isLoadingAdded = true;
        movieResults.add(new Moview());
        notifyItemInserted(movieResults.size() - 1);
    }

    public void removeLoadingFooter() {
        isLoadingAdded = false;

        int position = movieResults.size() - 1;
        Movie result = getItem(position);

        if (result != null) {
            movieResults.remove(position);
            notifyItemRemoved(position);
        }
    }



}

但是现在我正在尝试将ListAdapter用于我的Recycler View。这是我的代码,如果我的回收站视图使用ListAdapter

class GeneralEventRecyclerViewAdapter(val mContext: Context): ListAdapter<Event, RecyclerView.ViewHolder>(DIFF_CALLBACK) {

    lateinit var mOnEventKMListener : OnEventKMListener

    private val ITEM = 0
    private val LOADING = 1
    private var isLoadingAdded = false


    fun setOnItemClickListener(listener: OnEventKMListener) {
        mOnEventKMListener = listener
    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {


        if (viewType == ITEM) {

            val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_general_event, parent, false)
            return GeneralEventViewHolder(itemView, mOnEventKMListener)

        } else  {

            val loadingView = LayoutInflater.from(parent.context).inflate(R.layout.item_progress, parent, false)
            return LoadingViewHolder(loadingView)

        }



    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        if (getItemViewType(position) == ITEM) {

            // some code here

        }





    }

    override fun getItemViewType(position: Int): Int {
        if (position == currentList.size - 1 && isLoadingAdded) {
            return LOADING
        } else {
            return ITEM
        }
    }

    fun addLoadingFooter() {
        isLoadingAdded = true
        currentList.add(Event())
        notifyItemInserted(currentList.size - 1)
    }

    fun removeLoadingFooter() {
        isLoadingAdded = false
        val position: Int = currentList.size - 1
        val result: Event? = getItem(position)
        if (result != null) {
            currentList.removeAt(position)
            notifyItemRemoved(position)
        }
    }


    companion object {

        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Event>() {
            override fun areItemsTheSame(oldItem: Event, newItem: Event): Boolean {
                return oldItem.eventID == newItem.eventID
            }

            override fun areContentsTheSame(oldItem: Event, newItem: Event): Boolean {
                return oldItem == newItem
            }


        }
    }


}

这是我的问题.....

在添加和删除回收站中的加载项时,我试图模仿这两种方法(使用RecyclerView.Adapter):

        public void addLoadingFooter() {
            isLoadingAdded = true;
            movieResults.add(new Moview());
            notifyItemInserted(movieResults.size() - 1);
        }

        public void removeLoadingFooter() {
            isLoadingAdded = false;

            int position = movieResults.size() - 1;
            Movie result = getItem(position);

            if (result != null) {
                movieResults.remove(position);
                notifyItemRemoved(position);
            }
        }

我假设如果使用ListAdapter

,则上述两种方法与下面的两种方法相同。
    fun addLoadingFooter() {
        isLoadingAdded = true
        currentList.add(Event())
        notifyItemInserted(currentList.size - 1)
    }

    fun removeLoadingFooter() {
        isLoadingAdded = false
        val position: Int = currentList.size - 1
        val result: Event? = getItem(position)
        if (result != null) {
            currentList.removeAt(position)
            notifyItemRemoved(position)
        }
    }  

但是当我运行该应用程序时,我会崩溃

    java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)

currentList.add(Event())

如果使用ListAdapter,似乎无法在列表中添加新项目。那么如何使用列表适配器在回收站视图中修改列表?

如果使用ListAdapter,我不知道如何访问现有列表,看来currentList不能被修改

java或kotlin没问题

2 个答案:

答案 0 :(得分:0)

最终使用

找到解决方案
override fun getItemViewType(position: Int): Int {
        if ( position == currentList.lastIndex && isLoadingAdded) {
            return LOADING
        } else {
            return ITEM
        }
    }

    fun addLoadingFooter(currentList: ArrayList<Event>) {
        isLoadingAdded = true
        currentList.add(Event())
        submitList(currentList)
        notifyItemInserted(currentList.lastIndex)


    }

    fun removeLoadingFooter(currentList: ArrayList<Event>) {
        isLoadingAdded = false

        val result = currentList[currentList.lastIndex]
        currentList.remove(result)
        submitList(currentList)
        notifyItemRemoved(currentList.size)

    }

答案 1 :(得分:0)

聚会迟到,但您当前的回答并未充分利用ListAdapter。您应该改用 ListAdapter.submitList,它可以完成大部分 notifyItemXXXXXX 工作。

val newList = ArrayList(listAdapter.currentList)
newList.add(Event()) // or to remove / update / ... etc.
listAdapter.submitList(newList)

还有一件重要的事情要知道:submitList 必须使用来自原始对象的新对象(列表)

val objList = mutableListOf(myObjects)
listAdapter.submitList(objList)

objList.add(newObject)
listAdapter.submitList(objList) // will NOT do updates.
listAdapter.submitList(ArrayList(objList)) // will do updates.

它在另一个 Stack Overflow question 中被提及。