java - 按下按钮的 Android Firebase RecyclerView 出现无法解释的错误

标签 java android firebase firebase-realtime-database android-recyclerview

我有一个 RecyclerView 和一个用于“绑定(bind)”每个项目的按钮(移动到数据库中的另一个 child )。

大多数时候它运行良好,但有时我会收到 indexOutOfBounds 异常。

这是一个屏幕截图:

css

当我在顶部回收器 View 项目中按“BIND”时,我收到了这个错误。 我让它打印了这一行:

Log.d("dDebug","Almost bug! Size: " + ((MissionAdapter) MissionAdapter.this).mSnapshots.size() + " , index: " + missionPosition);

它打印出这个:

D/dDebug: Almost bug! Size: 1 , index: 1

在这里您可以看到错误 - 大小 1,索引 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!) - 第二个项目正在移动(在索引 1 处) . 所以这意味着我获取被点击的项目的方式可能有问题。

最佳答案

Rookie recycler view 错误:view holder 可以四处移动和重复使用(从而改变其位置),而 onClick 回调只会存储对原始位置的引用。要解决此问题,请使用 viewHolder.getAdapterPosition()。 👍

关于java - 按下按钮的 Android Firebase RecyclerView 出现无法解释的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48815595/

相关文章:

java - 确定最大和最小数

java - 如果我想构建一个不需要使用 gsm 调制解调器的 java 应用程序,有什么办法吗?

java - 需要了解一些 `ant fat/shaded` jar概念

android - 如何用 Powermockito 模拟最后一个类?

java - Android,当应用程序启用设备管理员时更改 GPS 状态

android - onMeasure 在 Android 6 的 Horizo​​ntalScrollView 中返回 widthMeasureSpec = 0

ios - 通过代码强制更改/更新 Firebase 通知 token 或实例 ID?

android - Firebase 分析 : Show Average of 'Value' Parameter and average of time like 'hh:mm:ss' in the Console for events sent from Android app

java - 关于 Java 嵌套 if 语句的问题

java - 在 Android Studio 中检索 Firebase 数据到 ListView