首先,我将解释问题的目的和背景。然后,我将为您提供一些有关如何实现此功能的概述。我将再次给您一些解释的代码。最后,我将向您展示输出的Java异常,并清楚地询问您我的问题。
由于使用了一些区分功能的REST API,我从网上得到了一些消息。我想在片段的ListView
中显示每个新闻。
我创建了对新闻进行建模的布局。它包含一个用于托管新闻图片的ImageView
和一些用于托管标题,描述等的TextView
。
我创建了ArrayAdapter
,它重新使用了此布局并填充了其小部件。
我设置了REST API调用,以在JSONArray中获取JSONObject。后者将转换为新闻对象列表。 ArrayAdapter
使用此列表(请参阅2。)。
ArrayAdapter
NB:在下面的代码中,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;
}
}
ArrayAdapter
设置ListView
NB:在下面的代码中,R.layout.world_news_list_item
(是对新闻进行建模的布局)将在ArrayAdapter
的构造函数中使用(见上文)。
list_view.setAdapter(new NewsAdapter(context, R.layout.world_news_list_item, News.toArrayList(news)));
(在HTTP成功(和响应成功)的情况下,写在API REST调用的回调中)。
片段的布局包含一个ListView
,它被夸大为list_view
。
当我启动包含ListView
的片段时,将输出此异常:
E / Android运行时:致命异常:主要 流程:com.example.xxx.xxx,PID:31843 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“ android.view.View android.view.View.findViewById(int)” 在com.example.xxx.xxx.NewsAdapter.getView(NewsAdapter.java:25) 在android.widget.AbsListView.obtainView(AbsListView.java:3189) 在android.widget.ListView.makeAndAddView(ListView.java:2197) 在android.widget.ListView.fillDown(ListView.java:824) 在android.widget.ListView.fillFromTop(ListView.java:885) 在android.widget.ListView.layoutChildren(ListView.java:1952) 在android.widget.AbsListView.onLayout(AbsListView.java:2961) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1915) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 在android.widget.FrameLayout.onLayout(FrameLayout.java:261) 在android.widget.ScrollView.onLayout(ScrollView.java:2492) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1171) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 在android.widget.FrameLayout.onLayout(FrameLayout.java:261) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791) 在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635) 在android.widget.LinearLayout.onLayout(LinearLayout.java:1544) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 在android.widget.FrameLayout.onLayout(FrameLayout.java:261) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791) 在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635) 在android.widget.LinearLayout.onLayout(LinearLayout.java:1544) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 在android.widget.FrameLayout.onLayout(FrameLayout.java:261) 在com.android.internal.policy.DecorView.onLayout(DecorView.java:945) 在android.view.View.layout(View.java:20854) 在android.view.ViewGroup.layout(ViewGroup.java:6401) 在android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2919) 在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2606) 在android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1743) 在android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:7780) 在android.view.Choreographer $ CallbackRecord.run(Choreographer.java:911) 在android.view.Choreographer.doCallbacks(Choreographer.java:723) 在android.view.Choreographer.doFrame(Choreographer.java:658) 在android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:897) 在android.os.Handler.handleCallback(Handler.java:789) 在android.os.Handler.dispatchMessage(Handler.java:98) 在android.os.Looper.loop(Looper.java:164) 在android.app.ActivityThread.main(ActivityThread.java:6944) 在java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:327) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
由于resource
的值设置为R.layout.world_news_list_item
(在ArrayAdapter
中),这是对新闻进行建模的布局,所以convertView
{{1}为什么}(也在null
中)?
换句话说:为什么我必须写类似ArrayAdapter
的东西?
答案 0 :(得分:2)
您需要自己为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所述自己进行布局创建。另外,您也可以检查here是否使用各种适配器。 here也可以找到另一本很棒的ListView
教程。
建议:
学习使用RecyclerView
。它更复杂,但是比简单的ListView
强大得多。