简体   繁体   English

回收器适配器 onClick 项目的问题

[英]Problem with recycler-adapter onClick item

I have a problem with onClick method in my recycler adapter.我的回收器适配器中的 onClick 方法有问题。

I feed my adapter from fragment and then in adapter i get all the information i need from firebase including users info and buttons "join" that were already clicked (i set red background to that button).我从片段中提供我的适配器,然后在适配器中我从 firebase 获得我需要的所有信息,包括用户信息和已经点击的“加入”按钮(我为那个按钮设置了红色背景)。 Everything works fine untill i click on button "join" that was not pressed before.一切正常,直到我点击之前未按下的“加入”按钮。 The color of the button changes (works fine and saves info to firebase with joinEvent method) but sometimes the color of the nearby buttons changes as well.按钮的颜色会发生变化(工作正常并使用 joinEvent 方法将信息保存到 firebase),但有时附近按钮的颜色也会发生变化。 I did research about the issue but nothing works for me.我对这个问题进行了研究,但对我没有任何作用。 I tried assigning position to the methods (joinEvent, checkIfInterested, checkIfAccepted) instead of holders but that does not work.我尝试将 position 分配给方法(joinEvent、checkIfInterested、checkIfAccepted)而不是持有人,但这不起作用。 I would appreciate any help: This is my adapter:我将不胜感激:这是我的适配器:

public class SuggestionHomeAdapter extends RecyclerView.Adapter<SuggestionHomeAdapter.ViewHolder> {
private Context mContext;
private List<Suggestion> mSuggestion;
private FirebaseUser fuser;
int index = -1;


public SuggestionHomeAdapter(Context mContext, List<Suggestion> mSuggestion) {
    this.mSuggestion = mSuggestion;
    this.mContext = mContext;
}

@NonNull
@Override
public SuggestionHomeAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.suggestion_home_item, parent, false);
    return new SuggestionHomeAdapter.ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull final SuggestionHomeAdapter.ViewHolder holder, final int position) {

    final Suggestion suggestion = mSuggestion.get(position);
    fuser = FirebaseAuth.getInstance().getCurrentUser();


    holder.title.setText(suggestion.getTitle());
    holder.description.setText(suggestion.getDescription());
    holder.join.setBackgroundColor(0xF0DC82);
    getUserInfo(holder.username, holder.profile_image, suggestion.getSpublisher());

    checkIfInterested(holder.join, suggestion.getSid(), fuser.getUid());
    checkIfAccepted(holder.join, suggestion.getSid(), fuser.getUid());

    ColorDrawable buttonColor = (ColorDrawable) holder.join.getBackground();
    final int colorId = buttonColor.getColor();

    holder.join.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(colorId != 0xFFFF0000 && colorId != 0xff00ff00){
                joinEvent(fuser.getUid(), suggestion.getSid(), suggestion.getSpublisher());
            notifyItemChanged(position);}
        }
    });
}

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

public class ViewHolder extends RecyclerView.ViewHolder {

    public TextView username;
    public ImageView profile_image;
    public TextView title;
    public TextView description;
    public Button join;

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

        username = itemView.findViewById(R.id.username);
        profile_image = itemView.findViewById(R.id.profile_image);
        title = itemView.findViewById(R.id.title);
        description = itemView.findViewById(R.id.description);
        join = itemView.findViewById(R.id.btn_join);

    }
}

private void getUserInfo(final TextView username, final ImageView profile_image, final String sPublisher) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(sPublisher);
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            final User user = dataSnapshot.getValue(User.class);
            username.setText(user.getUsername());

            if (user.getImageURL().equals("default")) {
                profile_image.setImageResource(R.mipmap.ic_launcher);
            } else {
                Glide.with(mContext.getApplicationContext()).load(user.getImageURL()).into(profile_image);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}

this is my joinEvent method in it这是我的 joinEvent 方法

private void joinEvent(String fuser, String sId, String publisher){
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");

    String iId = reference.push().getKey();

    HashMap<String, Object> map = new HashMap<>();
    map.put("interested", fuser);
    map.put("sid", sId);
    map.put("iId", iId);
    map.put("publisher", publisher);
    map.put("accepted", "");
    reference.child(iId).setValue(map);

    //join.setBackgroundColor(0xFFFF0000);

}

and my checkIfInterested and checkIfAccepted methods in it和我的 checkIfInterested 和 checkIfAccepted 方法

