Android空指针异常:Button.setOnClickListener调用空对象引用问题
解决空对象引用错误(Attempt to invoke virtual method ... on a null object reference)
问题根源
你触发空指针的核心原因是调用findViewById的时机早于setContentView。在setContentView执行前,布局还未加载到内存中,所有通过findViewById获取的控件实例都是null,此时调用setOnClickListener必然抛出空指针异常。
修复方案
将所有控件初始化(findViewById)的代码,移动到setContentView(R.layout.activity_main)之后执行。修改后的onCreate方法如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); // 现在才初始化控件,此时布局已加载 sB = findViewById(R.id.selectB); pB = findViewById(R.id.PredicteB); cB = findViewById(R.id.captureB); result = findViewById(R.id.result); imageView = findViewById(R.id.imageView); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); // 后续的点击监听设置逻辑保持不变 sB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent1 = new Intent(); intent1.setAction(Intent.ACTION_GET_CONTENT); intent1.setType("image/*"); startActivityForResult(intent1,10); } }); cB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent2, 12); } }); getPermission(); int cnt = 0; String[] lables = new String[1001]; try { BufferedReader br= new BufferedReader(new InputStreamReader(getAssets().open("labels.txt"))); String line = br.readLine(); while (line != null){ lables[cnt] = line; cnt++; line = br.readLine(); } } catch (IOException e) { e.printStackTrace(); } pB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 新增:先判断Bitmap是否为空,避免崩溃 if (bm == null) { result.setText("请先选择或拍摄图片"); return; } try { MobilenetV110224Quant model = MobilenetV110224Quant.newInstance(MainActivity.this); TensorBuffer inputFeature0 = TensorBuffer.createFixedSize(new int[]{1, 224, 224, 3}, DataType.UINT8); Bitmap scaledBm = Bitmap.createScaledBitmap(bm, 224, 224, true); inputFeature0.loadBuffer(TensorImage.fromBitmap(scaledBm).getBuffer()); MobilenetV110224Quant.Outputs outputs = model.process(inputFeature0); TensorBuffer outputFeature0 = outputs.getOutputFeature0AsTensorBuffer(); result.setText(lables[getMax(outputFeature0.getFloatArray())]); model.close(); } catch (IOException e) { e.printStackTrace(); result.setText("识别失败"); } } }); }
额外优化建议
- 相机拍照结果处理:在
onActivityResult的相机分支(requestCode=12)中,增加data非空判断,避免空指针:
else if(requestCode == 12){ if (data != null) { bm = (Bitmap) data.getExtras().get("data"); imageView.setImageBitmap(bm); } }
- 权限请求逻辑:当前权限请求如果用户拒绝后会无限弹窗,可添加提示引导用户开启权限:
void getPermission(){ if(checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { Toast.makeText(this, "需要相机权限来拍摄图片", Toast.LENGTH_SHORT).show(); } ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CAMERA},11); } }
内容的提问来源于stack exchange,提问作者Nier Yorha
相关产品推荐
相关产品推荐

