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

时间:2017-01-29 14:53:47

标签: android firebase nullpointerexception firebase-realtime-database

我是一位长期追随者,第一次发布海报,所以我希望我能做到这一点。我正在尝试进入android-firebase开发,并认为最好的方法是选择一个项目并尝试找到我的方式。我一直在努力开发一个简单的工作应用程序(我是一名医生),这将允许我们的团队查看关于我们住院病人的简要进展记录,并且还允许我们发布每个需要执行的任务。患者。我已经完成了大部分工作,但是,我一度陷入困境。打开患者记录后,会加载详细信息页面,其中包括“评论”部分和“任务”部分。这两个都是包含多对一条目的RecyclerViews。我面临的问题与在单击时删除其中一个“任务”项目有关(因此它已从列表中删除,并且不再处于待处理状态)。我一直得到一个空指针异常。问题是,我不完全确定我的代码是否正确。我还在学习,所以我的代码包含了很多来自不同地方的部分(我从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)

就像我说的那样,我不确定问题出在哪里,而且我已经尝试了很多东西来解决问题,但不能。任何帮助都将受到高度赞赏。

非常感谢。

1 个答案:

答案 0 :(得分:1)

我不是firebase的专家,但是从你的代码中我看不出你在 mAdapter 字段中分配了什么。这就是为什么稍后在 removeItem 方法中访问NPE时使用NPE的原因。

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