【问题标题】:removing RecyclerView items删除 RecyclerView 项目
【发布时间】:2017-08-25 04:21:02
【问题描述】:

我有一个 RecyclerView,它在每个特定时期添加项目。添加对象时,如果列表项超过(比如说)500 个,则将删除第一个项目并添加新项目。

如果 RecyclerView 不能再向下滚动!recyclerView.canScrollVertically(1);,那么在添加新项目后,RecyclerView 将smoothScroolToPosition() 到最后一个位置。

问题出在哪里? 好吧,如果ReyclerView在移除旧物品时在中间(不是底部,不是顶部),它会突然向上跳一些位置。我希望 RecyclerView 在移除顶部的项目时不跳转位置并保持原位

我尝试使用layoutManager.setStackFromEnd(true);,但没有成功

有什么建议吗?

一些代码(不相关的代码被删除)。当 RecyclerView 从中间显示列表项并按 VOLUME_UP 时,我的问题可以重现:

public class ActivityMain extends ActionBarActivity {

    public static final int MAX_LOG_ITEMS = 500;

    private RecyclerView mRecyclerView;
    private AdapterLog mRecyclerAdapter;
    private boolean mAutoScroll = true;

    private DataReceiver mDataReceiver;
    private Handler mLogHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            switch (msg.what){
                case DataReceiver.CAT_LOGS:
                    List<Log> catLogs = (List<Log>) msg.obj;
                    updateLogs(catLogs);
                    break;
                case DataReceiver .CLEAR_LOGS:
                    if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
                        mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - MAX_LOG_ITEMS);
                    break;
                case Logcat.REMOVE_LOGS:
                    mRecyclerAdapter.clear();
            }
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setStackFromEnd(true);
        mRecyclerAdapter = new AdapterLog();

        mRecyclerView = (RecyclerView) findViewById(R.id.activity_main_recyclerview);
        mRecyclerView.setHasFixedSize(true);        
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(mRecyclerAdapter);
        mRecyclerView.setOnScrollListener(new UIUtils.ScrollManager(toolbarContainer != null ?
                toolbarContainer : toolbar){
                @Override public void onScrolled(RecyclerView r, int dx, int dy) {
                    super.onScrolled(r, dx, dy);
                    mAutoScroll = !r.canScrollVertically(1);
                    }
                });
    }



    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch(keyCode){
            case KeyEvent.KEYCODE_VOLUME_UP:
//                mAutoScroll = false;
//                mRecyclerView.scrollToPosition(0);
//                if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
                    mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - 50);

                return true;
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                mAutoScroll = true;
                mRecyclerView.scrollToPosition(mRecyclerAdapter.getItemCount() -1);
                return true;
        }
        return false;
    }

    private void updateLogs(final List<Log> logList) {
        final boolean scroll = mAutoScroll;
        mRecyclerAdapter.addAll(logList);
        if (scroll) mRecyclerView.smoothScrollToPosition(mRecyclerAdapter.getItemCount() - 1);
    }

}

RecyclerAdapter:

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

    private final List<Log> mLogList;

    public AdapterLog() {
        this.mLogList = new ArrayList<Log>();
    }

    @Override
    public AdapterLog.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.listitem_log, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(getItem(position).getMessage());
        holder.mTextView.setTextColor(getItem(position).getLevel().getColor());
    }

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

    public Log getItem(int position) {
        return mLogList.get(position);
    }

    public void addAll(List<Log> logList) {
        mLogList.addAll(logList);
        notifyDataSetChanged();
    }

    public void removeFirstItems(int count) {
        for (int i=0; i<count; i++) mLogList.remove(0);
        notifyDataSetChanged();
    }

    public void clear() {
        mLogList.clear();
        notifyDataSetChanged();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.listitem_log_textview);
        }
    }
}

【问题讨论】:

  • 你在打电话给notififyDataSetChanged吗?
  • 是的,在调用 add 或 remove 时来自适配器。我更新代码
  • notifyDataSetChanged(); 上的removeFirstItems 更改为notifyItemRangeRemoved(0,count) 以获得更好的性能
  • @PedroOliveira 您的解决方案使其工作,现在 RecyclerView 不会突然跳跃...将其发布为答案,以便我可以接受并增加您的代表 :)

标签: android listitem android-recyclerview


【解决方案1】:

你告诉你的观点你改变了你的整个适配器。对于添加、删除和重新排序,请考虑使用以下方法:

notifyItemRangeChanged
notifyItemRangeInserted
notifyItemRangeRemoved
notifyItemMoved
notifyItemInserted
notifyItemChanged
notifyItemRemoved

因此,在您的情况下,您将删除顶部的 count 项目,因此:

notifyItemRangeRemoved(0,count)

应该做的工作。

【讨论】:

    【解决方案2】:
    public class viewHolderFav extends RecyclerView.ViewHolder {
        private ImageView image;
        private TextView name;
    
    
    
    
    public viewHolderFav( View itemView ) {
            super( itemView );
            image = ( ImageView ) itemView.findViewById( R.id.txt_image_fav );
            name = ( TextView ) itemView.findViewById( R.id.txt_name_fav );
    
    
    
            edite.setOnClickListener( new View.OnClickListener( ) {
                @Override
                public void onClick( View v ) {
    
                remove( posts.get( getLayoutPosition() ) );
    
    
                }
            } );
    
    
    
        }
    
    
    
    public void remove(DataBoj item) {
        int position = posts.indexOf(item);
        posts.remove(position);
        notifyItemRemoved(position);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-25
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 2015-08-30
      • 2019-09-22
      • 1970-01-01
      相关资源
      最近更新 更多