我有一个RecyclerView和一个用于'绑定'的按钮。每个项目(转移到DB的另一个孩子)。
大部分时间它都运行良好,但有时我会收到indexOutOfBounds Exception。
这是一个截图:
当我按下'BIND'在顶部回收站视图项目中,我收到此错误。 我打印了这一行:
Log.d("dDebug","Almost bug! Size: " + ((MissionAdapter) MissionAdapter.this).mSnapshots.size() + " , index: " + missionPosition);
它打印出来:
D/dDebug: Almost bug! Size: 1 , index: 1
在这里你可以看到bug - size 1,index 1,所以它会有indexOutOfBounds。
这是代码:
public class AvailableFragmentPilot extends Fragment {
private String TAG = "dDEBUG";
private RecyclerView mavailableList;
private DatabaseReference mAvailableMissionsDb, mPendingMissionsDb;
private FirebaseAuth mAuth;
private ProgressDialog mSubmitMsnProgress;
private String mCurrent_pilot_id;
private View mMainView;
// Query queries;
public AvailableFragmentPilot() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mMainView = inflater.inflate(R.layout.fragment_of_recycler_view_user, container, false);
mavailableList = (RecyclerView)mMainView.findViewById(R.id.mission_recycler_user);
mAuth = FirebaseAuth.getInstance();
mSubmitMsnProgress = new ProgressDialog(getContext());
mCurrent_pilot_id = mAuth.getCurrentUser().getUid();
mAvailableMissionsDb = FirebaseDatabase.getInstance().getReference().child("Missions").child("Available");
mAvailableMissionsDb.keepSynced(true);
mPendingMissionsDb = FirebaseDatabase.getInstance().getReference().child("Missions").child("Pending");
mPendingMissionsDb.keepSynced(true);
// queries = mAvailableMissionsDb.orderByChild("user_uid").equalTo(mCurrent_pilot_id);
mavailableList.setHasFixedSize(true);
mavailableList.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return mMainView;
}
@Override
public void onStart() {
super.onStart();
mavailableList.setAdapter(new MissionAdapter(mAvailableMissionsDb));
}
private class MissionAdapter extends FirebaseRecyclerAdapter<Mission, AvailableFragmentPilot.MissionsViewHolder> {
public MissionAdapter(Query queries){
super(Mission.class, R.layout.missions_single_layout, AvailableFragmentPilot.MissionsViewHolder.class, queries);
}
@Override
protected void populateViewHolder(AvailableFragmentPilot.MissionsViewHolder missionViewHolder, final Mission missionModel, final int missionPosition) {
Log.d(TAG, "inside populateViewHolder" + missionModel.getType() + " , " + missionModel.getDescription());
missionViewHolder.setMissionName(missionModel.getType());
missionViewHolder.setMissionDescription(missionModel.getDescription());
missionViewHolder.setMissionStatus(missionModel.getStatus());
missionViewHolder.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Mission clickedMission = null;
if (((MissionAdapter) MissionAdapter.this).mSnapshots.size()>missionPosition){
clickedMission = AvailableFragmentPilot.MissionAdapter.this.getItem(missionPosition);
Log.d("dDebug","Ein bug. Size: " + ((MissionAdapter) MissionAdapter.this).mSnapshots.size() + " , index: " + missionPosition + " , mission: " + clickedMission.getType() + ": " + clickedMission.getDescription());
}
else{
Log.d("dDebug","Almost bug! Size: " + ((MissionAdapter) MissionAdapter.this).mSnapshots.size() + " , index: " + missionPosition);
}
if (clickedMission != null){ // for the sake of being extra-safe
// String url_str = getRef(missionPosition).toString();
// String uuid_for_mission = url_str.split("/")[5];
Log.d(TAG,"The button was pressed for mission: " + clickedMission.getType() + " , uid: " + missionModel.getMission_uid());
// removeMission(uuid_for_mission);
bindMission(clickedMission);
}
}
});
}
}
public void bindMission(final Mission mission){
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setCancelable(false);
builder.setTitle("Mission bind");
builder.setMessage("Are you sure you want to bind this mission?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
mAvailableMissionsDb.child(mission.getMission_uid()).setValue(null);
final HashMap<String, String> missionMap = new HashMap<>();
missionMap.put("username", mission.getUsername());
missionMap.put("user_uid", mission.getUser_uid());
missionMap.put("mission_uid", mission.getMission_uid());
missionMap.put("type", mission.getType());
missionMap.put("status", "Pending");
missionMap.put("description", mission.getDescription());
missionMap.put("x", String.valueOf(mission.getX()));
missionMap.put("y", String.valueOf(mission.getY()));
missionMap.put("pilot_uid", mCurrent_pilot_id);
mPendingMissionsDb.child(mission.getMission_uid()).setValue(missionMap).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()){
// Log.d("dDebug","Before");
mSubmitMsnProgress.dismiss();
Toast.makeText(getContext(), ("Bind to mission " + mission.getType()),
Toast.LENGTH_LONG).show();
Log.d("dDebug","Painting in Red 1");
}
else {
Toast.makeText(getContext(), "Something went wrong",
Toast.LENGTH_SHORT).show();
}
}
});
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("dDebug","ok, not binding");
}
});
// Create the AlertDialog object and return it
builder.create().show();
}
public static class MissionsViewHolder extends RecyclerView.ViewHolder {
View mView;
Button button ;
public MissionsViewHolder(View itemView) {
super(itemView);
mView = itemView;
button = (Button)mView.findViewById(R.id.mission_single_button);
button.setText("BIND");
}
public void setMissionName(String name){
TextView mMissionNameView = mView.findViewById(R.id.mission_single_name);
mMissionNameView.setText(name);
}
public void setMissionStatus(String status){
TextView mMissionStatusView = mView.findViewById(R.id.mission_single_status);
mMissionStatusView.setText(status);
if (status.equals("Available")){
mMissionStatusView.setTextColor(Color.parseColor("#008000"));;
} else {
mMissionStatusView.setTextColor(Color.parseColor("#FF0000"));;
}
}
public void setMissionDescription(String description){
TextView mMissionDescriptionView = mView.findViewById(R.id.mission_single_description);
mMissionDescriptionView.setText(description);
}
}
}
另外 - 有时候我会有5个项目,我会按最上面的一个,(应该是索引0!) - 并且正在移动SECOND项目(在索引处) 1)。 因此,这意味着我获得被抄袭的物品的方式可能会出现问题。
答案 0 :(得分:3)
新手回收者视图错误:视图持有者可以四处移动并重复使用(从而改变其位置),而onClick
回调只会存储对原始位置的引用。要解决此问题,请使用viewHolder.getAdapterPosition()
。