You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发遇NullPointerException:调用null对象方法崩溃求助

问题描述

我正在开发一款扫描商品条码并获取信息的应用,使用Retrofit与API通信。扫描数据库中不存在的商品时应用崩溃,崩溃日志如下:

E/an.fifthscanne: [qarth_debug:]  get PatchStore::createDisableExceptionQarthFile method fail. E/AndroidRuntime: FATAL EXCEPTION: main Process: com.givaudan.fifthscanner, PID: 9635 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.givaudan.fifthscanner.http.Product.getBrand()' on a null object reference at com.givaudan.fifthscanner.form$2.onResponse(form.java:121)

崩溃发生在这行代码:

brand = data.getProductField().getBrand() + "\n";

尝试添加空值判断的错误处理逻辑但未成功,也无法直接照搬初始化对象的方案,相关代码如下:

public class form extends AppCompatActivity {
    private TextView textViewResult;
    private TextView success;

    ProgressDialog progressDialog;
    Button btnInsert;
    String brand;
    String barcode;
    String line;
    String packaging;
    String countries;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_form);

        textViewResult = findViewById(R.id.text_view_result);

        btnInsert = findViewById(R.id.bt_send_excel);

        //Set the "Loading PopUp"
        progressDialog = new ProgressDialog(form.this);
        progressDialog.setMessage("Loading ...");

        btnInsert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                addProductData(brand, barcode, line, packaging, countries);
                progressDialog.show();
            }
        });

        //retrieve value CODE_BARRE from MainActivity
        String productCode = getIntent().getStringExtra("productId");

        //=========================
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://world.openfoodfacts.org/api/v0/produit/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        RequestPlaceHolder requestPlaceHolder = retrofit.create(RequestPlaceHolder.class);

        String url = "https://world.openfoodfacts.org/api/v0/produit/" +  productCode + ".json";

        Call<Data> call = requestPlaceHolder.getData(url);

        call.enqueue(new Callback<Data>() {
            @Override
            public void onResponse(Call<Data> call, Response<Data> response) {

                /*if (response.body() != null) {
                    //textViewResult.setText("Code" + response.code());
                    textViewResult.setText("The product does not exist with this barcode,\n" +
                            "look for the barcode of the product on: \n\n" +
                            "https://fr.openbeautyfacts.org/");
                    return;
                }*/

                if (response.isSuccessful()) {
                    //Retrieve data and display it

                    Data data = response.body();

                    barcode = productCode + "\n";
                    brand = data.getProductField().getBrand() + "\n";
                    line = data.getProductField().getLine() + "\n";
                    packaging = data.getProductField().getPackaging() + "\n";
                    countries = data.getProductField().getCountries() + "\n";
                    String content = brand + "\n" + barcode + "\n" + line +
                            "\n" + packaging + "\n" + countries;
                    textViewResult.append(content);
                }

            }

            @Override
            public void onFailure(Call<Data> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });

    }


    //Add data to excel
    public void addProductData(String brand, String barcode, String line, String packaging, String countries) {

        StringRequest stringRequest = new StringRequest(Request.Method.POST, "https://script.google.com/macros/s/AKfycbwyXLOJEa_Bvgb4Ae-qqX5zWQO0E_MJcUPy7nJBft9MTq3BvCd6gcwy0_2MhGUDFZNo8w/exec", new com.android.volley.Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Intent intent = new Intent(form.this, SuccessActivity.class);
                startActivity(intent);
                progressDialog.hide();

            }
        }, error -> {

        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("sbrand", brand);
                params.put("sbarcode", barcode);
                params.put("sline", line);
                params.put("spackaging", packaging);
                params.put("scountries", countries);

                return params;
            }
        };

        int socketTimeOut = 50000;
        RetryPolicy retryPolicy = new DefaultRetryPolicy(socketTimeOut, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
        stringRequest.setRetryPolicy(retryPolicy);

        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    }
}
解决方案
  • 逐层添加空值校验
    当商品不存在时,API会返回200成功响应,但response.body()内的productField为null。需要在获取数据前逐层判断空值,同时对单个字段做空值兜底:

    @Override
    public void onResponse(Call<Data> call, Response<Data> response) {
        if (response.isSuccessful()) {
            Data data = response.body();
            // 校验Data对象是否为空
            if (data == null) {
                textViewResult.setText("未找到该商品信息");
                return;
            }
            // 校验Product对象是否为空
            Product product = data.getProductField();
            if (product == null) {
                textViewResult.setText("未找到该商品信息");
                return;
            }
            // 对每个字段做空值兜底,避免拼接时出现空指针
            barcode = productCode + "\n";
            brand = (product.getBrand() != null ? product.getBrand() : "无品牌") + "\n";
            line = (product.getLine() != null ? product.getLine() : "无产品线") + "\n";
            packaging = (product.getPackaging() != null ? product.getPackaging() : "无包装信息") + "\n";
            countries = (product.getCountries() != null ? product.getCountries() : "无销售国家") + "\n";
            String content = brand + "\n" + barcode + "\n" + line +
                    "\n" + packaging + "\n" + countries;
            textViewResult.append(content);
        } else {
            // 处理非200的异常响应
            textViewResult.setText("请求失败:" + response.code());
        }
    }
    
  • 移除错误的判断逻辑
    你注释掉的if (response.body() != null)逻辑不符合API返回规则,直接删除即可。

  • 优化按钮点击逻辑
    防止用户在未获取商品信息时提交空数据,添加状态判断:

    btnInsert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (barcode == null || barcode.isEmpty()) {
                textViewResult.setText("请先获取商品信息");
                return;
            }
            addProductData(brand, barcode, line, packaging, countries);
            progressDialog.show();
        }
    });
    

内容的提问来源于stack exchange,提问作者LAZREQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:15:40