Android: Adapter 的viewconvert 为null,但我传递了正确的layout

Android: Adapter's viewconvert is null, but I passed the correct layout

总结

首先,我将解释我的问题的目的和背景。然后,我将向您概括介绍一下我是如何实现此功能的。我会再次给你一些解释的代码。最后,我将向您展示输出 Java 异常并清楚地问您我的问题。


目标和背景

多亏了 REST API,我从网上得到了一些消息,使用了一些有区别的功能。我想在我的片段 ListView.

中显示每个新闻

实施

解释

  1. 我创建了一个新闻模型的布局。它包含一个 ImageView 用于承载新闻图像,还有一些 TextView 用于承载标题、描述等。

  2. 我创建了 ArrayAdapter,它重用了这个布局并填充了它的小部件。

  3. 我设置了 REST API 调用以获取 JSONArray 中的 JSONObject。后者转换为新闻列表objects。 ArrayAdapter(参见 2.)使用此列表。

来源

ArrayAdapter

注意:在下面的代码中,resource的值设置为R.layout.world_news_list_item,这是模型化新闻的布局。

public class NewsAdapter extends ArrayAdapter<News> {
    private List<News> news;

    NewsAdapter(@NonNull Context context, int resource, @NonNull List<News> objects) {
        super(context, resource, objects);
        this.news = objects;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {

        News news = this.news.get(position);

        TextView textTitle = convertView.findViewById(R.id.world_news_item_title);
        textTitle.setText(news.getTitle());

        return convertView;
    }

}

片段的部分:为片段的 ListView

设置 ArrayAdapter

注意:在下面的代码中,R.layout.world_news_list_item 是对新闻进行建模的布局,将在 ArrayAdapter 的构造函数中使用(参见前面)。

list_view.setAdapter(new NewsAdapter(context, R.layout.world_news_list_item, News.toArrayList(news)));

(写在 API HTTP 成功(和响应成功)时 REST 调用的回调中。

该片段的布局包含一个 ListView,它被膨胀成 list_view


输出异常&问题

输出异常

当我启动包含 ListView 的片段时,输出此异常:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.xxx.xxx, PID: 31843 java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference at com.example.xxx.xxx.NewsAdapter.getView(NewsAdapter.java:25) at android.widget.AbsListView.obtainView(AbsListView.java:3189) at android.widget.ListView.makeAndAddView(ListView.java:2197) at android.widget.ListView.fillDown(ListView.java:824) at android.widget.ListView.fillFromTop(ListView.java:885) at android.widget.ListView.layoutChildren(ListView.java:1952) at android.widget.AbsListView.onLayout(AbsListView.java:2961) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1915) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at android.widget.ScrollView.onLayout(ScrollView.java:2492) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1171) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635) at android.widget.LinearLayout.onLayout(LinearLayout.java:1544) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635) at android.widget.LinearLayout.onLayout(LinearLayout.java:1544) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at com.android.internal.policy.DecorView.onLayout(DecorView.java:945) at android.view.View.layout(View.java:20854) at android.view.ViewGroup.layout(ViewGroup.java:6401) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2919) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2606) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1743) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7780) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) at android.view.Choreographer.doCallbacks(Choreographer.java:723) at android.view.Choreographer.doFrame(Choreographer.java:658) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) 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)

问题

既然resource的值设置为R.layout.world_news_list_item(在ArrayAdapter中),这是模型化新闻的布局,为什么convertView null(也在ArrayAdapter中)?

换句话说:为什么我一定要写成if(convertView == null) { inflate_world_news_list_item_layout(); }

您需要自己为 ListView 行 增加 视图。这就是为什么您需要这样的代码:

public class NewsAdapter extends ArrayAdapter<News> {
    private List<News> news;

    NewsAdapter(@NonNull Context context, int resource, @NonNull List<News> objects) {
        super(context, resource, objects);
        this.news = objects;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.list_item, container, false);
        }

        News news = this.news.get(position);

        TextView textTitle = convertView.findViewById(R.id.world_news_item_title);
        textTitle.setText(news.getTitle());

        return convertView;
    }

}

所有ListView在android中都是这样,这是他们的力量。您可以使用自己的布局自定义每一行。请记住,在您的情况下,您已经覆盖了 getView,因此您也需要按照 here. In addition, you can check here too for using various adapters. Another great ListView tutorial can be found here 所述自己进行布局创建。

建议:

学习使用RecyclerView。它更复杂,但比简单的 ListView.

强大得多