为什么RecyclerView项目出现在错误的位置?

时间:2017-10-31 08:40:51

标签: android android-recyclerview

我在我的应用程序中使用RecyclerView为用户创建一个论坛。

但是项目的位置有问题!有时项目会显示在错误的位置!有时项目播种两次,有些项目没有显示! 我在recyclerView中有不同的视图,因为我在其中使用了multiView。

这是我正在使用的recyclerView适配器:

using (_session.Use(1, 3)) // 3 is the Id of User1, who has no permissions
{
    // Execute operator
    switch (input.Operator.Type)
    {
        case "api":
            executeApiResult = await ExecuteApi(input);
            break;
        case "procedure":
            executeApiResult = await ExecuteProcedure(input);
            break;
        default:
            return new ExecuteOperatorOutput
            {
                Result = new ExecuteOperatorResult { Status = false, Message = $"Wrong operator type: {input.Operator.Type}" },
                WorkflowStatus = false
            };
    }
}

这是recyclerView的图像:

enter image description here

更新

我在public class chatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final ArrayList<ChatModel> chatArray = new ArrayList<>(); private Context mContext; FragmentForum fragmentForum; public chatAdapter(ArrayList<ChatModel> chatArray, Context mContext, FragmentForum fragmentForum) { this.chatArray.addAll(chatArray); this.mContext = mContext; this.fragmentForum = fragmentForum; } public static class ViewHolderNoFile extends RecyclerView.ViewHolder { ImageView reply; TextView qText; TextView aText; TextView aUserName; TextView qUserName; LinearLayout layoutAnswer; public ViewHolderNoFile(View v) { super(v); reply = (ImageView) v.findViewById(R.id.imgReplay); qText = (TextView) v.findViewById(R.id.txt_question); aText = (TextView) v.findViewById(R.id.txt_answer); aUserName = (TextView) v.findViewById(R.id.txt_a_user_name); qUserName = (TextView) v.findViewById(R.id.txt_q_user_name); layoutAnswer = (LinearLayout) v.findViewById(R.id.answer_box_item); } } public static class ViewHolderQFile extends RecyclerView.ViewHolder { ImageView qImage; ImageView reply; TextView qText; TextView aText; TextView aUserName; TextView qUserName; LinearLayout layoutAnswer; public ViewHolderQFile(View v) { super(v); qImage = (ImageView) v.findViewById(R.id.img_question); reply = (ImageView) v.findViewById(R.id.imgReplay); qText = (TextView) v.findViewById(R.id.txt_question); aText = (TextView) v.findViewById(R.id.txt_answer); qUserName = (TextView) v.findViewById(R.id.txt_q_user_name); aUserName = (TextView) v.findViewById(R.id.txt_a_user_name); layoutAnswer = (LinearLayout) v.findViewById(R.id.answer_box_item); } } public static class ViewHolderAFile extends RecyclerView.ViewHolder { ImageView aImage; ImageView reply; TextView qText; TextView aText; TextView aUserName; TextView qUserName; LinearLayout layoutAnswer; public ViewHolderAFile(View v) { super(v); aImage = (ImageView) v.findViewById(R.id.img_answer); reply = (ImageView) v.findViewById(R.id.imgReplay); qText = (TextView) v.findViewById(R.id.txt_question); aText = (TextView) v.findViewById(R.id.txt_answer); aUserName = (TextView) v.findViewById(R.id.txt_a_user_name); qUserName = (TextView) v.findViewById(R.id.txt_q_user_name); layoutAnswer = (LinearLayout) v.findViewById(R.id.answer_box_item); } } public static class ViewHolderQAFile extends RecyclerView.ViewHolder { ImageView qImage; ImageView aImage; ImageView reply; TextView qText; TextView aText; TextView aUserName; TextView qUserName; LinearLayout layoutAnswer; public ViewHolderQAFile(View v) { super(v); qImage = (ImageView) v.findViewById(R.id.img_question); aImage = (ImageView) v.findViewById(R.id.img_answer); reply = (ImageView) v.findViewById(R.id.imgReplay); qText = (TextView) v.findViewById(R.id.txt_question); aText = (TextView) v.findViewById(R.id.txt_answer); aUserName = (TextView) v.findViewById(R.id.txt_a_user_name); qUserName = (TextView) v.findViewById(R.id.txt_q_user_name); layoutAnswer = (LinearLayout) v.findViewById(R.id.answer_box_item); } } public static class ViewHolderUnsent extends RecyclerView.ViewHolder { TextView unSentQuestion; TextView unSentReplyText; ImageView unSentImage; public ViewHolderUnsent(View v) { super(v); unSentQuestion = (TextView) v.findViewById(R.id.txt_unSend_question); unSentReplyText = (TextView) v.findViewById(R.id.txt_reply_unSend_question); unSentImage = (ImageView) v.findViewById(R.id.img_unSend_question); } } public static class ViewHolderReply extends RecyclerView.ViewHolder { TextView replyPastQ; TextView replyPastA; TextView replyCurrentQ; TextView replyCurrentA; LinearLayout layoutAnswer; ImageView imgReplay; public ViewHolderReply(View v) { super(v); replyPastQ = (TextView) v.findViewById(R.id.reply_txt_past_question); replyPastA = (TextView) v.findViewById(R.id.right_reply_txt_past_answer); replyCurrentQ = (TextView) v.findViewById(R.id.reply_txt_current_question); replyCurrentA = (TextView) v.findViewById(R.id.right_reply_txt_current_answer); layoutAnswer = (LinearLayout) v.findViewById(R.id.answer_box_item); imgReplay = (ImageView) v.findViewById(R.id.imgReplay); } } @Override public int getItemViewType(int position) { /* *****************************Handling Inline Parents************** * * * 1 for item_message_no_file * 2 for item_message_question_has_file * 3 for item_message_answer_has_file * 4 for item_message_q_a_has_file * */ if (chatArray.get(position).isNoFile()) { return 1; } else if (chatArray.get(position).isMineUnSend()) { //UnSend return 2; } else if (chatArray.get(position).isReply()) { //Has Reply return 3; } else if (chatArray.get(position).isqHasFile()) { //At this position q has file return 4; } else if (chatArray.get(position).isaHasFile()) { //At this position a has file return 5; } else { //At this position q and a have file return 6; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // Create a new View //No File final View item_message_no_file = LayoutInflater.from(mContext).inflate(R.layout.item_message_no_file, parent, false); //Not Send final View item_message_un_send = LayoutInflater.from(mContext).inflate(R.layout.item_message_un_sent, parent, false); //Reply final View item_message_reply = LayoutInflater.from(mContext).inflate(R.layout.item_message_reply, parent, false); //Question has File final View item_message_q_has_file = LayoutInflater.from(mContext).inflate(R.layout.item_message_question_has_file, parent, false); //Answers has File final View item_message_a_has_file = LayoutInflater.from(mContext).inflate(R.layout.item_message_answer_has_file, parent, false); //Question and Answer have file final View item_message_q_a_has_file = LayoutInflater.from(mContext).inflate(R.layout.item_message_q_a_has_file, parent, false); if (viewType == 1) { return new ViewHolderNoFile(item_message_no_file); //For item_message_no_file } else if (viewType == 2) { return new ViewHolderUnsent(item_message_un_send); //For item_message_un_send } else if (viewType == 3) { return new ViewHolderReply(item_message_reply); //For item_message_reply } else if (viewType == 4) { return new ViewHolderQFile(item_message_q_has_file); //For item_message_q_has_file } else if (viewType == 5) { return new ViewHolderAFile(item_message_a_has_file); //For item_message_a_has_file } else { return new ViewHolderQAFile(item_message_q_a_has_file); //For item_message_q_a_has_file } } /** * add sent message to adapter * * @ArrayList<ChatModel> chatArray of messages */ public void addItem(ChatModel newMessage) { Log.i("CHAT_ADAPTER", "CHAT ARRAY SIZE: " + this.chatArray.size()); this.chatArray.add(newMessage); //notifyItemInserted(this.chatArray.size()-1); notifyDataSetChanged(); } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { String question; CourseForumModel cfm = chatArray.get(holder.getAdapterPosition()).getCourseForumModel(); switch (holder.getItemViewType()) { case 1: //For item_message_no_file ViewHolderNoFile vhNoFile = (ViewHolderNoFile) holder; //Set userName of Answer setUserName(vhNoFile.aUserName, cfm.getCourseForumAUserName()); //Set userName of Question setUserName(vhNoFile.qUserName, cfm.getCourseForumQUserName()); //Set Question Text setMessage(vhNoFile.qText, cfm.getCourseForumQuestion()); //Set Answer Text setMessage(vhNoFile.aText, cfm.getCourseForumAnswer()); vhNoFile.reply.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentForum.onEvent(fragmentForum, chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumId()); } }); // check if answer text is empty get answer layout gone if (vhNoFile.aText.getText() == "") { vhNoFile.layoutAnswer.setVisibility(View.INVISIBLE); } else { vhNoFile.layoutAnswer.setVisibility(View.VISIBLE); } break; case 2: //For item_message_unSent ViewHolderUnsent vhUnsent = (ViewHolderUnsent) holder; SendChatModel unSendChat = chatArray.get(holder.getAdapterPosition()).getUnSendChats(); question = unSendChat.getCourseForum().getCourseForumQuestion(); int hasFile = unSendChat.getHasFile(); if (unSendChat.getCourseForum().getCourseForumQuestion() != null) { vhUnsent.unSentQuestion.setText(question); } else { vhUnsent.unSentQuestion.setText(""); } if (unSendChat.getCourseForum().getCourseForumReplyTo() > 0) { vhUnsent.unSentReplyText.setText(unSendChat.getCourseForum().getReplyToSummary()); } else { vhUnsent.unSentReplyText.setText(""); } //This UnSend Message has a file if (hasFile == 1) { String filePath = chatArray.get(holder.getAdapterPosition()).getUnSendChats().getFilePath(); Picasso .with(mContext) .load(new File(filePath)) .resize(64, 64) .into(vhUnsent.unSentImage); } else { vhUnsent.unSentImage.setImageResource(android.R.color.transparent); } break; case 3: //For item_message_Reply ViewHolderReply vRTReply = (ViewHolderReply) holder; vRTReply.replyPastQ.setText(chatArray.get(holder.getAdapterPosition()).getReplayedMessage().getCourseForumQuestion()); vRTReply.replyPastA.setText(chatArray.get(holder.getAdapterPosition()).getReplayedMessage().getCourseForumAnswer()); vRTReply.replyCurrentQ.setText(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumQuestion()); vRTReply.replyCurrentA.setText(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAnswer()); vRTReply.imgReplay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentForum.onEvent(fragmentForum, chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumId()); } }); // check if answer text is empty get answer layout gone if (chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAnswer().equals("")) { vRTReply.layoutAnswer.setVisibility(View.INVISIBLE); } else { vRTReply.layoutAnswer.setVisibility(View.VISIBLE); } break; case 4: //For item_message_q_has_file ViewHolderQFile vhQFile = (ViewHolderQFile) holder; setUserName(vhQFile.qUserName, cfm.getCourseForumQUserName()); setUserName(vhQFile.aUserName, cfm.getCourseForumAUserName()); //Set Question Text setMessage(vhQFile.qText, cfm.getCourseForumQuestion()); //Set Answer Text setMessage(vhQFile.aText, cfm.getCourseForumAnswer()); loadImage( vhQFile.qImage, holder.getAdapterPosition(), chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumQFile() ); vhQFile.qImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showDialog(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumQFile()); } }); vhQFile.reply.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentForum.onEvent(fragmentForum, chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumId()); } }); // check if answer text is empty get answer layout gone if (vhQFile.aText.getText() == "") { vhQFile.layoutAnswer.setVisibility(View.INVISIBLE); } else { vhQFile.layoutAnswer.setVisibility(View.VISIBLE); } break; case 5: //For item_message_a_has_file ViewHolderAFile vhAFile = (ViewHolderAFile) holder; setUserName(vhAFile.qUserName, cfm.getCourseForumQUserName()); setUserName(vhAFile.aUserName, cfm.getCourseForumAUserName()); //Set Question Text setMessage(vhAFile.qText, cfm.getCourseForumQuestion()); //Set Answer Text setMessage(vhAFile.aText, cfm.getCourseForumAnswer()); loadImage( vhAFile.aImage, holder.getAdapterPosition(), chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAFile() ); vhAFile.aImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showDialog(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAFile()); } }); vhAFile.reply.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentForum.onEvent(fragmentForum, chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumId()); } }); // check if answer text is empty get answer layout gone if (vhAFile.aText.getText() == "") { vhAFile.layoutAnswer.setVisibility(View.INVISIBLE); } else { vhAFile.layoutAnswer.setVisibility(View.VISIBLE); } break; case 6: //For item_message_q_a_has_file ViewHolderQAFile vhQAFile = (ViewHolderQAFile) holder; setUserName(vhQAFile.qUserName, cfm.getCourseForumQUserName()); setUserName(vhQAFile.aUserName, cfm.getCourseForumAUserName()); //Set Question Text setMessage(vhQAFile.qText, cfm.getCourseForumQuestion()); //Set Answer Text setMessage(vhQAFile.aText, cfm.getCourseForumAnswer()); //Here Both Question and Answer have file loadImage( vhQAFile.qImage, holder.getAdapterPosition(), chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumQFile() ); loadImage( vhQAFile.aImage, holder.getAdapterPosition(), chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAFile() ); vhQAFile.qImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showDialog(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumQFile()); } }); vhQAFile.aImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showDialog(chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumAFile()); } }); vhQAFile.reply.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { fragmentForum.onEvent(fragmentForum, chatArray.get(holder.getAdapterPosition()).getCourseForumModel().getCourseForumId()); } }); // check if answer text is empty get answer layout gone if (vhQAFile.aText.getText() == "") { vhQAFile.layoutAnswer.setVisibility(View.INVISIBLE); } else { vhQAFile.layoutAnswer.setVisibility(View.VISIBLE); } break; } } public void update(ArrayList<ChatModel> updatedArray) { chatArray.clear(); chatArray.addAll(updatedArray); notifyDataSetChanged(); } @Override public int getItemCount() { return chatArray.size(); } private void setUserName(TextView textView, String name) { if (name.length() > 0) { textView.setText(name); } } private void setMessage(TextView textView, String text) { if (text.length() > 0) { textView.setText(text); } } private void loadImage(final ImageView view, int position, final int fileId) { FileModel fileModel = InternetService.getSingleFile(fileId); String imageAddress = G.DIR_APP + fileModel.getFileName() + "." + fileModel.getFileExtension(); Picasso .with(mContext) .load(new File(imageAddress)) .resize(64, 64) .into(view); } private void showDialog(int fileId) { FileModel fileModel = InternetService.getSingleFile(fileId); final Bitmap bitmap = BitmapFactory.decodeFile(G.DIR_APP + fileModel.getFileName() + "." + fileModel.getFileExtension()); final Dialog dialog = new Dialog(mContext, R.style.CustomDialog); dialog.setContentView(R.layout.activity_image_view); ImageView img = (ImageView) dialog.findViewById(R.id.imgShow); img.setImageBitmap(bitmap); Button dismissButton = (Button) dialog.findViewById(R.id.dissbtn); dismissButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); dialog.show(); } } 方法中获取了Log的位置Ans我从下往上滚动然后我在logCat中得到了这个项目0-1-2-3-4-5-6-12-13-14-15 -16-17! 项目7-8-9-1-11未登录!

这对我来说非常重要。 谢谢你的回答。

3 个答案:

答案 0 :(得分:3)

RecyclerView重用现有视图以更好地执行。因此调用onBindViewHolder并使用新的值和样式更新上一个视图。如果您不使用新值替换现有值,您仍会看到旧值。

来自RecyclerView文档。

  

如果用户滚动列表,Android支持库会将已准备好的视图持有者带入视图,并根据需要创建和绑定新视图。它不会立即摧毁已经滚出视线的视图持有者;如果用户向后滚动,它们将保持可用状态。但是,在创建了一定数量的视图持有者后,Android支持库不会创建新视图。相反,它通过为它们调用onBindViewHolder()来指定一个新位置,根据需要重新绑定现有的视图持有者。该方法更新了视图持有者的内容,但重新使用已为该视图持有者创建的视图。该方法不必执行昂贵的操作,如构建或膨胀新视图。

正如Amod Gokhale所说。在大多数情况下,由于缺少else的if语句,会出现错误的视图。

答案 1 :(得分:1)

对于position中用于检索项目的所有onBindViewHolder,您应使用holder.getAdapterPosition()

P.S。与您的问题无关。在onCreateViewHolder中,您首先要对所有类型的View进行充气,然后根据您的viewType仅返回您需要的类型viewType。您应首先检查View,然后只对您需要的<script> $(document).ready(function(){ tinymce.init({ selector : 'textarea', //content_css : "css/tinymcecss.css", setup : function(editor){ editor.on('init', function(event) { var iframeMce = $('#mce_0_ifr')[0]; rangy.init(); highlighter = rangy.createHighlighter(iframeMce); highlighter.addClassApplier(rangy.createClassApplier("highlight", { ignoreWhiteSpace: true, tagNames: ["span", "a"] })); $('#sl-highlight').on('click', function(){ var selection = rangy.getSelection(iframeMce); highlighter.highlightSelection('highlight', { selection : selection, exclusive : true }); }); }); } }); }); 进行充气。

答案 2 :(得分:0)

最后我发现了问题。 我正在使用viewPager和3个片段。当我打开包含上述recyclerView的聊天片段并向上和向下滚动时,所有项目都将出现在错误的位置!所以我在onBindViewHolder()中记录了项目位置,因为@Ahmadul Hoq对我说。然后我发现物品不会连续进入onBind!

最后我发现这个问题是关于fragment和viewPager的。然后我用这个方法再次设置我的recyclerView,当用户将它扫到看时。就像这样:

  @Override
  public void setUserVisibleHint(boolean isVisibleToUser){
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser){

      //Setting up recycler view for Chats
      LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
      rvMain.setLayoutManager(mLayoutManager);

      mAdapter = new chatAdapter(populateCourseChats(), getActivity() , this);
      rvMain.setAdapter(mAdapter);
      scrollRecyclerToBottom(); //Scroll recyclerView to bottom
    }
  }

现在一切都很好。

但我没有发现为什么会发生这种情况?! 如果你知道请告诉我。 谢谢。