有没有办法消除这个空对象引用错误?我正在尝试从扫描仪活动中打开一个底部对话框

Posted

技术标签:

【中文标题】有没有办法消除这个空对象引用错误?我正在尝试从扫描仪活动中打开一个底部对话框【英文标题】:Is there any way to remove this nullobject reference error? I am trying to open a bottom dialog from scanner activity 【发布时间】:2021-07-20 12:51:48 【问题描述】:

    错误:

     E/androidRuntime: FATAL EXCEPTION: main
         Process: com.example.swiftpass, PID: 16875
         java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
             at com.example.swiftpass.ScanPopUpDialog.setPrompt(ScanPopUpDialog.java:47)
             at com.example.swiftpass.ScanQrActivity$MyImageAnalyzer.readerBarcodeData(ScanQrActivity.java:170)
             at com.example.swiftpass.ScanQrActivity$MyImageAnalyzer.access$200(ScanQrActivity.java:109)
             at com.example.swiftpass.ScanQrActivity$MyImageAnalyzer$3.onSuccess(ScanQrActivity.java:142)
             at com.example.swiftpass.ScanQrActivity$MyImageAnalyzer$3.onSuccess(ScanQrActivity.java:138)
             at com.google.android.gms.tasks.zzn.run(com.google.android.gms:play-services-tasks@@17.2.0:4)
             at android.os.Handler.handleCallback(Handler.java:789)
             at android.os.Handler.dispatchMessage(Handler.java:98)
             at android.os.Looper.loop(Looper.java:164)
             at android.app.ActivityThread.main(ActivityThread.java:6944)
             at java.lang.reflect.Method.invoke(Native Method)
             at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
    

    XML 代码:

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout
         xmlns:android="http://schemas.android.com/apk/res/android" android:layout_
         android:layout_
         android:orientation="vertical">
    
         <RelativeLayout
             android:layout_
             android:layout_>
    
             <ImageView
                 android:id="@+id/img_close"
                 android:layout_
                 android:layout_
                 android:layout_marginStart="10dp"
                 android:layout_marginTop="10dp"
                 android:src="@drawable/ic_close">
             </ImageView>
    
             <TextView
                 android:id="@+id/txt_type"
                 android:layout_
                 android:layout_
                 android:layout_centerHorizontal="true"
                 android:layout_marginTop="6dp"
                 android:text="@string/qr_type"
                 android:fontFamily="@font/roboto_black"
                 android:textSize="20dp">
             </TextView>
    
             <TextView
                 android:id="@+id/txt_prompt"
                 android:layout_
                 android:layout_
                 android:layout_centerHorizontal="true"
                 android:layout_marginTop="50dp"
                 android:layout_marginBottom="10dp"
                 android:text="@string/qr_prompt"
                 android:fontFamily="@font/roboto_medium"
                 android:textSize="18dp">
             </TextView>
    
         </RelativeLayout>
    
     </LinearLayout>
    

    底部对话框 java:

    包 com.example.swiftpass;

    导入android.os.Bundle; 导入 android.view.LayoutInflater; 导入android.view.View; 导入android.view.ViewGroup; 导入android.widget.ImageView; 导入 android.widget.TextView; 导入androidx.annotation.NonNull; 导入androidx.annotation.Nullable;

    导入 com.google.android.material.bottomsheet.BottomSheetDialogFragment;

    公共类 ScanPopUpDialog 扩展 BottomSheetDialogFragment

     //Declaration of Variables
    
     TextView type;
     TextView prompt;
     ImageView close;
    
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
         View view = inflater.inflate(R.layout.pop_up_dialog, container, false);
    
         type = view.findViewById(R.id.txt_type);
         prompt = view.findViewById(R.id.txt_prompt);
         close = view.findViewById(R.id.img_close);
         close.setOnClickListener(this::OnClick);
         return view;
     
    
     //This function will listen to button clicks and will call certain functions according to what is pressed by the user
     private void OnClick(View view) 
         switch(view.getId())
             case R.id.img_close:
                 dismiss();
                 break;
             case R.id.txt_prompt:
                 break;
         
     
    
     public void setPrompt(String type, String prompt)
         this.type.setText(type);
         this.prompt.setText(prompt);
    
         if (type == "TEXT")
             this.prompt.setOnClickListener(this::OnClick);
         
     
    

    扫描仪活动java:

    包 com.example.swiftpass;

    导入 androidx.annotation.NonNull; 导入androidx.appcompat.app.AppCompatActivity; 导入androidx.camera.core.CameraSelector; 导入androidx.camera.core.ImageAnalysis; 导入androidx.camera.core.ImageCapture; 导入androidx.camera.core.ImageProxy; 导入androidx.camera.core.Preview; 导入androidx.camera.lifecycle.ProcessCameraProvider; 导入androidx.camera.view.PreviewView; 导入androidx.core.app.ActivityCompat; 导入androidx.core.content.ContextCompat; 导入androidx.fragment.app.FragmentManager;

    导入 android.Manifest; 导入 android.annotation.SuppressLint; 导入 android.content.pm.PackageManager; 导入android.graphics.Point; 导入android.graphics.Rect; 导入android.media.Image; 导入android.os.Bundle; 导入android.util.Size; 导入android.widget.Toast;

    导入 com.google.android.gms.tasks.OnCompleteListener; 导入 com.google.android.gms.tasks.OnFailureListener; 导入 com.google.android.gms.tasks.OnSuccessListener; 导入 com.google.android.gms.tasks.Task; 导入 com.google.common.util.concurrent.ListenableFuture; 导入 com.google.mlkit.vision.barcode.Barcode; 导入 com.google.mlkit.vision.barcode.BarcodeScanner; 导入 com.google.mlkit.vision.barcode.BarcodeScannerOptions; 导入 com.google.mlkit.vision.barcode.BarcodeScanning; 导入 com.google.mlkit.vision.common.InputImage;

    导入 java.util.List; 导入 java.util.concurrent.ExecutionException; 导入 java.util.concurrent.ExecutorService; 导入 java.util.concurrent.Executors;

    公共类 ScanQrActivity 扩展 AppCompatActivity

     //Declaration of Variables
    
     private ListenableFuture cameraProviderFuture;
     private ExecutorService cameraExecutor;
     private PreviewView previewView;
     private MyImageAnalyzer analyzer;
    
     @Override
     protected void onCreate(Bundle savedInstanceState) 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_scan_qr);
    
         //Assigning of widgets and Setting up of listeners
         initializeScan();
    
    
         cameraProviderFuture.addListener(new Runnable() 
             @Override
             public void run() 
                 try 
                     if (ActivityCompat.checkSelfPermission(ScanQrActivity.this, Manifest.permission.CAMERA) != (PackageManager.PERMISSION_GRANTED))
                         ActivityCompat.requestPermissions(ScanQrActivity.this, new String [] Manifest.permission.CAMERA, 101);
                     else
                         ProcessCameraProvider processCameraProvider = (ProcessCameraProvider) cameraProviderFuture.get();
                         bindPreview(processCameraProvider);
                     
                 catch (ExecutionException e)
                     e.printStackTrace();
                 catch (InterruptedException e)
                     e.printStackTrace();
                 
             
         , ContextCompat.getMainExecutor(this));
     
    
     @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
         if (requestCode == 101 && grantResults.length > 0)
             ProcessCameraProvider processCameraProvider = null;
             try 
                 processCameraProvider = (ProcessCameraProvider) cameraProviderFuture.get();
              catch (ExecutionException e) 
                 e.printStackTrace();
              catch (InterruptedException e) 
                 e.printStackTrace();
             
             bindPreview(processCameraProvider);
         
     
    
     private void bindPreview(ProcessCameraProvider processCameraProvider) 
    
         Preview preview = new Preview.Builder().build();
         CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
         preview.setSurfaceProvider(previewView.getSurfaceProvider());
         ImageCapture imageCapture = new ImageCapture.Builder().build();
         ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                 .setTargetResolution(new Size(1280, 720))
                 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                 .build();
         imageAnalysis.setAnalyzer(cameraExecutor, analyzer);
         processCameraProvider.unbindAll();
         processCameraProvider.bindToLifecycle(this,cameraSelector, preview, imageCapture, imageAnalysis);
     
    
     public class MyImageAnalyzer implements ImageAnalysis.Analyzer
         private FragmentManager fragmentManager;
         private ScanPopUpDialog bottomDialog;
    
         public MyImageAnalyzer(FragmentManager fragmentManager)
             this.fragmentManager = fragmentManager;
             bottomDialog = new ScanPopUpDialog();
         
    
         @Override
         public void analyze(@NonNull ImageProxy imageProxy) 
              scanBarcode(imageProxy);
         
    
         private void scanBarcode(ImageProxy imageProxy) 
    
             BarcodeScannerOptions options =
                     new BarcodeScannerOptions.Builder()
                             .setBarcodeFormats(
                                     Barcode.FORMAT_QR_CODE)
                             .build();
    
             @SuppressLint("UnsafeExperimentalUsageError") Image mediaImage = imageProxy.getImage();
             assert mediaImage != null;
             InputImage inputImage =
                     InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
    
             BarcodeScanner scanner = BarcodeScanning.getClient(options);
             Task<List<Barcode>> result = scanner.process(inputImage)
                     .addOnSuccessListener(new OnSuccessListener<List<Barcode>>() 
                         @Override
                         public void onSuccess(List<Barcode> barcodes) 
                             // Task completed successfully
                             readerBarcodeData(barcodes);
                         
                     )
                     .addOnFailureListener(new OnFailureListener() 
                         @Override
                         public void onFailure(@NonNull Exception e) 
                             // Task failed with an exception
                             // ...
                             e.printStackTrace();
                         
                     )
                     .addOnCompleteListener(new OnCompleteListener<List<Barcode>>() 
                         @Override
                         public void onComplete(@NonNull Task<List<Barcode>> task) 
                             imageProxy.close();
                         
                     );
         
    
         private void readerBarcodeData(List<Barcode> barcodes) 
             for (Barcode barcode: barcodes) 
                 Rect bounds = barcode.getBoundingBox();
                 Point[] corners = barcode.getCornerPoints();
    
                 String rawValue = barcode.getRawValue();
                 int valueType = barcode.getValueType();
                 switch (valueType)
                     case Barcode.TYPE_TEXT:
                         bottomDialog.setPrompt(rawValue, "CLICK TO CONFIRM");
                         break;
                     case Barcode.TYPE_CALENDAR_EVENT:
                         bottomDialog.setPrompt("Calendar Event", "Unsupported Type");
                         break;
                     case Barcode.TYPE_CONTACT_INFO:
                         bottomDialog.setPrompt("Contact Info", "Unsupported Type");
                         break;
                     case Barcode.TYPE_DRIVER_LICENSE:
                         bottomDialog.setPrompt("Driver's License", "Unsupported Type");
                         break;
                     case Barcode.TYPE_EMAIL:
                         bottomDialog.setPrompt("E-mail", "Unsupported Type");
                         break;
                     case Barcode.TYPE_GEO:
                         bottomDialog.setPrompt("Location", "Unsupported Type");
                         break;
                     case Barcode.TYPE_ISBN:
                         bottomDialog.setPrompt("Book Number", "Unsupported Type");
                         break;
                     case Barcode.TYPE_PHONE:
                         bottomDialog.setPrompt("Phone", "Unsupported Type");
                         break;
                     case Barcode.TYPE_PRODUCT:
                         bottomDialog.setPrompt("Product", "Unsupported Type");
                         break;
                     case Barcode.TYPE_SMS:
                         bottomDialog.setPrompt("SMS", "Unsupported Type");
                         break;
                     case Barcode.TYPE_URL:
                         bottomDialog.setPrompt("Link", "Unsupported Type");
                         break;
                     case Barcode.TYPE_WIFI:
                         bottomDialog.setPrompt("Wi-Fi", "Unsupported Type");
                         break;
                     default:
                         bottomDialog.setPrompt("Uknown", "Uknown Type");
                 
                 if (!bottomDialog.isAdded())
                     bottomDialog.show(fragmentManager, "");
                 
             
         
     
    
    
     private void initializeScan() 
         previewView = findViewById(R.id.previewView);
         this.getWindow().setFlags(1024,1024);
         cameraExecutor = Executors.newSingleThreadExecutor();
         cameraProviderFuture = ProcessCameraProvider.getInstance(this);
         analyzer = new MyImageAnalyzer(getSupportFragmentManager());
     
    

