Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe on a null object reference

Viewed 25536

I am getting the following error

I am using Android architecture components and tried to instantiate viewmodel and Observe data from LiveData. But im stuck here please help me solve this issue :

Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe(android.arch.lifecycle.LifecycleOwner, android.arch.lifecycle.Observer)' on a null object reference

My Fragment is this : While calling getCompany() method im getting and NullPoint Exception Error

    public class CompanyFragment extends LifecycleFragment {
    private CompanyViewModel companyViewModel;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        companyViewModel = ViewModelProviders.of(this).get(CompanyViewModel.class);
        companyViewModel.initData();
        companyViewModel.getCompany().observe(this, new Observer<CompanyEntity>() {
            @Override
            public void onChanged(@Nullable CompanyEntity companyEntity) {

            }
        });
    }
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_company, container, false);
    }
}

My ViewModel class is this :

public class CompanyViewModel extends ViewModel {
    private LiveData<CompanyEntity> companyEntityLiveData;
    private CompanyRepository companyRepo;

    public CompanyViewModel() {}

    public CompanyViewModel(CompanyRepository companyRepo){
        this.companyRepo = companyRepo;
    }

    public void initData(){
        companyEntityLiveData = companyRepo.getCompany();
    }

    public LiveData<CompanyEntity> getCompany() {
        return companyEntityLiveData;
    }

}

Error is at this line :

   companyViewModel.getCompany().observe(this, new Observer<CompanyEntity>() {
        @Override
        public void onChanged(@Nullable CompanyEntity companyEntity) {

        }
    });

This is my CompanyRepository class:

public class CompanyRepository {
private WebService webService;

    public CompanyRepository(){

    }

    public LiveData<CompanyEntity> getCompany() {
        final MutableLiveData<CompanyEntity> data = new MutableLiveData<>();

        webService.getCompany().enqueue(new Callback<CompanyEntity>() {
            @Override
            public void onResponse(Call<CompanyEntity> call, Response<CompanyEntity> response) {
                data.setValue(response.body());
            }

            @Override
            public void onFailure(Call<CompanyEntity> call, Throwable t) {

            }
        });

        return data;
    }
}
5 Answers

You must observe the same instance of your LiveData. In your CompanyRepository class you create a new LiveData instance every time you access the company, which means your activity is then observing an old instance.

The getCompany method should be changed to always return the same instance of the LiveData. Also, you should change setValue() to postValue() because you are trying to update the value on a background thread.

final MutableLiveData<CompanyEntity> data = new MutableLiveData<>();
public LiveData<CompanyEntity> getCompany() {

    webService.getCompany().enqueue(new Callback<CompanyEntity>() {
        @Override
        public void onResponse(Call<CompanyEntity> call, Response<CompanyEntity> response) {
            data.postValue(response.body());
        }

        @Override
        public void onFailure(Call<CompanyEntity> call, Throwable t) {

        }
    });

    return data;
}

Maybe You can have declared a LiveData object after the method.

That's what happened to me in my case.

fun aMethod() {
    _aLiveData.value = Unit
}

private val _aLiveData = MutableLiveData<Unit>()
val aLiveData: LiveData<Unit> = _aLiveData

In fact, it should have been as follows.

private val _aLiveData = MutableLiveData<Unit>()
val aLiveData: LiveData<Unit> = _aLiveData

fun aMethod() {
    _aLiveData.value = Unit
}

Change

public CompanyViewModel(){
    companyRepo= new companyRepo();
}

public LiveData<CompanyEntity> getCompany() {
    if(companyEntityLiveData==null)
        companyEntityLiveData= companyRepo.getSection();
    return companyEntityLiveData;
}

And in your Fragment:

    CompanyViewModel companyViewModel= 
    ViewModelProviders.of(this).get(CompanyViewModel .class);
    LiveData<CompanyEntity> s = companyViewModel.getCompany();

    s.observe(this, new Observer<CompanyEntity>() {
        @Override
        public void onChanged(@Nullable CompanyEntity companyEntity) {
            Toast.makeText(getContext(),"Go go go", Toast.LENGTH_LONG).show();
        }
    });

The problem is that you are trying to use something that has not been initialized. So in order not to depend on the order of execution, we must establish a safe nulability in the variable that stores what the repository returns private val nullableObj: LiveData<T2>?

With this we could use the property even before the repository has loaded it. Check the order of execution in the following example:

val aUse: LiveData<T> = MediatorLiveData<T>().apply {
    nullableObj?.let {
    }
}
private val nullableObj: LiveData<T2>? = repository::getNullableObj

Answering your question before using Repository #getCompany() check the nullability. In Kotlin:

companyVM.company?.observe(...) { ... }

GL

Related