Android 当我尝试在当前 activity 上使用适配器显示内容时,应用程序一直返回主 activity UI

Android app keeps going back to main activity UI when I try to display something using an adapter on the current activity

我是 android 开发的新手,正在构建一个可以从 BLE 设备读取特征的应用程序。我能够连接到设备并读取其特性。但是,我有一个问题是使用适配器显示特性。最初,我尝试使用 RecycleView 适配器,但是当我试图通知我的 recycleview 适配器时,我的程序一直返回到主 activity,Logcat 上剩下的所有内容都是这样的:

2020-11-24 13:35:37.220 12966-12966/? I/zygote64: Late-enabling -Xcheck:jni
2020-11-24 13:35:37.346 12966-12966/com.example.wbdmx I/LoadedApk: No resource references to update in package zui.platform
2020-11-24 13:35:37.368 12966-12966/com.example.wbdmx W/Typeface: setThemeFont(): FontPath Not Changed!
2020-11-24 13:35:37.683 12966-12993/com.example.wbdmx D/OpenGLRenderer: HWUI GL Pipeline
2020-11-24 13:35:37.757 12966-12993/com.example.wbdmx I/Adreno: QUALCOMM build                   : e89802c, I1ef8061d77
    Build Date                       : 03/28/18
    OpenGL ES Shader Compiler Version: EV031.22.00.01
    Local Branch                     : 
    Remote Branch                    : quic/gfx-adreno.lnx.1.0.r36-rel
    Remote Branch                    : NONE
    Reconstruct Branch               : NOTHING
2020-11-24 13:35:37.766 12966-12993/com.example.wbdmx I/Adreno: PFP: 0x005ff087, ME: 0x005ff063
2020-11-24 13:35:37.774 12966-12993/com.example.wbdmx I/zygote64: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
2020-11-24 13:35:37.776 12966-12993/com.example.wbdmx I/OpenGLRenderer: Initialized EGL, version 1.4
2020-11-24 13:35:37.776 12966-12993/com.example.wbdmx D/OpenGLRenderer: Swap behavior 2
2020-11-24 13:35:37.871 12966-12966/com.example.wbdmx D/QuickpanelHelper: mUpdateSettings connect cost:3
2020-11-24 13:35:37.887 12966-12966/com.example.wbdmx D/QuickpanelHelper: mUpdateSettings connect cost:1

我认为 recycleview 是问题所在,现在我正在使用自定义列表视图适配器,但在连接设备并且应用程序返回 MainActivity 视图后,我的 Logcat 中也会出现同样的问题。这是我的文件:

MainActivity.java:


import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;

import android.util.Log;
import android.view.View;
import android.widget.Button;

import android.widget.Toast;

import java.util.ArrayList;

