RecyclerView onClickListener Настройка производительности

1

поэтому я впервые попытался реализовать onClickListener для моего RecyclerView, и мне было интересно, стоит ли делать то, что я сделал. В моем приложении у меня разные представления Recycler, и мне не нужны одновременно onClickListeners и onLongClickListeners в большинстве из них, поэтому я хотел сделать это так, чтобы мне не пришлось реализовывать их оба в моем .setOnItemClickListener. Я в основном проверяю, какой onClickListener настроен в режиме enum, а затем в соответствии с этим я устанавливаю своих слушателей в onCreateViewHolder. Есть ли смысл делать это? Или я должен просто реализовать оба слушателя и не делать то, что я делал в своем коде?

public class FreindRecyclerViewAdapter extends RecyclerView.Adapter<FreindRecyclerViewAdapter.MyViewHolder> {

    private ClickListener clickListener ;
    private LongClickListener longClickListener;

    private Context context;
    private List<String> friends;
    private ListenerMode mode;

    public enum ListenerMode {NullMode, ShortClick, LongClick}

    public interface ClickListener {

        void onItemClick(int position, View v);

    }

    public interface LongClickListener {

        void onItemLongClick(int position, View v);

    }

    public void setOnItemClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
        mode = ListenerMode.ShortClick;
    }

    public void setOnLongItemClickListener(LongClickListener longItemClickListener) {
        this.longClickListener = longItemClickListener;
        mode = ListenerMode.LongClick;
    }

    public FreindRecyclerViewAdapter (Context context, List<String> friends) {

        this.context = context;
        this.friends = friends;
        this.mode = ListenerMode.NullMode;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view;
        view = LayoutInflater.from(context).inflate(R.layout.friend_item, viewGroup, false);
        final MyViewHolder myViewHolder = new MyViewHolder(view);

        if(mode == ListenerMode.ShortClick) {
            myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    clickListener.onItemClick(myViewHolder.getAdapterPosition(), view);
                }
            });
        } else if (mode == ListenerMode.LongClick) {

            myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {

                    longClickListener.onItemLongClick(myViewHolder.getAdapterPosition(), view);

                    return true;
                }
            });

        }



        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {

        myViewHolder.friendName.setText(friends.get(position));


    }

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

    public static class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView friendName;

        public MyViewHolder(View itemView) {
            super(itemView);

            friendName= itemView.findViewById(R.id.friendName_ID);

        }

    }

}

РЕДАКТИРОВАТЬ: Теперь, когда я думаю об этом, я даже не знаю, почему это работает, например, когда я настраиваю свой RecyclerView, адаптер и все в своем коде ниже, я сначала говорю адаптеру о списке, который я хочу показать на экран в нем конструктор recyclerViewAdapter = new FreindRecyclerViewAdapter(this, friends); , так что это когда onCreateViewHolder вызывается для моих представлений. Итак, теперь, когда все создано (ViewHolders), я вызываю функцию для настройки OnClickListener, который в моем коде добавляет разных слушателей в соответствии с установленным mode, и эти слушатели добавляются в onCreateViewHolder, который уже был вызван, так почему RecyclerViewAdapter (и как он узнает) снова вызывает onCreateViewHolder для добавления слушателей?

friends = new ArrayList<>();

        friends.add("Josh");
        friends.add("Mike");
        friends.add("Ashley");
        friends.add("Jess");


        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView = findViewById(R.id.recyclerViewFriend_ID);
        recyclerViewAdapter = new FreindRecyclerViewAdapter(this, friends);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(recyclerViewAdapter);

        DividerItemDecoration itemDecor = new DividerItemDecoration(this, linearLayoutManager.getOrientation());
        recyclerView.addItemDecoration(itemDecor);



        recyclerViewAdapter.setOnLongItemClickListener(new FreindRecyclerViewAdapter.LongClickListener() {
            @Override
            public void onItemLongClick(int position, View v) {
                Toast.makeText(FriendActivity.this, "Long Click. Position:" + Integer.toString(position), Toast.LENGTH_SHORT).show();
            }
        });
