在自定义ListView适配器中执行findViewById时发生NullPointerException

问题描述

我想在Android设备上创建文件管理器,并在文件管理器中为ListView的内部类创建了一个自定义适配器。

xtabs(amountMean ~ week + state,sumTable)
#    state
# week       AL       CA
#   1 2.500000 2.500000
#   2 2.666667 2.250000

以下是ListView中适配器的布局文件

# Name of the resource we're selectively copying
GOOGLESERVICE_INFO_LOCATION=${PROJECT_DIR}/${TARGET_NAME}/App/Scripts/GoogleService-Info.plist

# Upload sysmbol
echo "Uploading dsym file"

"${PODS_ROOT}/FirebaseCrashlytics/upload-symbols" -gsp ${GOOGLESERVICE_INFO_LOCATION} -p ios ${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}

这是活动的布局文件,其中包括listView。

    private static final class FileAdaptor extends BaseAdapter {
           // These variables below would be set in my activity class
            private final List<String> data = new ArrayList<>(); // file name
            private final List<Drawable> data1 = new ArrayList<>(); // file icon
            private final List<String> data2 = new ArrayList<>(); // file modified data
            private final AppCompatActivity activity;
    
            public FileAdaptor(final AppCompatActivity activity) {
                this.activity = activity;
            }
    
            @Override
            public final int getCount() {
                return data.size();
            }
    
            @Override
            public final Object getItem(final int position) {
                return data.get(position);
            }
    
            public final void setData(final List<String> data) {
                if (data != null) {
                    this.data.clear();
                    if (data.size() > 0)
                        this.data.addAll(data);
                    notifyDataSetChanged();
                }
            }
    
            public final void setData1(final List<Drawable> data) {
                if (data != null) {
                    this.data1.clear();
                    if (data.size() > 0)
                        this.data1.addAll(data);
                    notifyDataSetChanged();
                }
            }
    
            public final void setData2(final List<String> data) {
                if (data != null) {
                    this.data2.clear();
                    if (data.size() > 0)
                        this.data2.addAll(data);
                    notifyDataSetChanged();
                }
            }
    
            public final String getData(final int position) {
                return data.get(position);
            }
    
            public final Drawable getData1(final int position) {
                return data1.get(position);
            }
    
            public final String getData2(final int position) {
                return data2.get(position);
            }
    
            @Override
            public final long getItemId(final int position) {
                return 0;
            }
    
            @Override
            public final View getView(final int position,final View convertView,final ViewGroup parent) {
                View v;
                if (convertView == null) {
                    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.file_manager_items,parent,false);
                } else v = convertView;
    
                ViewHolder h = (ViewHolder) v.getTag();
                if (h == null) {
                    h = new ViewHolder(Objects.requireNonNull(activity.findViewById(R.id.itemIcon)),Objects.requireNonNull(activity.findViewById(R.id.fileName)),Objects.requireNonNull(activity.findViewById(R.id.fileInfo)));
                    v.setTag(h);
                }

/**********************
**Error occurred here**
**********************/

                    h.fileIcon.setimageDrawable(getData1(position));
                    h.fileName.setText(getData(position).substring(getData(position).lastIndexOf("/")));
                    h.fileInfo.setText(getData2(position));
                return v;
            }
    
            private static final class ViewHolder {
                public final AppCompatimageView fileIcon;
                public final AppCompatTextView fileName;
                public final AppCompatTextView fileInfo;
    
                public ViewHolder(@NonNull final AppCompatimageView fileIcon,@NonNull final AppCompatTextView fileName,@NonNull final AppCompatTextView fileInfo) {
                    this.fileIcon = fileIcon;
                    this.fileName = fileName;
                    this.fileInfo = fileInfo;
                }
            }
    
            @NonNull
            @Override
            public final String toString() {
                return "FileAdaptor{" +
                        "data=" + data +
                        ",activity=" + activity +
                        '}';
            }
        }

看起来目前一切正常。但是,当我尝试在适配器的getView方法中为文本视图调用setText时,应用程序崩溃了,输出java.lang.NullPointerException,但在此之前我已经叫过findViewById。

后来,我为ViewHold中的对象标注了NonNull,为findViewById标注了Objects.requireNonNull,但是仍然发生错误错误输出如下所示:

<?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="wrap_content"
    android:layout_centerInParent="true"
    android:orientation="horizontal">

    <androidx.appcompat.widget.AppCompatimageView
        android:id="@+id/itemIcon"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal|center_vertical"
        android:layout_weight="1"
        android:gravity="center" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left|start"
        android:layout_weight="10"
        android:gravity="start"
        android:orientation="vertical">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/fileName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/contents_title"
            android:textSize="18sp" />

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/fileInfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/contents" />
    </LinearLayout>
</LinearLayout>

谁能帮助我解决这个问题

解决方法

您的代码应该是这样的,因为视图是适配器布局的一部分,而不是活动布局的一部分。

h = new ViewHolder(Objects.requireNonNull(v.findViewById(R.id.itemIcon)),Objects.requireNonNull(v.findViewById(R.id.fileName)),Objects.requireNonNull(v.findViewById(R.id.fileInfo)));
       

  
,

替换此:

 h = new ViewHolder(Objects.requireNonNull(activity.findViewById(R.id.itemIcon)),Objects.requireNonNull(activity.findViewById(R.id.fileName)),Objects.requireNonNull(activity.findViewById(R.id.fileInfo)));

收件人:

h = new ViewHolder(Objects.requireNonNull(v.findViewById(R.id.itemIcon)),Objects.requireNonNull(v.findViewById(R.id.fileInfo)));

因为您必须在项目视图中找到子项目

,

findViewById可以返回Nullable对象,因此不会使您脱离NPE。

您之所以会获得NPE,是因为您尝试通过活动布局中的findViewById来扩大视图,并且它们实际上位于由convertView表示的项目布局中。

因此,如下更改activityconverView

h = new ViewHolder(Objects.requireNonNull(converView.findViewById(R.id.itemIcon)),Objects.requireNonNull(converView.findViewById(R.id.fileName)),Objects.requireNonNull(converView.findViewById(R.id.fileInfo)));