首页 > 解决方案 > 尝试在 RecyclerView 中添加新元素时,某些项目重复

问题描述

我创建了一个游戏,用户需要在回收站视图中输入玩家的姓名才能开始游戏。
我的问题是,当我尝试添加新玩家时,每 8 或 9 名玩家输入的名字就会重复。
我尝试在网上搜索原因,但未能找到解决方案,并且真的看不出问题出在哪里。
此外,当我修改重复的名称时,它还更改了回收器视图中该名称的每个实例。
该活动运行良好,当游戏开始时,输入的每个名称都在游戏中,没有重复。

编辑:我添加了 holder.playerName.getText().clear(); 在适配器类的 onBindViewHolder 中,纠正了重复问题,但创建了另一个问题:我现在有没有提示的空 EditTexts(EditText 应该提示玩家编号)

编辑2:将 holder.playerName.getText().clear() 行放在 onBindViewHolder 方法中的 holder.playerName.setHint(players.get(position).getName()) 行下就可以了!谢谢!

这是活动的代码:

 public class PlayersNameScreen extends AppCompatActivity {

  public PlayerMenu playerMenu;                           // A PlayerMenu used to populate the screen when started
  public static PlayerMenu playerMenu1;                   // A static PlayerMenu to store all the players entered on this screen and access it on the next

  private RecyclerView listOfPlayers;                     // The recycler view where the players can see, add and enter other players
  private ListOfPlayersAdapter listOfPlayersAdapter;      // The adapter for the recycler view

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

      initializeScreen();
  }

  /**
   * Sets the contents of the screen
   */
  private void initializeScreen() {

      setContentView(R.layout.activity_players_name_screen);

      listOfPlayers = findViewById(R.id.playerNames);
      // The button used to add a player
      FloatingActionButton addPlayer = findViewById(R.id.addPlayer);

      // Start the game with the new players entered, filtering the menu as well
      // The button to start the game
      Button startGame = findViewById(R.id.Booze);
      startGame.setOnClickListener(view -> {
          playerMenu1 = new PlayerMenu();
          playerMenu1.removeAllPlayers();
          playerMenu1.addAllPlayers(playerMenu.getPlayers());
          playerMenu1.filter();
          goToCardScreen();
      });

      playerMenu = new PlayerMenu();

      // Set the default view of the list
      setListOfPlayersView(playerMenu.getPlayers());

      // Adds a row to the list and a player to the menu, scrolls to the new player entered
      addPlayer.setOnClickListener((View view) -> {
          playerMenu.addPlayer(playerMenu.size());
          listOfPlayersAdapter.notifyItemInserted(playerMenu.size() - 1);
          listOfPlayers.smoothScrollToPosition(playerMenu.size() - 1);
      });

  }

  /**
   * Creates the list of all the players (the view)
   * @param playerz the list of the players
   */
  void setListOfPlayersView(ArrayList<Player> playerz) {
      listOfPlayersAdapter = new ListOfPlayersAdapter(playerz);
      RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());

      listOfPlayers.setLayoutManager(layoutManager);
      listOfPlayers.setItemAnimator(new DefaultItemAnimator());
      listOfPlayers.setAdapter(listOfPlayersAdapter);

  }

  /**
   * Before launching the game, check that the names are correct
   */
  private void goToCardScreen() {
      Set<String> set = new HashSet<>(playerMenu1.getPlayersNames());
      boolean playersNameOK = true;
      boolean playersEntered = true;
      boolean enoughPlayers = true;

      if (set.size() < playerMenu1.getPlayers().size()) {
          // Shows a message that the player entered duplicated names
          playersNameOK = false;
      }

      if (set.isEmpty()) {
          // Shows a message saying they need to enter players
          playersEntered = false;
      }

      if (set.size() == 1) {
          // Shows a message showing that there aren't enough players
          enoughPlayers = false;
      }

      if (playersNameOK && playersEntered && enoughPlayers) {
          createWaiver(); --> eventually leads to next activity
      }
  }
}

