0

I am new in Android and working on an Android app which can retrieve data from firebase. There is a weird problem. I already successfully implemented the retrieving function for one data model of my program, and I used same codes just changed the variables but it doesn't work for another data model. I did many tests and I think the problem is in FirebaseHelper cuz there is no any data returned from the data snapshot. The error is

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference  

The codes are shown below:

The Activity that shows the retrieved data in a listview.

public class TimeTableActivity extends AppCompatActivity {

    DatabaseReference db;
    FirebaseHelper firebasehelper;
    TimeTableAdapter adapter;
    ListView lv_CourseList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_time_table);

        //GET INTENT
        Intent intent = this.getIntent();
        String majorID = intent.getStringExtra("MAJOR_ID");

        lv_CourseList = (ListView) findViewById(R.id.lv_CourseList);

        //INITIALIZE FIREBASE DB
        db= FirebaseDatabase.getInstance().getReference();
        firebasehelper=new FirebaseHelper(db);

        //ADAPTER
        adapter = new TimeTableAdapter(getApplicationContext(),firebasehelper.retrieveCourse(majorID, new CourseCallbacks() {
                    @Override
                    public void onCourseCallback(ArrayList<CourseInfo> courseInfos) {

                        lv_CourseList.setAdapter(adapter);
                    }
                }));

        lv_CourseList.setAdapter(adapter);
    }
}

FirebaseHelper:

public class FirebaseHelper{

    private DatabaseReference db;
    private ArrayList<Major> majors = new ArrayList<>();
    private ArrayList<CourseInfo> courseInfos = new ArrayList<>();

    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }

    //Save the Major info. into db
    public Boolean saveMajor(Major major)
    {
        Boolean saved = null;
        if(major==null)
        {
            saved =false;
        }else
        {
            try
            {
                db.child("Major").push().setValue(major);
                saved =true;

            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved =false;
            }
        }

        return saved;
    }

    //Save the Course info. into db
    public Boolean saveCourse(CourseInfo courseInfo)
    {
        Boolean saved = null;
        if(courseInfo==null)
        {
            saved =false;
        }else
        {
            try
            {
                db.child("CourseInfo").push().setValue(courseInfo);
                saved =true;

            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved =false;
            }
        }

        return saved;
    }


    public ArrayList<Major> retrieveMajor(final MajorCallbacks majorCallbacks){

        ChildEventListener childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {

                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    Major major = ds.getValue(Major.class);

                    if (major != null && major.getMajor_id() != null) {
                        majors.add(major);
                    }

                }

                majorCallbacks.onMajorCallback(majors);
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {

                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    Major major = ds.getValue(Major.class);

                    if (major != null && major.getMajor_id() != null) {
                        majors.add(major);
                    }
                }
                majorCallbacks.onMajorCallback(majors);

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };

        db.addChildEventListener(childEventListener);

        if (!majors.isEmpty()){
            db.removeEventListener(childEventListener);
        }

        return majors;

    }



    public ArrayList<CourseInfo> retrieveCourse(String majorID, final CourseCallbacks courseCallbacks){

        ChildEventListener childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {

                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    CourseInfo courseInfo = ds.getValue(CourseInfo.class);

                    if (courseInfo != null && courseInfo.getCourse_id() != null) {
                        courseInfos.add(courseInfo);
                    }

                }


                courseCallbacks.onCourseCallback(courseInfos);
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {

                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    CourseInfo courseInfo = ds.getValue(CourseInfo.class);

                    if (courseInfo != null && courseInfo.getCourse_id() != null) {
                        courseInfos.add(courseInfo);
                    }

                }

                courseCallbacks.onCourseCallback(courseInfos);

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };
           db.child("CourseInfo").orderByChild("major_id").equalTo(majorID).addChildEventListener(childEventListener);



        return courseInfos;

    }


}

The retrieveMajor method works well even though it returns many null data and repetitive data, and I used the codes of retrieveMajor in retrieveCourse. It doesn't work, the courseInfos is always null. Even though I changed db.child("CourseInfo").orderByChild("major_id").equalTo(majorID).addChildEventListener(childEventListener);
to
db.addChildEventListener(childEventListener);
,still nothing is retrieved which means the problem is not the query (Probably the query is also wrong).

Adapter:

public class TimeTableAdapter extends BaseAdapter {