Теги:
android-recyclerview
onclick
onclicklistener

1 ответ

1

Это нормально, но может быть и лучше.

1) Вы создаете прослушиватель кликов и слушатель длинных кликов для каждой позиции

Вам не нужно создавать слушателя для каждой позиции, как вы делаете здесь:

myViewHolder.itemView.setOnClickListener(new View.OnClickListener() ...

and

myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() ...

Поскольку они выполняют очень похожее действие, вы можете создать только один щелчок и прослушивание longclick и делиться со всеми представлениями. Для этого переместите itemView.setOnClickListener() и itemView.setOnLongClickListener() в класс ViewHolder.

Вам также необходимо сохранить позицию в ViewHolder. Таким образом, они смогут хранить свою позицию.

2) Вам не нужно создавать перечисление

Вам не нужно создавать перечисление для проверки текущего режима (щелчок или длительный щелчок). Вместо этого вы можете просто проверить, являются ли переменные нулевыми, например.

В конце концов, вы можете получить такой код:

public class FreindRecyclerViewAdapter extends RecyclerView.Adapter<FreindRecyclerViewAdapter.MyViewHolder> {

    private ClickListener clickListener ;
    private LongClickListener longClickListener;

    private Context context;
    private List<String> friends;

    public interface ClickListener {
        void onItemClick(int position, View v);
    }

    public interface LongClickListener {
        void onItemLongClick(int position, View v);
    }

    public void setOnItemClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }

    public void setOnLongItemClickListener(LongClickListener longItemClickListener) {
        this.longClickListener = longItemClickListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view;
        view = LayoutInflater.from(context).inflate(R.layout.friend_item, viewGroup, false);
        return new MyViewHolder(view, i, clickListener, longClickListener);;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {
        myViewHolder.friendName.setText(friends.get(position));
    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder implements
            View.OnLongClickListener, View.OnClickListener {

        private TextView friendName;
        private int position;

        public MyViewHolder(View itemView, int position) {
            super(itemView);
            friendName = itemView.findViewById(R.id.friendName_ID);
            this.position = position;
            if (clickListener != null) {
                itemView.setOnClickListener(this);
            }
            if (longClickListener != null) {
                itemView.setOnLongClickListener(this);
            }
        }

        @Override
        public void onClick(View view) {
            if (clickListener != null) {
                clickListener.onItemClick(position, view);
            }
        }

        @Override
        public boolean onLongClick(View view) {
            if (longClickListener != null) {
                longClickListener.onItemLongClick(position, view);
                return true;
            } else {
                return false;
            }
        }
    }
}
  • Обратите внимание, что теперь каждый держатель представления знает свою собственную позицию
  • Держатель представления реализует обычные View.OnClickListener и View.LongClickListener. Таким образом, вам не нужно создавать экземпляр нового слушателя для каждой позиции.
  • Если вы хотите включить щелчок, вызовите FreindRecyclerViewAdapter.setOnItemClickListener(object);
  • Если вы хотите включить длинный щелчок, вызовите FreindRecyclerViewAdapter.setOnLongItemClickListener(object);
  • Если вы хотите отключить любой из них, не вызывайте методы, описанные выше, или просто вызывайте их, передавая null качестве параметра. Если вы проверите код в MyViewHolder, вы увидите, что любое действие выполняется, когда эти слушатели являются нулевыми

Надеюсь, я мог бы помочь и поделиться больше способов достичь того, что вы хотите!

  • 0
    Разве переменная i return new MyViewHolder(view, i) самом деле не позиция, согласно документации Google, i в onCreateViewHolder это ViewType, только в onBindViewHolder i это позиция, которую я переименовал в своем коде. И я немного запутался из-за того, что не создавал много onClickListener, вы сказали, что реализация onClickListener для ViewHolder позволяет избежать создания нескольких слушателей, но не return new MyViewHolder(view, i) ли эта строка return new MyViewHolder(view, i) создает новый ViewHolder для каждого представления, которое в основном создает новый onClickListener (сам) с ним?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню