NullPointerException when i want to GET my data from my model class - java

In my Application in android i want to GET data from my web service to my recycle view, instead i got my data i got an error, here is my code
public class UserMenuActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_menu);
retrofit = new Retrofit.Builder().baseUrl("http://172.31.32.17:9290/")
.addConverterFactory(GsonConverterFactory.create())
.build();
afs = retrofit.create(AdminFullService.class);
responseLoginHome = (ResponseLoginHome) getIntent().getSerializableExtra("data");
initViews();
getCustomer = new getCustomer();
}
private void initViews() {
recyclerViewCustomer = (RecyclerView) findViewById(R.id.recycler_view_user_menu);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerViewCustomer.setLayoutManager(layoutManager);
recyclerViewCustomer.setHasFixedSize(true);
adapterCustomer = new DataAdapterCustomer(this, getCustomerList);
loadData();
}
private void loadData() {
Call<ResponseCustomerData> callCustomer = afs.customerDataView("bearer " + responseLoginHome.getData().getAuth_token());
callCustomer.enqueue(new Callback<ResponseCustomerData>() {
#Override
public void onResponse(Call<ResponseCustomerData> call, Response<ResponseCustomerData> response) {
ResponseCustomerData responseCustomerData = response.body();
getCustomerList.clear();
getCustomerList.addAll(responseCustomerData.getData()); //this is where i got error in my logcat
recyclerViewCustomer.setAdapter(adapterCustomer);
adapterCustomer.notifyDataSetChanged();
getCustomer.getTanggalLahir().substring(0,10);
Toast.makeText(UserMenu.this, getCustomer.getTanggalLahir(), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ResponseCustomerData> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
}
and i have got this error
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.example.ipul.aprovementfullservice.Model.ResponseCustomerData.getData()' on a null object reference
at com.example.ipul.aprovementfullservice.UI.UserMenu$1.onResponse(UserMenu.java:77)
when i use my debug mode the responseCustomerData is null, and then i got confused why i got error like this, i create my model response just like my web service ask
sorry for bad grammar, English is not my native language
So i hope you all hand me your help, thank you
EDIT this is my list getCustomer
public class getCustomer{
public String getNoHP() {
return noHP;
}
public void setNoHP(String noHP) {
this.noHP = noHP;
}
public String getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(String registrationDate) {
this.registrationDate = registrationDate;
}
public String getNama() {
return nama;
}
public void setNama(String nama) {
this.nama = nama;
}
public String getNoID() {
return noID;
}
public void setNoID(String noID) {
this.noID = noID;
}
public String getJenisID() {
return jenisID;
}
public void setJenisID(String jenisID) {
this.jenisID = jenisID;
}
public String getTanggalLahir() {
return tanggalLahir;
}
public void setTanggalLahir(String tanggalLahir) {
this.tanggalLahir = tanggalLahir;
}
public String getJenisKelamin() {
return jenisKelamin;
}
public void setJenisKelamin(String jenisKelamin) {
this.jenisKelamin = jenisKelamin;
}
public String getNamaIbuKandung() {
return namaIbuKandung;
}
public void setNamaIbuKandung(String namaIbuKandung) {
this.namaIbuKandung = namaIbuKandung;
}
public String getAlamat() {
return alamat;
}
public void setAlamat(String alamat) {
this.alamat = alamat;
}
public String getProvinsi() {
return provinsi;
}
public void setProvinsi(String provinsi) {
this.provinsi = provinsi;
}
public String getKota() {
return kota;
}
public void setKota(String kota) {
this.kota = kota;
}
public String getKecamatan() {
return kecamatan;
}
public void setKecamatan(String kecamatan) {
this.kecamatan = kecamatan;
}
public String getKelurahan() {
return kelurahan;
}
public void setKelurahan(String kelurahan) {
this.kelurahan = kelurahan;
}
public String getKodepos() {
return kodepos;
}
public void setKodepos(String kodepos) {
this.kodepos = kodepos;
}
public String getAlamatDomosili() {
return alamatDomosili;
}
public void setAlamatDomosili(String alamatDomosili) {
this.alamatDomosili = alamatDomosili;
}
public String getProvinsiDomisili() {
return provinsiDomisili;
}
public void setProvinsiDomisili(String provinsiDomisili) {
this.provinsiDomisili = provinsiDomisili;
}
public String getKotaDomisili() {
return kotaDomisili;
}
public void setKotaDomisili(String kotaDomisili) {
this.kotaDomisili = kotaDomisili;
}
public String getKecamatanDomisili() {
return kecamatanDomisili;
}
public void setKecamatanDomisili(String kecamatanDomisili) {
this.kecamatanDomisili = kecamatanDomisili;
}
public String getKelurahanDomisili() {
return kelurahanDomisili;
}
public void setKelurahanDomisili(String kelurahanDomisili) {
this.kelurahanDomisili = kelurahanDomisili;
}
public String getKodeposDomisili() {
return kodeposDomisili;
}
public void setKodeposDomisili(String kodeposDomisili) {
this.kodeposDomisili = kodeposDomisili;
}
public String getFotoID() {
return fotoID;
}
public void setFotoID(String fotoID) {
this.fotoID = fotoID;
}
public String getRegisterStatus() {
return registerStatus;
}
public void setRegisterStatus(String registerStatus) {
this.registerStatus = registerStatus;
}
public String getKeterangan() {
return keterangan;
}
public void setKeterangan(String keterangan) {
this.keterangan = keterangan;
}
public String getFotoTandaTangan() {
return fotoTandaTangan;
}
public void setFotoTandaTangan(String fotoTandaTangan) {
this.fotoTandaTangan = fotoTandaTangan;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
and this my model ResponseCustomerData
public class ResponseCustomerData{
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public List<getCustomer> getData() {
return data;
}
public void setData(List<getCustomer> data) {
this.data = data;
}
}

Please try this, you have to check if your response is null or not.
Call<ResponseCustomerData> callCustomer = afs.customerDataView("bearer " + responseLoginHome.getData().getAuth_token());
callCustomer.enqueue(new Callback<ResponseCustomerData>() {
#Override
public void onResponse(Call<ResponseCustomerData> call, Response<ResponseCustomerData> response) {
ResponseCustomerData responseCustomerData = response.body();
getCustomerList.clear();
if(responseCustomerData!=null){ // check data retrive or not
if(responseCustomerData.getData()!=null){
getCustomerList.addAll(responseCustomerData.getData());
recyclerViewCustomer.setAdapter(adapterCustomer);
adapterCustomer.notifyDataSetChanged();
getCustomer.getTanggalLahir().substring(0,10);
Toast.makeText(UserMenu.this, getCustomer.getTanggalLahir(), Toast.LENGTH_SHORT).show();
} else {
Log.d("Error", responseCustomerData.getError());
}
}
}
#Override
public void onFailure(Call<ResponseCustomerData> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});

Related

Retrieve data from Firebase with complex model and print it inside adapter

How can i get branch Choix from Sondage and print it into my Adapter class.
Here's my ModelClass
AccueilItem
public class AccueilItem {
private String idSondage;
private String publisher;
private String titreSondage;
private ArrayList<ChoixItem> choix;
public AccueilItem() {
}
public AccueilItem(String idSondage, String publisher, String titreSondage, ArrayList<ChoixItem> choix) {
this.idSondage = idSondage;
this.publisher = publisher;
this.titreSondage = titreSondage;
this.choix = choix;
}
public String getIdSondage() {
return idSondage;
}
public void setIdSondage(String idSondage) {
this.idSondage = idSondage;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String getTitreSondage() {
return titreSondage;
}
public void setTitreSondage(String titreSondage) {
this.titreSondage = titreSondage;
}
public ArrayList<ChoixItem> getChoix() {
return choix;
}
public void setChoix(ArrayList<ChoixItem> choix) {
this.choix = choix;
}
}
ChoixItem
public class ChoixItem extends ArrayList<ChoixItem> {
private String idChoix;
private String titreChoix;
public ChoixItem() {
}
public ChoixItem(String idChoix, String titreChoix) {
this.idChoix = idChoix;
this.titreChoix = titreChoix;
}
public String getIdChoix() {
return idChoix;
}
public void setIdChoix(String idChoix) {
this.idChoix = idChoix;
}
public String getTitreChoix() {
return titreChoix;
}
public void setTitreChoix(String titreChoix) {
this.titreChoix = titreChoix;
}
}
Inside my main class, I retreive my data successfully, but i can't get the branch Choix to print it
AcceilActivity
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
accueilItems.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
AccueilItem accueilModel = dataSnapshot.getValue(AccueilItem.class);
accueilItems.add(accueilModel);
}
accueilAdapter = new AccueilAdapter(AccueilActivity.this, (ArrayList<AccueilItem>) accueilItems);
recyclerView.setAdapter(accueilAdapter);
accueilAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(AccueilActivity.this, "Error:" + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
If anyone can help, I would be so grateful, i'm suck in this for 2 days.

In paging library, PagedList value is null

I have tried to implement a user list with pagination using paging library. But despite being able to fetch all data from back-end, the PagedList is null while observing LiveData.
Here are the codes.
UserModel.java
class User{
#SerializedName("user_id")
public int user_id;
#SerializedName("username")
public String username;
#SerializedName("name")
public String name;
#SerializedName("familyname")
public String familyname;
#SerializedName("pp_dir")
public String pp_url; }
public class UserModel {
#SerializedName("users")
public List<User> list;
#SerializedName("last_page")
public boolean lastPage;
#SerializedName("total_page")
public int totalPage;
#SerializedName("total_user_count")
public int totalUserCount;}
UserSearchDataSource.java
public class UserSearchDataSource extends ItemKeyedDataSource<Integer, User> {
public static final int PAGE_SIZE = 15;
private static final int FIRST_PAGE = 1;
#Override
public void loadInitial(#NonNull LoadInitialParams<Integer> params, #NonNull LoadInitialCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
callback.onResult(response.body().list);
System.out.println(response.body().list);
}
else {
System.out.println(response.code());
System.out.println(response.message());
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
System.out.println(t.getMessage());
}
});
}
#Override
public void loadAfter(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
//Integer key = response.body().lastPage ? null : params.key + 1;
callback.onResult(response.body().list);
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
//Integer key = (params.key > 1) ? params.key - 1 : null;
callback.onResult(response.body().list);
}
else {
System.out.println(response.message());
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
System.out.println(t.getMessage());
}
});
}
#NonNull
#Override
public Integer getKey(#NonNull User item) {
return item.user_id;
} }
UserSearchDataSourceFactory.java
public class UserSearchDataSourceFactory extends DataSource.Factory<Integer, User> {
private MutableLiveData<UserSearchDataSource> userLiveDataSource = new MutableLiveData<>();
public UserSearchDataSourceFactory() {
}
#NonNull
#Override
public DataSource<Integer, User> create() {
UserSearchDataSource dataSource = new UserSearchDataSource();
userLiveDataSource.postValue(dataSource);
return dataSource;
}
public MutableLiveData<UserSearchDataSource> getUserLiveDataSource() {
return userLiveDataSource;
} }
UserSearchAdapter.java
public class UserSearchAdapter extends PagedListAdapter<User, UserSearchAdapter.ViewHolder> {
private Context context;
UserSearchAdapter(Context context) {
super(DIFF_CALLBACK);
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.user_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
User model = getItem(position);
if (model != null) {
Picasso.get().load(model.pp_url).into(holder.userPp);
holder.tvUsername.setText(model.username);
holder.tvFullname.setText(model.name.concat(" ").concat(model.familyname));
}
else {
Toast.makeText(context, "Item is null", Toast.LENGTH_LONG).show();
}
}
private static DiffUtil.ItemCallback<User> DIFF_CALLBACK = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User oldItem, #NonNull User newItem) {
return oldItem.user_id == newItem.user_id;
}
#SuppressLint("DiffUtilEquals")
#Override
public boolean areContentsTheSame(#NonNull User oldItem, #NonNull User newItem) {
return oldItem.equals(newItem);
}
};
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView userPp;
TextView tvUsername, tvFullname;
public ViewHolder(#NonNull View itemView) {
super(itemView);
userPp = itemView.findViewById(R.id.image_user);
tvUsername = itemView.findViewById(R.id.tv_username);
tvFullname = itemView.findViewById(R.id.tv_fullname);
}
} }
UserSearchViewModel.java
public class UserSearchViewModel extends AndroidViewModel {
private LiveData<PagedList<User>> userPagedList;
LiveData<UserSearchDataSource> liveDataSource;
public UserSearchViewModel(Application application) {
super(application);
}
public LiveData<PagedList<User>> getUserPagedList() {
UserSearchDataSourceFactory userSearchDataSourceFactory = new UserSearchDataSourceFactory();
liveDataSource = userSearchDataSourceFactory.getUserLiveDataSource();
PagedList.Config config = (new PagedList.Config.Builder())
.setEnablePlaceholders(true)
.setPageSize(UserSearchDataSource.PAGE_SIZE)
.build();
userPagedList = new LivePagedListBuilder<>(userSearchDataSourceFactory, config).build();
return userPagedList;
} }
UserSearchFragment.java
mViewModel.getUserPagedList().observe(this, (PagedList<User> users) -> {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
adapter = new UserSearchAdapter(getContext());
adapter.submitList(users);
recyclerView.setAdapter(adapter);
//System.out.println(users.get(0).name);
});

