-1

I created a Fragment that contains a list of items that contains information loaded from the SQLite database. I used CursurAdapter to load the data. Here is the Fragment and the inner AlarmAdapter class that extends CursorAdapter.

public class AlarmListFragment extends Fragment {

    private DBHelper dbHelper;
    private Context context;
    private Cursor mCursor;
    private AlarmListAdapter alarmItemAdapter;
    private final String QUERY = String.format("SELECT * FROM %s", DBHelper.TABLE_ALARM_LIST);

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = getActivity().getApplicationContext();
        dbHelper = new DBHelper(context);
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        mCursor = db.rawQuery(QUERY, null);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        /*
         * Instead of doing inflater.inflate(R.layout.fragment_alarm_list, null);
         * inflater.inflate(R.layout.fragment_alarm_list, container, false) will occur with the given container, but won't attach it to the parent.
         */
        View view = inflater.inflate(R.layout.fragment_alarm_list, container, false);

        final ListView lvAlarmsList = (ListView) view.findViewById(R.id.lvAlarmsList);
        alarmItemAdapter = new AlarmListAdapter(context, mCursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        lvAlarmsList.setAdapter(alarmItemAdapter);

        loadAlarms();

        Button btnAddNewAlarm = (Button) view.findViewById(R.id.btnAddNewAlarm);
        btnAddNewAlarm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlarmPreferencesFragment fragment = new AlarmPreferencesFragment();
                FragmentTransaction transaction = getFragmentManager().beginTransaction();
                transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
                transaction.replace(R.id.main_frame, fragment);
                transaction.addToBackStack(null);
                transaction.commit();
            }
        });
        return view;
    }

    private void loadAlarms() {
        int alarmsCount = dbHelper.getAllAlarms().size();

        if(alarmsCount != 0) {
            for (int i = 1; i <= alarmsCount; i++) {
                Alarm alarm = dbHelper.getAlarm(i);
                alarmItemAdapter.addItem(alarm);
            }
        }
        alarmItemAdapter.notifyDataSetChanged();
    }

    class AlarmListAdapter extends CursorAdapter {

        private ArrayList<Alarm> itemsList = new ArrayList<>();

        AlarmListAdapter(Context context, Cursor cursor, int flags) {
            super(context, cursor, flags);

        }

        @Override
        public int getCount() {
            return itemsList.size();
        }

        @Override
        public Object getItem(int i) {
            return itemsList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            return inflater.inflate(R.layout.listitem_alarm, parent, false);
        }

        @Override
        protected void onContentChanged() {
            super.onContentChanged();
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {

            final long id = cursor.getLong(0);
            final int position = cursor.getPosition();
            final Alarm alarm = dbHelper.getAlarm(id);

            CardView cvAlarmItem = (CardView) view.findViewById(R.id.cvAlarmItem);
            cvAlarmItem.setBackgroundColor(ContextCompat.getColor(context, R.color.super_light_grey));
            cvAlarmItem.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // If you click the CardView item, it will lead to the alarm preference fragment with the corresponding alarm's info.
                    Bundle bundle = new Bundle();
                    bundle.putSerializable("alarm", alarm);
                    Toast.makeText(getContext(), ""+id, Toast.LENGTH_SHORT).show();
                    AlarmPreferencesFragment fragment = new AlarmPreferencesFragment();
                    fragment.setArguments(bundle);
                    FragmentTransaction transaction = getFragmentManager().beginTransaction();
                    transaction.replace(R.id.main_frame, fragment);
                    transaction.addToBackStack(null);
                    transaction.commit();
                }
            });

            TextView tvSetAlarmType = (TextView) view.findViewById(R.id.tvSetAlarmType);
            int alarmType = alarm.getRingTypeOptionNum();
            String strAlarmType = "";
            switch(alarmType) {
                case SoundVibrate.SOUND:
                    strAlarmType = getString(R.string.sound);
                    break;
                case SoundVibrate.SOUND_AND_VIBRATE:
                    strAlarmType = getString(R.string.sound_and_vibrate);
                    break;
                case SoundVibrate.VIBRATE:
                    strAlarmType = getString(R.string.vibrate);
                    break;
            }

            tvSetAlarmType.setTextColor(ContextCompat.getColor(context, R.color.dark_grey));
            tvSetAlarmType.setText(strAlarmType);

            TextView tvSetAlarmRepeat = (TextView) view.findViewById(R.id.tvSetAlarmRepeat);
            tvSetAlarmRepeat.setTextColor(ContextCompat.getColor(context, R.color.dark_grey));

            Alarm.Day[] repeatDays = alarm.getRepeatDays();

            String guide = "";
            int size = repeatDays.length;
            if(size > 1) {
                int i = 0;
                while(i<size-1) {
                    guide += repeatDays[i].toString() + ", ";
                    ++i;
                }
                guide += "and " + repeatDays[size-1];
            } else if(size == 1){
                guide = repeatDays[0].toString();
            } else {
                guide = getString(R.string.never);
            }

            tvSetAlarmRepeat.setText(guide);

            TextView tvSetAlarmTime = (TextView) view.findViewById(R.id.tvSetAlarmTime);
            String strAlarmTime = alarm.getAlarmTimeString();
            tvSetAlarmTime.setTextColor(ContextCompat.getColor(context, R.color.dark_grey));
            tvSetAlarmTime.setText(strAlarmTime);

            Switch switchAlarmOnOff = (Switch) view.findViewById(R.id.switchAlarmOnOff);
            boolean active = alarm.isAlarmActive();
            switchAlarmOnOff.setChecked(active);

            switchAlarmOnOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                }
            });

            ImageView ivDelete = (ImageView) view.findViewById(R.id.ivDelete);
            ivDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Cursor c = alarmItemAdapter.getCursor();
                    c.moveToPosition(position);
                    dbHelper.deleteAlarm(alarm);
                    loadAlarms();
                }
            });
        }

        void addItem(Alarm item) {
            itemsList.add(item);
        }
    }
}

Here's the screenshot.

enter image description here

What I want to do here is, if I click the 'X' on the item, the item is removed from the database and the list. But now, if click the 'X', the application quits leaving this error message.

01-20 12:50:13.969 20112-20112/com.marshall.alarm E/AndroidRuntime: FATAL EXCEPTION: main
 Process: com.marshall.alarm, PID: 20112
 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
     at com.marshall.alarm.ui.AlarmListFragment$AlarmListAdapter.bindView(AlarmListFragment.java:200)
     at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:273)
     at android.widget.AbsListView.obtainView(AbsListView.java:2402)
     at android.widget.ListView.makeAndAddView(ListView.java:1891)
     at android.widget.ListView.fillSpecific(ListView.java:1364)
     at android.widget.ListView.layoutChildren(ListView.java:1676)
     at android.widget.AbsListView.onLayout(AbsListView.java:2206)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
     at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1795)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
     at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
     at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
     at android.view.View.layout(View.java:16075)
     at android.view.ViewGroup.layout(ViewGroup.java:5300)
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
     at android.view.View.layout(View.java:16075)

I think this problem has to do with the Cursor, but I don't know how to start.

Jon Goodwin
  • 9,053
  • 5
  • 35
  • 54
marshallslee
  • 645
  • 1
  • 8
  • 22

1 Answers1

0

Check condition for above line:

if(alarm!=null && alarm.isAlarmActive()!=null && alarm.isAlarmActive()){
 boolean active = alarm.isAlarmActive();
 switchAlarmOnOff.setChecked(active);
}

I hope this code will helpful to you.

dipali
  • 10,966
  • 5
  • 25
  • 51