【发布时间】:2021-02-19 13:45:24
【问题描述】:
我想在 Android 设备上创建一个文件管理器,并在我的文件管理器中创建了一个自定义适配器作为 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 +
'}';
}
}
下面是ListView中适配器的布局文件。
<?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>
这是 Activity 的布局文件,其中包括 listView。
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fileManagerContentView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/fileManagerBottomBar">
<ListView
android:id="@+id/mainContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>
<LinearLayout
android:id="@+id/fileManagerBottomBar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/back"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="@drawable/arrow_back" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/next"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="@drawable/arrow_next" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/create"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="@drawable/create" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/refreshContents"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="@drawable/reload" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/parentFolder"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="@drawable/up_dir" />
</LinearLayout>
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/navigation_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
现在看起来一切正常。但是,当我尝试在适配器的 getView 方法中为我的文本视图调用 setText 时,应用程序崩溃了,并输出 java.lang.NullPointerException,但在此之前我已经调用了 findViewById。
后来我为ViewHold中的对象注解了NonNull,为findViewById注解了Objects.requireNonNull,但是仍然出现错误,错误输出如下
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at com.example.filemanager.MainActivity$FileAdaptor.getView(MainActivity.java:500)
at android.widget.AbsListView.obtainView(AbsListView.java:3271)
at android.widget.ListView.makeAndAddView(ListView.java:2238)
at android.widget.ListView.fillDown(ListView.java:838)
at android.widget.ListView.fillFromTop(ListView.java:900)
at android.widget.ListView.layoutChildren(ListView.java:1974)
at android.widget.AbsListView.onLayout(AbsListView.java:3041)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1818)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1584)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:1059)
at android.view.View.layout(View.java:23754)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3679)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3139)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2200)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8960)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:996)
at android.view.Choreographer.doCallbacks(Choreographer.java:794)
at android.view.Choreographer.doFrame(Choreographer.java:729)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:981)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)
谁能帮我解决这个问题
【问题讨论】:
-
在 setText 周围使用 try-catch 可以避免 NullPointerException 崩溃,但并不能解决这个问题。
-
getView 方法的第 500 行究竟写了什么?
-
getView 中写的东西在我上面给出的 FileAdaptor 中,FileAdaptor 是 MainActivity 的一个内部类
-
错误给出了一个特定的行号,我不知道哪个行号是什么。你给我整个方法的事实对我没有帮助,除非你告诉我哪一行在哪里
标签: java android android-layout listview android-listview