Reputation: 76
I'm facing a problem on my android programming, I have an app that needs run some routines like scan some barcode. Once that I scanned a barcode I will send the data of this barcode to my API, "wait" to get some information and after that do another things.
The problem it's when I call my API to get the information and after I try to use the information that was supposed to come from the API, I'm falling on a NULL Exception, see the code below:
My scan routine that is called every time I scan a barcode:
// 1 - First Stage: Scan barcode of tank
if(stageScannerTank == 1)
{
// Verify if the user scanned the correct Tank
if (!resultScan.equals(expectedTank)) {
Toast.makeText(getContext(), "Wrong Tank, scan the correct ", Toast.LENGTH_LONG).show();
stageScannerTank = 0;
return;
}
// Get the tank information
//new TanqueTask().execute(resultScan);
**HERE IS MY PROBLEM, When I call the function below, I fill my tankMixPlant with data**
getTankMixPlant(resultScan);
** I always fall into this IF **
// If null information
if(tankMixPlant == null) {
Toast.makeText(getContext(), "Error to read tank information", Toast.LENGTH_LONG).show();
return;
}
}
getTankMixPlant, using Retrofit to call my service, it is working if I test out of my routine:
private void getTankMixPlant(String tankName){
mService.getTankMixPlant(tankName).enqueue(new Callback<TankMixPlant>() {
@Override
public void onResponse(Call<TankMixPlant> call, Response<TankMixPlant> response) {
tankMixPlant = response.body();
}
@Override
public void onFailure(Call<TankMixPlant> call, Throwable t) {
// On failure show the error message to the User
AlertDialog alert;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Error");
builder.setMessage("Error: " + t.getMessage());
alert = builder.create();
alert.show();
}
});
}
How can I wait tankMixPlant be filled up with data to continue my routine?
UPDATES:
I continue with the problem, but I changed some things that you can see below: Now I get NullPointerException.
Now I verify if my object is null inside the onResponse method:
private void getTankMixPlant(String tankName){
mService.getTankMixPlant(tankName).enqueue(new Callback<TankMixPlant>() {
@Override
public void onResponse(Call<TankMixPlant> call, Response<TankMixPlant> response) {
tankMixPlant = response.body();
if(tankMixPlant == null) {
Toast.makeText(getContext(), "Error to read tank information",
Toast.LENGTH_LONG).show();
return;
}
}
@Override
public void onFailure(Call<TankMixPlant> call, Throwable t) {
// On failure show the error message to the User
AlertDialog alert;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Error");
builder.setMessage("Error: " + t.getMessage());
alert = builder.create();
alert.show();
}
});
}
But when I try to verify some information about tankMixPlant:
// Verify tank stage
if(!tankMixPlant.getBlenderCode().equals("0") && tankMixPlant.getIngr() == 1)
{
getPackages(tankMixPlant.getRecipeNumber(), tankMixPlant.getBlenderCode(), tankMixPlant.getTankName());
// 2 - Mix Packages: Scan package barcode
stageScannerTank = 2;
}
if(!tankMixPlant.getIngrSAPNumber().equals("0") && tankMixPlant.getIngr() == 1)
{
getIngr(tankMixPlant.getRecipeNumber(), tankMixPlant.getTankName());
// 3 - P.I Packages: Scan package barcode
stageScannerTank = 3;
}
My app crashes with this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.labtse.kibonapp, PID: 21519
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=114910, result=-1, data=Intent { act=com.google.zxing.client.android.SCAN flg=0x80000 VirtualScreenParam=Params{mDisplayId=-1, null, mFlags=0x00000000)} (has extras) }} to activity {com.example.labtse.kibonapp/com.example.labtse.kibonapp.TabPagesActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.labtse.kibonapp.model.TankMixPlant.getBlenderCode()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:5007)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5050)
at android.app.ActivityThread.access$1600(ActivityThread.java:230)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1876)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7409)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.labtse.kibonapp.model.TankMixPlant.getBlenderCode()' on a null object reference
at com.example.labtse.kibonapp.MixPlantFragment.scanRoutine(MixPlantFragment.java:367)
at com.example.labtse.kibonapp.MixPlantFragment.onActivityResult(MixPlantFragment.java:399)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7165)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5003)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5050)
at android.app.ActivityThread.access$1600(ActivityThread.java:230)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1876)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7409)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
My tankMixPlant class:
package com.example.labtse.kibonapp.model;
public class TankMixPlant {
private String tankName;
private String recipeNumber;
private int idBatch;
private String ingrSAPNumber;
private String blenderCode;
private short ingr;
private boolean QRUN;
private boolean QEND;
private Boolean QDOSANDO;
private Boolean CONF_ING;
public TankMixPlant() {
}
public String getTankName() {
return tankName;
}
public void setTankName(String tankName) {
this.tankName = tankName;
}
public String getRecipeNumber() {
return recipeNumber;
}
public void setRecipeNumber(String recipeNumber) {
this.recipeNumber = recipeNumber;
}
public int getIdBatch() {
return idBatch;
}
public void setIdBatch(int idBatch) {
this.idBatch = idBatch;
}
public String getIngrSAPNumber() {
return ingrSAPNumber;
}
public void setIngrSAPNumber(String ingrSAPNumber) {
this.ingrSAPNumber = ingrSAPNumber;
}
public String getBlenderCode() {
return blenderCode;
}
public void setBlenderCode(String blenderCode) {
this.blenderCode = blenderCode;
}
public short getIngr() {
return ingr;
}
public void setIngr(short ingr) {
this.ingr = ingr;
}
public boolean isQRUN() {
return QRUN;
}
public void setQRUN(boolean QRUN) {
this.QRUN = QRUN;
}
public boolean isQEND() {
return QEND;
}
public void setQEND(boolean QEND) {
this.QEND = QEND;
}
public Boolean getQDOSANDO() {
return QDOSANDO;
}
public void setQDOSANDO(Boolean QDOSANDO) {
this.QDOSANDO = QDOSANDO;
}
public Boolean getCONF_ING() {
return CONF_ING;
}
public void setCONF_ING(Boolean CONF_ING) {
this.CONF_ING = CONF_ING;
}
}
Upvotes: 3
Views: 8710
Reputation: 10095
Solution:
You must write this:
if(tankMixPlant == null) {
Toast.makeText(getContext(), "Error to read tank information", Toast.LENGTH_LONG).show();
return;
}
Inside your onResponse
, after the line tankplant = ...
Now, null exception will be eliminated if you are getting any data from the server.
Hope it helps.
Update1:
Write this:
if(!tankMixPlant.getBlenderCode().equals("0") && tankMixPlant.getIngr() == 1)
{
getPackages(tankMixPlant.getRecipeNumber(), tankMixPlant.getBlenderCode(), tankMixPlant.getTankName());
// 2 - Mix Packages: Scan package barcode
stageScannerTank = 2;
}
if(!tankMixPlant.getIngrSAPNumber().equals("0") && tankMixPlant.getIngr() == 1)
{
getIngr(tankMixPlant.getRecipeNumber(), tankMixPlant.getTankName());
// 3 - P.I Packages: Scan package barcode
stageScannerTank = 3;
}
in your onResponse
method as shown below:
private void getTankMixPlant(String tankName){
mService.getTankMixPlant(tankName).enqueue(new Callback<TankMixPlant>() {
@Override
public void onResponse(Call<TankMixPlant> call, Response<TankMixPlant> response) {
tankMixPlant = response.body();
if(tankMixPlant == null) {
Toast.makeText(getContext(), "Error to read tank information",
Toast.LENGTH_LONG).show();
return;
}
...... (Write Here)
}
@Override
public void onFailure(Call<TankMixPlant> call, Throwable t) {
// On failure show the error message to the User
AlertDialog alert;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Error");
builder.setMessage("Error: " + t.getMessage());
alert = builder.create();
alert.show();
}
});
Try it.
Upvotes: 2
Reputation: 11487
The problem is that the retrofit call is done asynchronously, while the rest of your code isn't. That's why your data is null
, since it's nor ready yet.
First of all, you have to remove the part of the code where you're checking for the "pending data", and move it inside your retrofit onResponse
or somewhere else that'll be later called after the network response by using callbacks.
There are quite a few ways on exactly how you can do that. I'd suggest that you read the documentation and some tutorials like this one, and this other one.
Also, while you're making the retrofit call, it's best to display a loading message to the user, to keep him aware that you're making a network call and is waiting for the results.
Upvotes: 2