Nested callback is too deep

How to replace nested callbacks (Testing.java) for easy reading like this:
if(isValidGenderID() && isValidReligionID() && isValidMaritalID()){
// DO PRIMARY TASK
}
Nested callbacks are too deep, making the program not easy to read!. How to resolved this problem?
//PersonValidation.java
public static void isValidGenderID(#NonNull Context context, int genderID, final IGenderDataSource.IIsExistGenderIDCallback callback) {
GenderDataSource.getInstance(context).isExistGenderID(genderID, new IGenderDataSource.IIsExistGenderIDCallback() {
#Override
public void onSuccess(boolean result) {
callback.onSuccess(result);
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
}
public static void isValidReligionID(#NonNull Context context, int religionID, final IReligionDataSource.IIsExistReligionIDCallback callback) {
ReligionDataSource.getInstance(context).isExistReligionID(religionID, new IReligionDataSource.IIsExistReligionIDCallback() {
#Override
public void onSuccess(boolean result) {
callback.onSuccess(result);
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
}
public static void isValidMaritalID(#NonNull Context context, int maritalID, final IMaritalDataSource.IIsExistMaritalIDCallback callback) {
MaritalDataSource.getInstance(context).isExistMaritalID(maritalID, new IMaritalDataSource.IIsExistMaritalIDCallback() {
#Override
public void onSuccess(boolean result) {
callback.onSuccess(result);
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
}
// GenderDataSource.java
#Override
public void isExistGenderID(final int ID, #NonNull final IIsExistGenderIDCallback callback) {
Runnable r = new Runnable() {
#Override
public void run() {
db.sqlRawQuery();
callback.onSuccess();
}
};
appExecutors.getLocalDb().execute(r);
}
// ReligionDataSource.java
#Override
public void isExistReligionID(final int ID, #NonNull final IIsExistReligionIDCallback callback) {
Runnable r = new Runnable() {
#Override
public void run() {
db.sqlRawQuery();
callback.onSuccess();
}
};
appExecutors.getLocalDb().execute(r);
}
// MaritalDataSource.java
#Override
public void isExistMaritalID(final int ID, #NonNull final IIsExistMaritalIDCallback callback) {
Runnable r = new Runnable() {
#Override
public void run() {
db.sqlRawQuery();
callback.onSuccess();
}
};
appExecutors.getLocalDb().execute(r);
}
// Testing.java (Nested calls are too deep, making the program not easy to read)
#Override
public void createCustomer(#NonNull final Customer customer, #NonNull final ICustomerDataSource.ICreateCustomerCallback callback) {
//
// isValidGenderID?
//
isValidGenderID(context, customer.getGenderID(), new IGenderDataSource.IIsExistGenderIDCallback() {
#Override
public void onSuccess(boolean result) {
if (result) {
//
// isValidReligionID?
//
isValidReligionID(context, customer.getReligionID(), new IReligionDataSource.IIsExistReligionIDCallback() {
#Override
public void onSuccess(boolean result) {
if (result) {
//
// isValidMaritalID?
//
isValidMaritalID(context, customer.getMaritalID(), new IMaritalDataSource.IIsExistMaritalIDCallback() {
#Override
public void onSuccess(boolean result) {
if (result) {
//
// DO PRIMARY TASK
//
} else {
callback.onFailure("Marital is not valid");
}
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
//
} else {
callback.onFailure("Religion is not valid!");
}
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
//
} else {
callback.onFailure("Gender is not valid!");
}
}
#Override
public void onFailure(String result) {
callback.onFailure(result);
}
});
}

How to fill the RecyclerView with nested object from firebase

This is the event object that I want to inflate with RecyclerView:
public class Event {
private String mName;
private String mId;
private String mDate;
private String mPlace;
private User mUser;
private Category mCat;
private String mDescription;
public void setmEventCat(Map<String, Category> mEventCat) {
this.mEventCat = mEventCat;
}
public Map<String, Category> getmEventCat() {
return mEventCat;
}
private Map<String,Category> mEventCat;
public String getmDescription() {
return mDescription;
}
public void setDescription(String mDescription) {
this.mDescription = mDescription;
}
public Category getCat() {
return mCat;
}
public void setCat(Category mCat) {
this.mCat = mCat;
}
public String getDate() {
return mDate;
}
public String getPlace() {
return mPlace;
}
private ArrayList<User> mList;
public Event() {
}
public String getName() {
return mName;
}
public void setName(String mName) {
this.mName = mName;
}
public void setDate(String mDate) {
this.mDate = mDate;
}
public void setPlace(String mPlace) {
this.mPlace = mPlace;
}
public String getId() {
return mId;
}
public void setId(String mId) {
this.mId = mId;
}
}
The nested Category object:
public class Category implements Serializable{
private String mCatName;
private String mCatID;
public Category() {
}
public Category(String mCatName) {
this.mCatName = mCatName;
}
public String getCatName() {
return mCatName;
}
public String getCatID() {
return mCatID;
}
public void setCatName(String mCatName) {
this.mCatName = mCatName;
}
public void setCatID(String mCatID) {
this.mCatID = mCatID;
}
}
How I retrieve the data from firebase:
mDataBase = FirebaseDatabase.getInstance().getReference("Event");
mEvents = new ArrayList<Event>();
mEvent=new Event();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mDataBase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
Event event = eventSnapshot.getValue(Event.class);
String id = eventSnapshot.getKey();
mEvents.add(event);
mRecyclerView.scrollToPosition(mEvents.size() - 1);
mAdapter.notifyItemInserted(mEvents.size() - 1);
}
}
catch (Exception ex) {
Log.e("ERROR", ex.getMessage());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mAdapter = new EventAdapter(mContext, mEvents);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
My EventAdapter:
#Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
mEvent = mEvents.get(position);
holder.mEventName.setText(mEvent.getName());
//Every time I tried to add this line to set category name
//the NullPointerException error occurs
holder.mEventCategory.setText(mEvent.getCat().getCatName());
holder.mEventDate.setText(mEvent.getDate());
}
The ViewHolder Class:
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mEventName, mEventDate,mEventCategory;
public ViewHolder(View itemView) {
super(itemView);
mEventName = itemView.findViewById(R.id.eventName_tv);
mEventDate = itemView.findViewById(R.id.date_tv);
mEventCategory = itemView.findViewById(R.id.categoryTv);
}
}
#Override
public EventAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_event, parent, false);
return new ViewHolder(view);
}
The problem is the Event is displayed as I expected, but I cannot get the category inside the event and bind it to my widget by simply calling the getCat(). I know this may caused by asynchronous Firebase API. How can I set up the TextView with the nested category object.
This is my FINAL piece of my application, any hints would be a great help.
Thanks in advance!
I figure out the question that may be useful for other people. Before adding the event object to the list, I retrieve the nested object by key and assign it to category object. Finally, linking it with event...
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
Event event = eventSnapshot.getValue(Event.class);
String id = eventSnapshot.getKey();
mCategory = eventSnapshot.child(id).getValue(Category.class);
event.setCat(mCategory);
mEvents.add(event);
mRecyclerView.scrollToPosition(mEvents.size() - 1);
mAdapter.notifyItemInserted(mEvents.size() - 1);
}
}
catch (Exception ex) {
Log.e("ERROR", ex.getMessage());
}
}
}
Then binding the desired data with widget by calling the pojo getter method (nothing's changed here).
#Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
mEvent = mEvents.get(position);
holder.mEventName.setText(mEvent.getName());
holder.mEventCategory.setText(mEvent.getCat().getCatName());
holder.mEventDate.setText(mEvent.getDate());
}

java.lang.NullPointerException error on Retrofit onResponse

Good day, I'm using Retrofit for the first time and I can't seem to get it to work. working on an app that get crypto currency rates in local currencies, here is the api link, JSON format
{
"BTC": {
"USD": 6019.1,
"EUR": 5139.44,
"NGN": 2136243.25
},
"ETH": {
"USD": 290.98,
"EUR": 250.03,
"NGN": 103031.01
}
}
Here are my models (from http://www.jsonschema2pojo.org/): UPDATED
public class CryptoCurrency {
#SerializedName("BTC")
#Expose
private BTC BTC;
#SerializedName("ETH")
#Expose
private ETH ETH;
public BTC getBTC() {
return BTC;
}
public void setBTC(BTC BTC) {
this.BTC = BTC;
}
public ETH getETH() {
return ETH;
}
public void setETH(ETH ETH) {
this.ETH = ETH;
}
public class BTC {
#SerializedName("USD")
#Expose
private Double USD;
#SerializedName("EUR")
#Expose
private Double EUR;
#SerializedName("NGN")
#Expose
private Double NGN;
public Double getUSD() {
return USD;
}
public void setUSD(Double USD) {
this.USD = USD;
}
public Double getEUR() {
return EUR;
}
public void setEUR(Double EUR) {
this.EUR = EUR;
}
public Double getNGN() {
return NGN;
}
public void setNGN(Double NGN) {
this.NGN = NGN;
}
}
public class ETH {
#SerializedName("USD")
#Expose
private Double USD;
#SerializedName("EUR")
#Expose
private Double EUR;
#SerializedName("NGN")
#Expose
private Double NGN;
public Double getUSD() {
return USD;
}
public void setUSD(Double USD) {
this.USD = USD;
}
public Double getEUR() {
return EUR;
}
public void setEUR(Double EUR) {
this.EUR = EUR;
}
public Double getNGN() {
return NGN;
}
public void setNGN(Double NGN) {
this.NGN = NGN;
}
}
}
My interface:
public interface CurrencyInterface {
#GET("/data/pricemulti/")
Call<CryptoCurrency.BTC> currency(#Query("crypto") String crypto, #Query("local") String local);
}
my onResponse method:
call.enqueue(new Callback<CryptoCurrency.BTC>() {
#Override
public void onResponse(Call<CryptoCurrency.BTC> call, Response<CryptoCurrency.BTC> response) {
String currency = response.body().toString();
Toast.makeText(getApplicationContext(), "result " + currency, Toast.LENGTH_LONG).show();
Log.i("MainActivity", currency);
}
#Override
public void onFailure(Call<CryptoCurrency.BTC> call, Throwable t) {
}
});
When I run the code and check my log I get this error:
java.lang.NullPointerException
at com.example.raynold.cryptorates.MainActivity$1.onResponse(MainActivity.java:53)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
UPDATED---------
My MainActivity class
public class MainActivity extends AppCompatActivity {
private RecyclerView mCurrencyRecycler;
private Button mclickMe;
private CurrencyAdapter mCurrencyAdapter;
private List<CryptoCurrency> mCurrencyList;
private CurrencyInterface mCurrencyInterface;
private LinearLayoutManager mLinearLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCurrencyRecycler = (RecyclerView) findViewById(R.id.rv_rates);
mLinearLayoutManager = new LinearLayoutManager(this);
mCurrencyRecycler.setLayoutManager(mLinearLayoutManager);
mCurrencyRecycler.setHasFixedSize(true);
mclickMe = (Button) findViewById(R.id.click_me);
mCurrencyInterface = ApiClient.getApiClient().create(CurrencyInterface.class);
Call<CryptoCurrency.BTC> call = mCurrencyInterface.currency("BTC", "NGN");
call.enqueue(new Callback<CryptoCurrency.BTC>() {
#Override
public void onResponse(Call<CryptoCurrency.BTC> call, Response<CryptoCurrency.BTC> response) {
String currency = response.body().toString();
Toast.makeText(getApplicationContext(), "result " + currency, Toast.LENGTH_LONG).show();
Log.i("MainActivity", currency);
}
#Override
public void onFailure(Call<CryptoCurrency.BTC> call, Throwable t) {
}
});
mclickMe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
I will also like to know how i can get it to work with a recyclerview since the JSON is of object type not Array.
public class CryptoCurrency {
#SerializedName("BTC")
#Expose
private BTC BTC;
#SerializedName("ETH")
#Expose
private ETH ETH;
public BTC getBTC() {
return BTC;
}
public void setBTC(BTC BTC) {
this.BTC = BTC;
}
public ETH getETH() {
return ETH;
}
public void setETH(ETH ETH) {
this.ETH = ETH;
}
class ETH {
...
}
class BTC {
...
}
}
In your interface CurrencyInterface use like
#GET("/data/pricemulti")
Call<CryptoCurrency> currency(#Query("fsyms") String crypto, #Query("tsyms") String local);
Handle like
Call<CryptoCurrency> call = mCurrencyInterface.currency("BTC", "NGN");
call.enqueue(new Callback<CryptoCurrency>() {
#Override
public void onResponse(Call<CryptoCurrency> call, Response<CryptoCurrency> response) {
BTC btc = response.body().getBTC();
Toast.makeText(getApplicationContext(), "result " + btc.getNGN(), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<CryptoCurrency.BTC> call, Throwable t) {
}
});
You should not use backslash at the start and end of URLs.
Try
#GET("data/pricemulti")
instead of
#GET("/data/pricemulti/")
Change your onResponse method like this:
...........
call.enqueue(new Callback<CryptoCurrency.BTC>() {
#Override
public void onResponse(Call<CryptoCurrency.BTC> call, Response<CryptoCurrency.BTC> response) {
String currency = response.getUSD().toString();
Toast.makeText(getApplicationContext(), "result " + currency, Toast.LENGTH_LONG).show();
Log.i("MainActivity", currency);
}
#Override
public void onFailure(Call<CryptoCurrency.BTC> call, Throwable t) {
}
});
Try this solve your issue.
check if response.body() not null before this line
String currency = response.body().toString();
if response code not equal 200 your response will be null

Categories

Resources