B. Chandresh
B. Chandresh

Reputation: 125

Getting null object reference using MVVM & Firestore

I'm trying to use MVVM in my project for so many days. But unable to achieve it.

My code:

FeedRepository.java

public class FeedsRepository {

private static FeedsRepository instance;

private List<Feed> feedsToAppend = new ArrayList<>();


public static FeedsRepository getInstance() {
    if (instance == null) {
        instance = new FeedsRepository();
    }
    return instance;
}

public MutableLiveData<List<Feed>> getFeeds() {

    MutableLiveData<List<Feed>> mFeeds = new MutableLiveData<>();

    Query query;
    query = feedsRef.whereEqualTo("userID", currentUID).whereEqualTo("not_interested", false)
            .orderBy("created_at", Query.Direction.DESCENDING).limit(10);
    query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {

                QuerySnapshot snapshot = task.getResult();

                if (snapshot.isEmpty()) {

                } else {

                    List<DocumentSnapshot> documents = snapshot.getDocuments();

                    for (DocumentSnapshot doc: documents) {
                        final Feed feed = doc.toObject(Feed.class);
                        feed.setFeedID(doc.getId());
                        feed.setFeedAvailable(true);

                        feedsToAppend.add(feed);
                        System.out.println("Feed: " + feed.getFeedID());
                    }

                    System.out.println("Total feeds to append: " + feedsToAppend.size());
                    mFeeds.setValue(feedsToAppend);

                }

            }
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {

        }
    });

    return mFeeds;

}

HomeViewModel.java

public class HomeViewModel extends ViewModel {

    private MutableLiveData<List<Feed>> mFeeds;
    private FeedsRepository repo;

    public void init() {

        if (mFeeds != null) {
            return;
        }
        repo = FeedsRepository.getInstance();
        mFeeds = repo.getFeeds();
    }

    public LiveData<List<Feed>> getFeeds() {

        return mFeeds;

    }

}

HomeFragment.java

    public View onCreateView(@NonNull LayoutInflater inflater,
                                 ViewGroup container, Bundle savedInstanceState) {
    
        View view = inflater.inflate(R.layout.home_fragment, container, false);

        feedsRecycleView = view.findViewById(R.id.feeds_recycler_view);

        homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
        homeViewModel.init();

        homeViewModel.getFeeds().observe(getViewLifecycleOwner(), new Observer<List<Feed>>() {
            @Override
            public void onChanged(List<Feed> feeds) {
                System.out.println("Feed adapter feeds: "+feeds.size());
                mFeeds = feeds;
                feedAdapter.notifyDataSetChanged();
            }
        });

        List<Feed> testFeeds = homeViewModel.getFeeds().getValue();
        System.out.println("Test feeds are : " + testFeeds.size());

        feedAdapter = new FeedAdapter(getContext(), homeViewModel.getFeeds().getValue());
        feedsRecycleView.setAdapter(feedAdapter);

        feedsRecycleView.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setStackFromEnd(true); //newer posts will be shown on top
        linearLayoutManager.setReverseLayout(true);
        feedsRecycleView.setLayoutManager(linearLayoutManager);

        return view;
    
    }

I get error

"Attempt to invoke interface method 'int java.util.List.size()' on a null object reference"

on this line

List<Feed> testFeeds = homeViewModel.getFeeds().getValue();

and

feedAdapter = new FeedAdapter(getContext(), homeViewModel.getFeeds().getValue());

Please anyone tell me where am I making mistake.

Upvotes: 0

Views: 331

Answers (2)

B. Chandresh
B. Chandresh

Reputation: 125

Okay. I have figured it out.

I had to add this line in FeedsRepository,

 public MutableLiveData<ArrayList<Feed>> getFeeds() {

    MutableLiveData<ArrayList<Feed>> mFeeds = new MutableLiveData<>();
    mFeeds.setValue(feedsToAppend);
    ......

and after fetching records from backend, again

mFeeds.setValue(feedsToAppend);

As the backend process is asynchronous, and would take time to fetch it would return with null object.

Upvotes: 0

Alex Mamo
Alex Mamo

Reputation: 138969

You are getting the following error:

"Attempt to invoke interface method 'int java.util.List.size()' on a null object reference"

Most likely at this particular line of code:

System.out.println("Test feeds are : " + testFeeds.size());

And this is because your testFeeds object is null, meaning that:

homeViewModel.getFeeds().getValue();

Return null. This also means that getValue() method returns a LiveData object that is null, which is indeed the case as in your HomeViewModel class the getFeeds() method returns a LiveData object which is never initialized. To solve this, please change the following line of code:

private MutableLiveData<List<Feed>> mFeeds

to

private MutableLiveData<List<Feed>> mFeeds = new MutableLiveData<>();

Upvotes: 1

Related Questions