    Context context;
    ArrayList<CourseInfo> courseInfos;

    public TimeTableAdapter(Context context, ArrayList<CourseInfo> courseInfos) {
        this.context = context;
        this.courseInfos = courseInfos;
    }

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

    @Override
    public Object getItem(int pos) {
        return courseInfos.get(pos);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {

        LayoutInflater inflater = LayoutInflater.from(context);

        if(convertView == null)
        {
            convertView= LayoutInflater.from(context).inflate(R.layout.model_timetable,viewGroup,false);
        }

        TextView tv_courseid= (TextView) convertView.findViewById(R.id.tv_courseid);
        TextView tv_coursename= (TextView) convertView.findViewById(R.id.tv_coursename);
        TextView tv_courseinstructor= (TextView) convertView.findViewById(R.id.tv_courseinstructor);
        TextView tv_courseavailable= (TextView) convertView.findViewById(R.id.tv_courseavailable);

        final CourseInfo courseInfo= (CourseInfo) this.getItem(position);

        tv_courseid.setText(courseInfo.getCourse_id());
        tv_coursename.setText(courseInfo.getCourse_name());
        tv_courseinstructor.setText(courseInfo.getCourse_instructor());
        tv_courseavailable.setText(courseInfo.getCourse_available());

        return convertView;
    }

}

Data model:

@IgnoreExtraProperties
public class CourseInfo {

    public String course_id;
    public String course_name;
    public int course_section;
    public String course_type;
    public double course_crdhrs;
    public String course_days;
    public String course_times;
    public String course_location;
    public int course_max;
    public int course_cur;
    public int course_available;
    public int course_wl;
    public double course_per;
    public String course_instructor;
    public String course_description;
    public String course_prerequire;
    public String major_id;

    public CourseInfo() {

    }

    public CourseInfo(String course_id, String course_name, int course_section, String course_type, double course_crdhrs, String course_days, String course_times, String course_location, int course_max, int course_cur, int course_available, int course_wl, double course_per, String course_instructor, String course_description, String course_prerequire, String major_id) {
        this.course_id = course_id;
        this.course_name = course_name;
        this.course_section = course_section;
        this.course_type = course_type;
        this.course_crdhrs = course_crdhrs;
        this.course_days = course_days;
        this.course_times = course_times;
        this.course_location = course_location;
        this.course_max = course_max;
        this.course_cur = course_cur;
        this.course_available = course_available;
        this.course_wl = course_wl;
        this.course_per = course_per;
        this.course_instructor = course_instructor;
        this.course_description = course_description;
        this.course_prerequire = course_prerequire;
        this.major_id = major_id;
    }

    public String getCourse_id() {
        return course_id;
    }

    public String getCourse_name() {
        return course_name;
    }

    public int getCourse_section() {
        return course_section;
    }

    public String getCourse_type() {
        return course_type;
    }

    public double getCourse_crdhrs() {
        return course_crdhrs;
    }

    public String getCourse_days() {
        return course_days;
    }

    public String getCourse_times() {
        return course_times;
    }

    public String getCourse_location() {
        return course_location;
    }

    public int getCourse_max() {
        return course_max;
    }

    public int getCourse_cur() {
        return course_cur;
    }

    public int getCourse_available() {
        return course_available;
    }

    public int getCourse_wl() {
        return course_wl;
    }

    public double getCourse_per() {
        return course_per;
    }

    public String getCourse_instructor() {
        return course_instructor;
    }

    public String getCourse_description() {
        return course_description;
    }

    public String getCourse_prerequire() {
        return course_prerequire;
    }

    public String getMajor_id() {
        return major_id;
    }

}

If you need more codes or information, please comment and let me know. I will really appreciate if you can also help me solve the null data and repetitive data problem cuz it makes the listview show many blank and repetitive items.

Haofan Hou
  • 31
  • 2

1 Answers1

0

You cannot return something now that hasn't been loaded yet. With other words, you cannot just simply create a method that as a return type, an ArrayList<Major> and in the same time return that object. This is happening because those methods, onChildAdded(), onChildChanged() and so on, have an asynchronous behaviour, which means that are called even before you are getting/updating the data from/in the database. To solve this, you can move the declaration of that ArrayList inside one method and do what you need to do with it or dive into asynchronous world and use the last part of my answer from this post. You can take also a look at this video for a better understanding.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193