我的对象不为空,但我得到一个 NULL POINTER EXCEPTION
My object is not null but I'm getting a NULL POINTER EXCEPTION
出于某种原因,当它确实不为空时,我得到一个指向 videosFound 的空指针异常。甚至传入的参数 adapter 也不为空。我只是通过打印出它是否为空(它们都不为空)来检查和验证这一点。那么有人可以告诉我我是如何得到这个错误的吗?
private ListView videosFound;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
searchInput = (EditText)findViewById(R.id.search_input);
videosFound = (ListView)findViewById(R.id.videos_found);
handler = new Handler();
addClickListener();
searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
searchOnYoutube(v.getText().toString());
return false;
}
return true;
}
});
}
private void updateVideosFound(){
ArrayAdapter<VideoItem> adapter = new ArrayAdapter<VideoItem>(getApplicationContext(), R.layout.video_item, searchResults){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getLayoutInflater().inflate(R.layout.video_item, parent, false);
}
ImageView thumbnail = (ImageView)convertView.findViewById(R.id.video_thumbnail);
TextView title = (TextView)convertView.findViewById(R.id.video_title);
TextView description = (TextView)convertView.findViewById(R.id.video_description);
VideoItem searchResult = searchResults.get(position);
Picasso.with(getApplicationContext()).load(searchResult.getThumbnailURL()).into(thumbnail);
title.setText(searchResult.getTitle());
description.setText(searchResult.getDescription());
return convertView;
}
};
if(videosFound == null){
System.out.println("videoFound is null***********");
}else{
System.out.println("videoFound is NOT null***********");
}
if(adapter == null){
System.out.println("adapter is null***********");
}else{
System.out.println("adapter is NOT null***********");
}
videosFound.setAdapter(adapter);//ERROR HERE. neither videosFound no adapter are null
}
private void addClickListener(){
videosFound.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> av, View v, int pos,
long id) {
Intent intent = new Intent(getApplicationContext(), PlayerActivity.class);
intent.putExtra("VIDEO_ID", searchResults.get(pos).getId());
startActivity(intent);
}
});
}
XML
<?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="match_parent"
android:orientation="vertical" >
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search"
android:id="@+id/search_input"
android:singleLine="true" />
<ListView
android:id="@+id/videos_found"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="5dp" />
</LinearLayout>
控制台:
03-24 18:04:31.833 17014-17440/com.example.shawn.myyoutube D/YC: Could not search: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.",
"reason" : "ipRefererBlocked",
"extendedHelp" : "https://console.developers.google.com"
} ],
"message" : "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."
}
03-24 18:04:31.833 17014-17014/com.example.shawn.myyoutube I/System.out: videoFound is NOT null***********
03-24 18:04:31.833 17014-17014/com.example.shawn.myyoutube I/System.out: adapter is NOT null***********
03-24 18:04:31.843 17014-17014/com.example.shawn.myyoutube D/AndroidRuntime: Shutting down VM
03-24 18:04:31.843 17014-17014/com.example.shawn.myyoutube E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.shawn.myyoutube, PID: 17014
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
at android.widget.ListView.setAdapter(ListView.java:502)
at com.example.shawn.myyoutube.SearchActivity.updateVideosFound(SearchActivity.java:98)
at com.example.shawn.myyoutube.SearchActivity.access0(SearchActivity.java:23)
at com.example.shawn.myyoutube.SearchActivity.run(SearchActivity.java:61)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
在堆栈跟踪中我看到了这个:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
适配器正试图在空 List
上调用 size()
。确保您的列表 searchResults
不为空。
NullPointerException
发生是因为 searchResults
未初始化并且是 null
。
关于评论中的问题 -
do you know why the error did not actually point to the line where
searchResults was?
每当您调用 setAdapter()
或使用 notifyDataSetChanged()
刷新已创建的适配器时,ArrayAdapter
会在内部调用 getCount()
。
在您调用 setAdapter()
或 notifyDataSetChanged()
之前,ArrayAdapter
不会为您创建视图,为了创建视图,它需要检查您传递给它的数据的大小。
为此,它调用 getCount()
这是
public int getCount() {
return mObjects.size();
}
其中 mObjects
被初始化为您在创建适配器时传递的数据列表。
显然 mObjects.size()
会抛出 NullPointerException
因为 mObjects
是 null
因为 searchResults
是空的。
希望你明白。
出于某种原因,当它确实不为空时,我得到一个指向 videosFound 的空指针异常。甚至传入的参数 adapter 也不为空。我只是通过打印出它是否为空(它们都不为空)来检查和验证这一点。那么有人可以告诉我我是如何得到这个错误的吗?
private ListView videosFound;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
searchInput = (EditText)findViewById(R.id.search_input);
videosFound = (ListView)findViewById(R.id.videos_found);
handler = new Handler();
addClickListener();
searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
searchOnYoutube(v.getText().toString());
return false;
}
return true;
}
});
}
private void updateVideosFound(){
ArrayAdapter<VideoItem> adapter = new ArrayAdapter<VideoItem>(getApplicationContext(), R.layout.video_item, searchResults){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getLayoutInflater().inflate(R.layout.video_item, parent, false);
}
ImageView thumbnail = (ImageView)convertView.findViewById(R.id.video_thumbnail);
TextView title = (TextView)convertView.findViewById(R.id.video_title);
TextView description = (TextView)convertView.findViewById(R.id.video_description);
VideoItem searchResult = searchResults.get(position);
Picasso.with(getApplicationContext()).load(searchResult.getThumbnailURL()).into(thumbnail);
title.setText(searchResult.getTitle());
description.setText(searchResult.getDescription());
return convertView;
}
};
if(videosFound == null){
System.out.println("videoFound is null***********");
}else{
System.out.println("videoFound is NOT null***********");
}
if(adapter == null){
System.out.println("adapter is null***********");
}else{
System.out.println("adapter is NOT null***********");
}
videosFound.setAdapter(adapter);//ERROR HERE. neither videosFound no adapter are null
}
private void addClickListener(){
videosFound.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> av, View v, int pos,
long id) {
Intent intent = new Intent(getApplicationContext(), PlayerActivity.class);
intent.putExtra("VIDEO_ID", searchResults.get(pos).getId());
startActivity(intent);
}
});
}
XML
<?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="match_parent"
android:orientation="vertical" >
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search"
android:id="@+id/search_input"
android:singleLine="true" />
<ListView
android:id="@+id/videos_found"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="5dp" />
</LinearLayout>
控制台:
03-24 18:04:31.833 17014-17440/com.example.shawn.myyoutube D/YC: Could not search: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.",
"reason" : "ipRefererBlocked",
"extendedHelp" : "https://console.developers.google.com"
} ],
"message" : "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."
}
03-24 18:04:31.833 17014-17014/com.example.shawn.myyoutube I/System.out: videoFound is NOT null***********
03-24 18:04:31.833 17014-17014/com.example.shawn.myyoutube I/System.out: adapter is NOT null***********
03-24 18:04:31.843 17014-17014/com.example.shawn.myyoutube D/AndroidRuntime: Shutting down VM
03-24 18:04:31.843 17014-17014/com.example.shawn.myyoutube E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.shawn.myyoutube, PID: 17014
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
at android.widget.ListView.setAdapter(ListView.java:502)
at com.example.shawn.myyoutube.SearchActivity.updateVideosFound(SearchActivity.java:98)
at com.example.shawn.myyoutube.SearchActivity.access0(SearchActivity.java:23)
at com.example.shawn.myyoutube.SearchActivity.run(SearchActivity.java:61)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
在堆栈跟踪中我看到了这个:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
适配器正试图在空 List
上调用 size()
。确保您的列表 searchResults
不为空。
NullPointerException
发生是因为 searchResults
未初始化并且是 null
。
关于评论中的问题 -
每当您调用do you know why the error did not actually point to the line where searchResults was?
setAdapter()
或使用 notifyDataSetChanged()
刷新已创建的适配器时,ArrayAdapter
会在内部调用 getCount()
。
在您调用 setAdapter()
或 notifyDataSetChanged()
之前,ArrayAdapter
不会为您创建视图,为了创建视图,它需要检查您传递给它的数据的大小。
为此,它调用 getCount()
这是
public int getCount() {
return mObjects.size();
}
其中 mObjects
被初始化为您在创建适配器时传递的数据列表。
显然 mObjects.size()
会抛出 NullPointerException
因为 mObjects
是 null
因为 searchResults
是空的。
希望你明白。