import java.util.List;
import java.util.ListIterator;

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter = null;
    private BluetoothLeScanner bleScanner=null;
    private ScanSettings scanSettings;
    private ScanCallback scanCallback;
    private static final int REQUEST_ENABLE_BT = 1;
    private static final int REQUEST_PERMISSIONS = 2;
    private boolean isScanning = false;
    private ArrayList<ScanResult> scanResult = new ArrayList<>();
    private scanResultAdapter scanAdapter;
    private RecyclerView recyclerView;
    private Button scan_btn;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "bluetooth_not_supported", Toast.LENGTH_SHORT).show();
            finish();
        }
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(linearLayoutManager);
        scanAdapter = new scanResultAdapter(scanResult, new CustomItemClickListner() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onItemClick(View v, int position) {
                if(isScanning){
                    stopScan();
                }
                final BluetoothDevice device = scanResult.get(position).getDevice();
                Log.w("ScanResultAdapter", "Connecting to device "+device.getAddress());
                Operations(v, device);

            }
        });
        recyclerView.setAdapter(scanAdapter);

        //button so that we can change its text when clicked
        scan_btn = (Button) findViewById(R.id.search_button);
    }
    public void Operations(View view, BluetoothDevice device){
        Intent intent = new Intent(this, BleOperationsActivity.class);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        startActivity(intent);
    }


    @Override
    protected void onResume() {
        super.onResume();

        // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
        // fire an intent to display a dialog asking the user to grant permission to enable it.
        if (!mBluetoothAdapter.isEnabled()) {
            final Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            return;
        }
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this,
                        Manifest.permission.READ_PHONE_STATE)
                        != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this,
                        Manifest.permission.READ_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {

                    ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                    Manifest.permission.READ_PHONE_STATE,
                                    Manifest.permission.READ_EXTERNAL_STORAGE,
                                    Manifest.permission.WRITE_EXTERNAL_STORAGE},
                            REQUEST_PERMISSIONS);
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void startScan(){
        //response to the scan button
        bleScanner = mBluetoothAdapter.getBluetoothLeScanner();
        scanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
        scanResult.clear();
        scanAdapter.notifyDataSetChanged();
        scanCallback = new ScanCallback(){
            @Override
            public void onScanResult(int callbackType, ScanResult result){
                ListIterator<ScanResult> item_iterator = scanResult.listIterator();
                boolean flag = true;
                while(item_iterator.hasNext()){
                    ScanResult item = item_iterator.next();
                    if(item.getDevice().getAddress().equals(result.getDevice().getAddress())){
                        flag = false;
                   }
                }
                if(flag) {
                    Log.i("ScanCallback", "Found unique BLE device! Name : " + result.getDevice().getName() + " address: " +result.getDevice().getAddress());
                    scanResult.add(result);
                    scanAdapter.notifyItemInserted(scanResult.size()-1); }
            }

            @Override
            public void onScanFailed(int errorCode){
                Log.e("ScanCallback", "onScanFailed: code " + errorCode);
            }
        };
        scanResult.clear();
//        ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("D7:42:44:9F:56:C9").build();
//        List<ScanFilter> filters = null;
//        filters.add(filter);
        bleScanner.startScan(null, scanSettings, scanCallback);
        isScanning = true;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void stopScan(){
        bleScanner.stopScan(scanCallback);
        isScanning = false;
        scan_btn.setText("SEARCH FOR DEVICES");
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void button_function(View v) {
        if(isScanning){
            stopScan();

        }
        else{
            startScan();
            scan_btn.setText("STOP SEARCH");

        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onPause() {
        super.onPause();

        if (bleScanner != null) {
            stopScan();
            bleScanner = null;
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onStop() {
        super.onStop();

        if (bleScanner != null) {
            stopScan();
            bleScanner = null;
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (bleScanner != null) {
            stopScan();
            bleScanner = null;
        }
    }

}

scanResultAdapter.java:

package com.example.wbdmx;


import android.bluetooth.le.ScanResult;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.RequiresApi;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;

public class scanResultAdapter extends RecyclerView.Adapter<scanResultAdapter.ViewHolder> {
    private List<ScanResult> scanResult;

    private CustomItemClickListner listner;

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView deviceName;
        TextView deviceAddress;
        TextView deviceRssi;

        public ViewHolder(View view) {
            super(view);
            // Define click listener for the ViewHolder's View
            deviceName = view.findViewById(R.id.device_name);
            deviceAddress = view.findViewById(R.id.device_address);
            deviceRssi = view.findViewById(R.id.device_rssi);
        }

    }

    public scanResultAdapter(List<ScanResult> dataSet, CustomItemClickListner listner) {
        scanResult = dataSet;
        this.listner = listner;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.listitem_device, viewGroup, false);
        final ViewHolder mViewHolder = new ViewHolder(view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listner.onItemClick(v, mViewHolder.getAdapterPosition());
            }
        });

        return mViewHolder;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.deviceName.setText(scanResult.get(position).getDevice().getName() == null ? "Unknown": scanResult.get(position).getDevice().getName());
        viewHolder.deviceRssi.setText(String.valueOf(scanResult.get(position).getRssi()));
        viewHolder.deviceAddress.setText(scanResult.get(position).getDevice().getAddress());

    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        if (scanResult == null) return 0;

        return scanResult.size();
    }
}

BleOperations.java:


import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanResult;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class BleOperationsActivity extends AppCompatActivity {
    private BluetoothDevice device;
    private ArrayList<BluetoothGattCharacteristic> characteristics = new ArrayList<>();
    private List<BluetoothGattService> services;
    private static final int GATT_MAX_MTU_SIZE = 517;
    ListView listView;
    private characteristicAdapter charAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if(device == null) Log.e("BleOperationsIntent", "Missing BluetoothDevice from MainActivity");
        device.connectGatt(this, false, gattCallback);
        setContentView(R.layout.activity_ble_operations);

        listView = (ListView)findViewById(R.id.list);

    }

//    public void setupRecyclerView(){
//        recyclerView = (RecyclerView) findViewById(R.id.characteristics_recycler_view);
//        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
//        recyclerView.setLayoutManager(linearLayoutManager);
//        charAdapter = new characteristicAdapter(characteristics, new CustomItemClickListner() {
//            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
//            @Override
//            public void onItemClick(View v, int position) {
//                final BluetoothGattCharacteristic character= characteristics.get(position);
//            }
//        }, this);
//        recyclerView.setAdapter(charAdapter);
//    }

    private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);

            if(status == gatt.GATT_SUCCESS){
                if (newState == BluetoothProfile.STATE_CONNECTED){
                    Log.w("BluetoothGattCallback", "Successfully connected to device " + gatt.getDevice().getAddress());
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            boolean ans = gatt.discoverServices();
                            Log.d("onConnectionStateChange", "Discover Services started: " + ans);
                            gatt.requestMtu(GATT_MAX_MTU_SIZE);

                        }
                    });
                    //gatt.discoverServices();

                }
                else if(newState == BluetoothProfile.STATE_DISCONNECTED){
                    Log.w("BluetoothGattCallback", "Succesfully disconnected form device "+ gatt.getDevice().getAddress());
                    gatt.close();
                }
                else{
                    Log.w("BluetoothGattCallback", "Error "+status+" encountered for "+gatt.getDevice().getAddress()+ "\nDisconnecting...");
                    gatt.close();
                }
            }
        }

        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status){
            super.onServicesDiscovered(gatt, status);
            services = gatt.getServices();
            Log.w("BluetoothGattCallback", "Discovered "+ services.size()+" for "+gatt.getDevice().getAddress());

            characteristics.addAll(services.stream().flatMap(s -> s.getCharacteristics().stream())
                    .collect(Collectors.toList()));

            Log.w("onServicesDiscovered", "size = "+characteristics.size());
            printGattTable(services);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
//                    charAdapter.notifyDataSetChanged();
//                    Log.w("onServicesDiscovered", "adapter item count = "+ charAdapter.getItemCount());
                    charAdapter = new characteristicAdapter(characteristics, getApplicationContext());
                    listView.setAdapter(charAdapter);
                }
            });

        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status){
            boolean event = status ==BluetoothGatt.GATT_SUCCESS;
            Log.w("onMtuChanged", "ATT MTU changed to "+mtu+" "+ event);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
            if(status == BluetoothGatt.GATT_SUCCESS){
                Log.i("BluetoothGattCallback", "Read characteristic success for "+ characteristic.getUuid().toString());
            }
            else if(status == BluetoothGatt.GATT_READ_NOT_PERMITTED){
                Log.i("BluetoothGattCallback", "Read not permitted for  "+ characteristic.getUuid().toString());
            }
            else{
                Log.i("BluetoothGattCallback", "Characteristic read failed for  "+ characteristic.getUuid().toString());
            }
        }
    };


    private void printGattTable(List<BluetoothGattService> services){
        if(services.isEmpty()){
            Log.i("printGattTable", "No service and characteristic available, call discoverServices() first?");
            return;
        }
        Iterator<BluetoothGattService> it = services.iterator();
        while(it.hasNext()){
            BluetoothGattService service = it.next();
            Log.i("printGattTable", "Service "+ service.getUuid()+"\nCharacteristics:\n"+service.getCharacteristics()+"\n");
        }
    }
}