【问题讨论】:

【参考方案1】:

我解决了,代码如下:

package com.example.swiftpass;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;


public class ScanPopUpDialog extends BottomSheetDialogFragment 

    //Declaration of Variables

    TextView type;
    TextView prompt;
    ImageView close;
    String stringType;
    String stringPrompt;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
        View view = inflater.inflate(R.layout.pop_up_dialog, container, false);

        type = view.findViewById(R.id.txt_type);
        type.setText(getStringType());
        prompt = view.findViewById(R.id.txt_prompt);
        prompt.setText(getStringPrompt());
        if (stringPrompt == "CLICK TO CONFIRM")
            prompt.setOnClickListener(this::OnClick);
        
        close = view.findViewById(R.id.img_close);
        close.setOnClickListener(this::OnClick);
        return view;
    

    //This function will listen to button clicks and will call certain functions according to what is pressed by the user
    private void OnClick(View view) 
        switch(view.getId())
            case R.id.img_close:
                dismiss();
                break;
            case R.id.txt_prompt:
                break;
        
    

    public void setDialog(String type, String prompt)
        /**
         * This method is public because it is being called fron the scan qr activity
         * this will set the value for the objects stringType and stringPrompt
         * this does not return any value thus, the values will be accessed through
         * get method
         */
        stringType = type;
        stringPrompt = prompt;
    

    /**
     *These methods are used to access the value set by the setDialog method
     *
     */
    private String getStringType()
        return stringType;
    

    private String getStringPrompt()
        return stringPrompt;
    

【讨论】:

以上是关于有没有办法消除这个空对象引用错误?我正在尝试从扫描仪活动中打开一个底部对话框的主要内容,如果未能解决你的问题,请参考以下文章

NullPointerException 错误尝试在空对象引用上调用虚拟方法错误

尝试从空对象引用上的字段“android.view.View androidx.recyclerview.widget.RecyclerView$b0.a”读取

java.lang.NullPointerException:尝试在 OnPostExecute() 上的空对象引用错误上调用接口方法 - AsyncTask

尝试在空对象引用上调用接口方法“____”[重复]

由于尝试在空对象引用上调用虚拟方法“ ”,应用程序崩溃

带有空对象的补丁值