【问题标题】: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
【问题描述】:
  1. 错误:

     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)
    
  2. XML 代码:

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout
         xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">
    
         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
    
             <ImageView
                 android:id="@+id/img_close"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="10dp"
                 android:layout_marginTop="10dp"
                 android:src="@drawable/ic_close">
             </ImageView>
    
             <TextView
                 android:id="@+id/txt_type"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 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_width="wrap_content"
                 android:layout_height="wrap_content"
                 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>
    
  3. 底部对话框 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);
         }
     }
    

    }

  4. 扫描仪活动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());
     }
    

    }

【问题讨论】:

    标签: android


    【解决方案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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 2014-05-20
      • 1970-01-01
      • 2016-12-01
      • 1970-01-01
      相关资源
      最近更新 更多