private void checkIfInterested(final Button join_btn, final String sid, final String fuser) { 

    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                final Interested interested = snapshot.getValue(Interested.class);
                assert interested != null;
                if (interested.getSid().equals(sid) && interested.getInterested().equals(fuser)) {
                    join_btn.setBackgroundColor(0xFFFF0000);
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

private void checkIfAccepted(final Button join_btn, final String sid, final String fuser) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                final Interested interested = snapshot.getValue(Interested.class);
                assert interested != null;
                if (interested.getSid().equals(sid) && interested.getAccepted().equals(fuser)) {
                    join_btn.setBackgroundColor(0xff00ff00);
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

everything works good with firebase but buttons change color when they should not. firebase 一切正常,但按钮不应该改变颜色。

First of all, you should not be using the onBindViewHolder()'s position parameter in your OnClickListener.首先,您不应该在 OnClickListener 中使用 onBindViewHolder() 的 position 参数。 This is unreliable and you should use holder.getAdapterPosition() instead.这是不可靠的,您应该改用 holder.getAdapterPosition()。

Next, RecyclerViews re-use or "recycle" views which makes them efficient for having many views in a list.接下来,RecyclerViews 重用或“回收”视图,这使得它们可以有效地在列表中拥有许多视图。 However, they have a problem if you want different items to have different background colors.但是,如果您希望不同的项目具有不同的背景 colors,他们就会遇到问题。 The solution is to keep track of which ones you want to be "selected" or have a different background then update it accordingly.解决方案是跟踪您想要“选择”哪些或具有不同背景,然后相应地更新它。 So:所以:

if(item.isSelected())
    setBackgroundColor(<highlight_color>)
else
    setBackgroundColor(<default_color>)

You need to make sure ones that are not selected are still set to the default background because the recycler view might have accidentally used a highlighted one in its place.你需要确保那些没有被选中的仍然设置为默认背景,因为回收站视图可能不小心使用了一个突出显示的位置。

RecyclerView used ViewHolder design pattens. RecyclerView使用ViewHolder设计模式。 That's why it's view is reused between different items.这就是为什么它的视图在不同的项目之间重用。 So, your call to holder.join.getBackground() don't give you the exact result for that item.因此,您对holder.join.getBackground()的调用不会为您提供该项目的确切结果。 To avoid you should store your color inside model [here: Suggestion] and make decision based on that.为避免您应该将color存储在 model [此处:建议] 中并据此做出决定。

Step - 1:步骤1:

class Suggestion {

    ...

    private int buttonColor = 0xF0DC82;

    public int getButtonColor() {
        return buttonColor;
    }

    public void setButtonColor(int buttonColor) {
        this.buttonColor = buttonColor;
    }

    ...

}

Step - 2: update your checkIfAccepted and checkIfAccepted like below:步骤 - 2:更新您的checkIfAcceptedcheckIfAccepted ,如下所示:

private void checkIfAccepted(Suggestion suggestion, final String fuser) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                final Interested interested = snapshot.getValue(Interested.class);
                assert interested != null;
                if (interested.getSid().equals(suggestion.getSid()) && interested.getAccepted().equals(fuser)) {
                    suggestion.setButtonColor(0xff00ff00);
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

private void checkIfAccepted(Suggestion suggestion, final String fuser) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                final Interested interested = snapshot.getValue(Interested.class);
                assert interested != null;
                if (interested.getSid().equals(suggestion.getSid()) && interested.getAccepted().equals(fuser)) {
                    suggestion.setButtonColor(0xff00ff00);
                }
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

Step - 3: Then change your onBindViewHolder implementation:步骤 - 3:然后更改您的onBindViewHolder实现:

@Override
public void onBindViewHolder(@NonNull final SuggestionHomeAdapter.ViewHolder holder, final int position) {

    final Suggestion suggestion = mSuggestion.get(position);
    fuser = FirebaseAuth.getInstance().getCurrentUser();

    holder.title.setText(suggestion.getTitle());
    holder.description.setText(suggestion.getDescription());
    holder.join.setBackgroundColor(suggestion.getButtonColor());
    getUserInfo(holder.username, holder.profile_image, suggestion.getSpublisher());

    checkIfInterested(suggestion, fuser.getUid());
    checkIfAccepted(suggestion, fuser.getUid());

    holder.join.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(suggestion.getButtonColor() != 0xFFFF0000 && suggestion.getButtonColor() != 0xff00ff00){
                joinEvent(fuser.getUid(), suggestion);
                notifyItemChanged(position);
            }
        }
    });
}

Step - 4: Lastly update joinEvent步骤 - 4:最后更新joinEvent

private void joinEvent(String fuser, Suggestion suggestion) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Interested");

    String iId = reference.push().getKey();

    HashMap<String, Object> map = new HashMap<>();
    map.put("interested", fuser);
    map.put("sid", suggestion.getSid());
    map.put("iId", iId);
    map.put("publisher", suggestion.getSpublisher());
    map.put("accepted", "");
    reference.child(iId).setValue(map);

    suggestion.setButtonColor(0xFFFF0000);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM