Android: дождитесь ответа от API, прежде чем продолжить выполнение с помощью Retrofit - PullRequest
0 голосов
/ 01 октября 2018

У меня проблема с программированием на Android, у меня есть приложение, которое требует запуска некоторых подпрограмм, таких как сканирование штрих-кода.После того, как я отсканировал штрих-код, я отправлю данные этого штрих-кода в мой API, «подожду», чтобы получить некоторую информацию, и после этого сделаю другие вещи.

Проблема в том, что когда я вызываю свой API для получения информации и после того, как я пытаюсь использовать информацию, которая должна была поступить из API, у меня возникает исключение NULL, см. Код ниже:

Моя процедура сканирования, которая вызывается каждый раз, когда я сканирую штрих-код:

    // 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, используя Retrofit для вызова моей службы, работает, если я проверяю свою программу:

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();
        }
    });
}

Как я могу ждать, когда tankMixPlant будет заполнен данными, чтобы продолжить мою процедуру?

ОБНОВЛЕНИЯ:

Я продолжаю решать проблему, но я изменилсянекоторые вещи, которые вы можете увидеть ниже: Теперь я получаю NullPointerException.

Теперь я проверяю, является ли мой объект нулевым внутри метода onResponse:

     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();
        }
    });
}

Но когда я пытаюсь проверить некоторую информацию о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;
        }

Мое приложение вылетает с этой ошибкой:

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) 

Мой tankMixPlant класс:

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;
    }

}

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

Решение:

Вы должны написать это:

    if(tankMixPlant == null) {
        Toast.makeText(getContext(), "Error to read tank information", Toast.LENGTH_LONG).show();
        return;
    }

Внутри вашего onResponse после строки tankplant = ...

Теперь нулевое исключение будет исключеноесли вы получаете какие-либо данные с сервера.

Надеюсь, это поможет.

Update1:

Напишите это:

    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;
    }

в вашем onResponse методе, как показано ниже:

 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();
    }
});

Попробуйте.

0 голосов
/ 01 октября 2018

Проблема в том, что вызов дооснащения выполняется асинхронно, а остальной код - нет.Вот почему ваши данные null, так как они еще не готовы.

Прежде всего, вам нужно удалить часть кода, где вы проверяете «ожидающие данные», и переместить ее внутрьВаша модернизация onResponse или где-то еще, что позже будет вызвано после ответа сети с помощью обратных вызовов.

Существует довольно много способов, как именно вы можете это сделать.Я бы посоветовал вам прочитать документацию и некоторые учебные пособия, такие как этот и этот другой .

Кроме того, пока вы 'При повторном вызове лучше всего отобразить пользователю сообщение о загрузке, чтобы он знал, что вы делаете сетевой вызов и ожидаете результатов.

...