这是适配器的代码

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

  private ArrayList<Player> players; // The array to old every player entered

  @NonNull
  @Override
  public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.player_name_row, parent, false);
      return new MyViewHolder(itemView);
  }

  @Override
  public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
      int x = holder.getLayoutPosition();
      // If a real name was entered (names that don't include the string <player>), set the text of the EditText to the name of the player
      if (!players.get(x).getName().contains("Player")){
          holder.playerName.setText(players.get(x).getName());
      }
      else {
          // Keep hinting the player number (aka Player x)
          holder.playerName.setHint(players.get(position).getName());
          holder.playerName.getText().clear();
      }
  }
      @Override
  public int getItemCount() {
      return players.size();
  }

  ListOfPlayersAdapter(ArrayList<Player> players) {
      this.players = players;
  }

  class MyViewHolder extends RecyclerView.ViewHolder {

      private EditText playerName;

      MyViewHolder(View itemView) {
          super(itemView);
          playerName = itemView.findViewById(R.id.playerInput);

          playerName.addTextChangedListener(new TextWatcher() {
              @Override
              public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

              @Override
              public void onTextChanged(CharSequence s, int start, int before, int count) {
                  Player playerBis = new Player(s.toString());
                  players.set(getAdapterPosition(),playerBis);
              }

              @Override
              public void afterTextChanged(Editable s) {
              }
          });
      }
  }
 }

这是播放器菜单的代码:

 class PlayerMenu {
  private ArrayList<Player> players; // List to store every player

  PlayerMenu() {
      // Creating and adding the players to the menu
      players = new ArrayList<>();

      Player player1 = new Player("Player 1");
      Player player2 = new Player("Player 2");
      Player player3 = new Player("Player 3");

      players.add(player1);
      players.add(player2);
      players.add(player3);
  }

  /**
   *
   * @param i The position of the player in the list
   * @return The name of the player
   */
  String getPlayer(int i) {
      return players.get(i).getName();
  }

  /**
   * Method to add a player in the menu
   */
  void addPlayer(int position){
      Player player = new Player("Player" + " " + (players.size() + 1));
      players.add(position, player);
  }

  /**
   * Method to add all players from an ArrayList to the players array list
   * @param playerz The ArrayList we want to get the players from
   */
  void addAllPlayers(ArrayList<Player> playerz) {
      players.addAll(playerz);
  }

  /**
   * Method to remove all players from the list
   */
  void removeAllPlayers() {
      players.clear();
  }

  /**
   * To see the list of players
   * @return the list of all the players
   */
  ArrayList<Player> getPlayers() {
      return players;
  }

  /**
   * Remove from the list of players all those who are nameless (aka Player i)
   */
  void filter() {
      players.removeIf(player -> player.getName().toLowerCase().contains("player")) || player.getName().isEmpty()));
  }

  /**
   * Size of the list
   * @return the size of the list of players
   */
  public int size() {
      return players.size();
  }
 }

当活动屏幕加载以及我们按下“+”按钮时

添加一个名为 Bob 的新玩家,然后向下滚动:Bob 被复制

如果我们添加一个新玩家 John(在顶部)......

...然后按下“+”按钮,John 也被复制了

如果我们一直按“+”按钮,每 6-9 次,输入的名称就会重复

如果我们将其中一个玩家的名字(这里是 John)替换为另一个名字(Karen)......

...然后向上滚动,我们可以看到 John 的一些实例被替换为 karen

标签: javaandroidandroid-recyclerview

解决方案


尝试在您的 bindviewholder 方法中添加以下代码:

     @Override
  public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
      int x = holder.getLayoutPosition();
      // If a real name was entered (names that don't include the string <player>), set the text of the EditText to the name of the player
      if (!players.get(x).getName().contains("Player")){
          holder.playerName.setText(players.get(x).getName());
      }
      else {
          holder.playerName.setText("")
          // Keep hinting the player number (aka Player x)
          holder.playerName.setHint(players.get(position).getName());
      }
  }

holder.playerName.setText("") 您还需要在 else 条件下添加一些值,因为 recyclerview 会回收项目,因此您会得到重复的项目。

希望这可以帮助!


推荐阅读