characteristicsAdapter.java:

package com.example.wbdmx;

import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;

public class characteristicAdapter  extends ArrayAdapter<BluetoothGattCharacteristic> implements View.OnClickListener{
    private List<BluetoothGattCharacteristic> characteristics;
    private Context mContext;

    private static class ViewHolder{
        TextView characteristic_uuid;
        TextView characteristic_property;
    }
    public characteristicAdapter(List<BluetoothGattCharacteristic> characteristics,  Context m) {
        super(m, R.layout.row_characteristic, characteristics);
        this.characteristics = characteristics;
        this.mContext = m;
    }
    @Override
    public void onClick(View v) {

    }

    public View getView(int position, View convertView, ViewGroup parent){
        BluetoothGattCharacteristic character = getItem(position);

        ViewHolder viewHolder;

        final View result;

        if(convertView == null){
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.row_characteristic, parent, false);
            viewHolder.characteristic_uuid = (TextView) convertView.findViewById(R.id.characteristic_uuid);
            viewHolder.characteristic_property= (TextView) convertView.findViewById(R.id.characteristic_properties);

            result = convertView;
            convertView.setTag(viewHolder);
        }
        else{
            viewHolder = (ViewHolder)convertView.getTag();
            result = convertView;
        }

        viewHolder.characteristic_uuid.setText(character.getUuid().toString());
        viewHolder.characteristic_property.setText((character.getProperties()));

        return convertView;
    }

}

编辑 1:删除了构建 gradle 文件和一些 xml 文件,因为我达到了字符数限制。

这是导致崩溃的原因:

2020-11-24 14:54:13.897 16688-16789/com.example.wbdmx D/BluetoothGatt: onConnectionUpdated() - Device=D7:42:44:9F:56:C9 interval=39 latency=0 timeout=500 status=0
2020-11-24 14:54:13.901 16688-16688/com.example.wbdmx W/ResourceType: No package identifier when getting value for resource number 0x00000002
2020-11-24 14:54:13.902 16688-16688/com.example.wbdmx D/AndroidRuntime: Shutting down VM
2020-11-24 14:54:13.912 16688-16688/com.example.wbdmx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.wbdmx, PID: 16688
    android.content.res.Resources$NotFoundException: String resource ID #0x2
        at android.content.res.Resources.getText(Resources.java:339)
        at android.widget.TextView.setText(TextView.java:5496)
        at com.example.wbdmx.characteristicAdapter.getView(characteristicAdapter.java:53)
        at android.widget.AbsListView.obtainView(AbsListView.java:2388)
        at android.widget.ListView.measureHeightOfChildren(ListView.java:1408)
        at android.widget.ListView.onMeasure(ListView.java:1315)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22087)
        at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:792)
        at androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:583)
        at androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:682)
        at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:159)
        at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:290)
        at androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:119)
        at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1578)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1690)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:146)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:490)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:786)
        at android.view.View.measure(View.java:22087)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2504)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1542)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1799)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1430)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6885)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6606)
        at java.lang.reflect.Method.invoke(Native Method)
2020-11-24 14:54:13.913 16688-16688/com.example.wbdmx E/AndroidRuntime:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)

所有这一切的发生是因为我没有在 characteristicAdapter 文件中的 getView() 中将 character.getProperties() 转换为字符串值。