android - 尝试删除 Android Firebase 中的项目时出现空指针异常

标签 android firebase nullpointerexception firebase-realtime-database

我是一个长期的追随者,第一次张贴,所以我希望我做对了。我正在尝试进入 android-firebase 开发,并认为最好的方法是选择一个项目并尝试找到我的方式。我一直在尝试开发一个简单的工作应用程序(我是一名医生),它可以让我们的团队查看有关住院病人的简要进度记录,还可以让我们发布需要对每个病人执行的任务病人。我已经完成了大部分工作,但是,我被困在了一个点上。在我打开患者记录后,会加载详细信息页面,其中包括“评论”部分和“任务”部分。这两个都是包含多对一条目的 RecyclerView。我面临的问题与在单击时尝试删除其中一个“任务”项目有关(因此它已从列表中删除,并且不再处于待处理状态)。我不断收到空指针异常。问题是,我不完全确定我的代码是否正确。我还在学习,所以我的代码包括很多我玩过的不同地方的部分(我从 github 的 android-firebase 数据库示例以及许多其他在线资源开始),并重写(之后很多破坏和修复)让它工作。很抱歉介绍很长。所以,这就是我到目前为止所得到的(不是完整的代码,只是我认为重要的部分)。我希望有人能帮助我。

postDetailActivity.java

private static class TaskViewHolder extends RecyclerView.ViewHolder {

        public TextView dateView;
        public TextView bodyView;
        public ImageButton checkView;

        public TaskViewHolder(View itemView, final TaskAdapter mTaskAdapter) {
            super(itemView);

            dateView = (TextView) itemView.findViewById(R.id.task_date);
            bodyView = (TextView) itemView.findViewById(R.id.task_body);
            checkView = (ImageButton) itemView.findViewById(R.id.check);
            checkView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG, "Adapter Position:" + getAdapterPosition());
                    mTaskAdapter.removeItem(getAdapterPosition());
                }
            });
        }

private static class TaskAdapter extends RecyclerView.Adapter<TaskViewHolder> {

    private Context mContext;
    private DatabaseReference mDatabaseReference;
    private DatabaseReference mTaskReference;
    private ChildEventListener mChildEventListener;
    private FirebaseRecyclerAdapter<Task, TaskViewHolder> mAdapter;

    private List<String> mTaskIds = new ArrayList<>();
    private List<Task> mTasks = new ArrayList<>();


    public TaskAdapter(final Context context, DatabaseReference ref) {
        mContext = context;
        mDatabaseReference = ref;

        // Create child event listener
        // [START child_event_listener_recycler]
        ChildEventListener childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());

                // A new task has been added, add it to the displayed list
                Task task = dataSnapshot.getValue(Task.class);

                // [START_EXCLUDE]
                // Update RecyclerView
                mTaskIds.add(dataSnapshot.getKey());
                mTasks.add(task);
                notifyItemInserted(mTasks.size() - 1);
                // [END_EXCLUDE]
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());

                // A task has changed, use the key to determine if we are displaying this
                // task and if so displayed the changed task.
                Task newTask = dataSnapshot.getValue(Task.class);
                String taskKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int taskIndex = mTaskIds.indexOf(taskKey);
                if (taskIndex > -1) {
                    // Replace with the new data
                    mTasks.set(taskIndex, newTask);

                    // Update the RecyclerView
                    notifyItemChanged(taskIndex);
                } else {
                    Log.w(TAG, "onChildChanged:unknown_child:" + taskKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

                // A task has changed, use the key to determine if we are displaying this
                // task and if so remove it.
                String taskKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int taskIndex = mTaskIds.indexOf(taskKey);
                if (taskIndex > -1) {
                    // Remove data from the list
                    mTaskIds.remove(taskIndex);
                    mTasks.remove(taskIndex);

                    // Update the RecyclerView
                    notifyItemRemoved(taskIndex);
                } else {
                    Log.w(TAG, "onChildRemoved:unknown_child:" + taskKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());

                // A task has changed position, use the key to determine if we are
                // displaying this task and if so move it.
                Task movedTask = dataSnapshot.getValue(Task.class);
                String taskKey = dataSnapshot.getKey();

                // ...
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w(TAG, "postTasks:onCancelled", databaseError.toException());
                Toast.makeText(mContext, "Failed to load tasks.",
                        Toast.LENGTH_SHORT).show();
            }
        };
        ref.addChildEventListener(childEventListener);
        // [END child_event_listener_recycler]

        // Store reference to listener so it can be removed on app stop
        mChildEventListener = childEventListener;

    }

    @Override
    public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.item_task, parent, false);
        return new TaskViewHolder(view, this);
    }

    @Override
    public void onBindViewHolder(TaskViewHolder holder, int position) {
        Task task = mTasks.get(position);
        holder.dateView.setText(task.date);
        holder.bodyView.setText(task.text);
    }

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

    public void cleanupListener() {
        if (mChildEventListener != null) {
            mDatabaseReference.removeEventListener(mChildEventListener);
        }
    }

    public void removeItem(int position) {
        mAdapter.getRef(position).removeValue();
        mAdapter.notifyItemRemoved(position);

错误日志

java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.firebase.ui.database.FirebaseRecyclerAdapter.getRef(int)' on a null object reference
                  at com.hanykasem.omfsrounds.PostDetailActivity$TaskAdapter.removeItem(PostDetailActivity.java:606)
                  at com.hanykasem.omfsrounds.PostDetailActivity$TaskViewHolder$1.onClick(PostDetailActivity.java:451)
                  at android.view.View.performClick(View.java:5198)
                  at android.view.View$PerformClick.run(View.java:21147)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

就像我说的,我不太确定问题出在哪里,而且我已经尝试了很多方法来解决它,但没有成功。任何帮助将不胜感激。

非常感谢。

最佳答案

我不是 firebase 方面的专家,但从您的代码中我看不到您是否为您的 mAdapter 字段分配了任何内容。这就是为什么您稍后在 removeItem 方法中访问它时遇到 NPE 的原因。

关于如何使用 firebase 适配器的示例: http://www.coderefer.com/firebaseui-android-firebase-database/

关于android - 尝试删除 Android Firebase 中的项目时出现空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41922223/

相关文章:

java - 什么是NullPointerException,我该如何解决?

android - 不推荐使用 setTargetFragment() 后如何替换它

android - 如何将 FAB 转换为弹出菜单?

java - 如何使用 Java 在 Android 中进行图像转换

ios - 将音频上传到 Firebase Swift

java - 使用Optional.ofNullable()简化条件

android gradle 错误 : Can't register given path of type 'SOURCE' because it's out of content root

java - list 合并失败并出现多个错误,请参阅日志错误

android - 升级旧版 Android 应用程序中的 Gradle 版本

java - Android - 当定义了多个按钮时,自定义对话框抛出 NullPointerException