vendredi 26 juin 2015

Android prevent app from querying an empty database on startup

I'm building a simple todo/task app in which tasks are presented in a Recycler/card view layout and upon the selection of a task the user is taken a "detailed" view of that specific task. I'm testing my app using the Genymotion emulator. My problem is the app crashes immediately upon startup with a NPE.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.api.client.util.DateTime.toString()' on a null object reference
            at com.github.idclark.forgetmenot.TaskAdapter.onBindViewHolder(TaskAdapter.java:35)
            at com.github.idclark.forgetmenot.TaskAdapter.onBindViewHolder(TaskAdapter.java:17)

Although I'm not entirely sure, I think this is because I haven't entered any data into the database yet. The database is first queried from the fragment that is inflated by my Main activity.

public static class PlaceholderFragment extends Fragment {

        Activity mActivity;
        RecyclerView mRecyclerView;
        TaskAdapter taskAdapter;
        AddFloatingActionButton mFabView;
        CheckBox mCheckBox;

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            mRecyclerView = (RecyclerView) rootView.findViewById(R.id.cardList);
            mFabView = (AddFloatingActionButton) rootView.findViewById(R.id.normal_plus);

            mFabView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Intent createTaskIntent = new Intent(v.getContext(), EditActivity.class);
                    startActivity(createTaskIntent);
                }
            });

            taskAdapter = new TaskAdapter(new TaskTableController(getActivity()).getAllTasksForUser());
            return rootView;
        }

My TaskAdapter expects an ArrayList<Task>

public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {

    private List<Task> taskList;
    OnItemClickListener mItemClickListener;

    public TaskAdapter(List<Task> taskList) {
        this.taskList = taskList;
    }

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

    @Override
    public void onBindViewHolder(TaskViewHolder taskViewHolder, int i) {
        Task task = taskList.get(i);
        taskViewHolder.mTitle.setText(task.getTitle());
        taskViewHolder.mUpdated.setText(task.getUpdated().toString());
        if (task.getStatus().equals("completed")) {
            taskViewHolder.mStatus.setChecked(true);
        } else taskViewHolder.mStatus.setChecked(false);

    }

    @Override
    public TaskViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View itemView = LayoutInflater.from(viewGroup.getContext()).
                inflate(R.layout.tasklist_layout, viewGroup, false);

        return new TaskViewHolder(itemView);
    }

The actual query to the database looks like

public List<Task> getAllTasksForUser() {
        final String QUERY_ALL_RECORDS = "SELECT * FROM " + TaskEntry.TABLE_NAME;

        List<Task> taskList = new ArrayList<>();
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(QUERY_ALL_RECORDS, null);
        if (cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                Task task = new Task();
                int TaskId = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_ID);
                task.setId(cursor.getString(TaskId));
                task.setTitle(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE)));
                task.setDue(new DateTime(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DUE))));
                task.setNotes(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_NOTES)));
                taskList.add(task);
            }
        } else return taskList;
        db.close();
        return taskList;
    }

When the app is first installed on the emulator, there is no data in the database, which I think is what is causing the NPE. How do I handle this situation so that if there is no data my fragment just displays an empty list (ie blank). I'm already checking to see if cursor.getCount() is greater than 0, if it's not return an empty list to the adapter. What am I missing to get rid of this NPE?

Aucun commentaire:

Enregistrer un commentaire