Android 使用 Volley 的 ListAdapter NullPointerException
Android ListAdapter NullPointerException using Volley
当我的 ListAdapter 在初始化后调用 getCount() 时,我 运行 陷入了获取 NPE 的永久性问题。我使用 Volley 填充了我的 "Sound" 项数组,但应用程序仍然在启动时崩溃。
我一直在使用本教程寻求帮助:http://www.androidhive.info/2014/06/android-facebook-like-custom-listview-feed-using-volley/。我的应用程序的棘手之处在于我必须在片段内完成所有操作,因为我有一个选项卡式界面,并且我尝试构建的提要托管在一个选项卡中。
下面是我的代码:
相关代码来自LandingActivity.java:
Tab tab = actionBar.newTab()
.setIcon(R.drawable.feed_icon)
.setTabListener(new TabListener<SoundFragment>(this, "feed", SoundFragment.class));
actionBar.addTab(tab);
我的 SoundFragment.java 文件:
public class SoundFragment extends ListFragment {
private static final String TAG = "SoundFragment";
private ArrayList<Sound> mSounds;
private AudioRecorder mPlayer = new AudioRecorder();
private ImageButton mImageButton;
SoundAdapter adapter;
private String URL_FEED = "http://puncture.org/wavesdemo/feed.json";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_sound, parent, false);
return v;
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// First check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
if (entry != null) {
// Fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONObject(data));
Log.w("DEBUG", "JSON feed parsed from cache!");
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
Log.w("DEBUG", "UnsupportedEncodingException");
e.printStackTrace();
}
} else {
// making fresh volley request and getting JSON
Log.w("DEBUG", "onResponse method hit within JsonObjectRequest");
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.w("DEBUG", "onResponse method hit within JsonObjectRequest");
VolleyLog.d(TAG, "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.w("DEBUG", "onErrorResponse method hit within JsonObjectRequest");
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
Log.w("DEBUG", "AppController getInstance request queue thing hit.");
}
Log.w("DEBUG", "Made it to the end!!");
adapter = new SoundAdapter(getActivity(), com.littlecloudcollective.waves.R.layout.fragment_sound_item, mSounds);
setListAdapter(adapter);
Log.w("DEBUG", "ListAdapter set!");
}
/** * Parsing JSON response and passing the data to feed view list adapter * */
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
Sound s = new Sound();
s.setId(feedObj.getInt("sound_id"));
s.setSound(feedObj.getString("sound"));
Log.w("DEBUG", feedObj.getString("sound"));
s.setSoundViz(feedObj.getString("sound_viz"));
Log.w("DEBUG", feedObj.getString("sound_viz"));
s.setLocation(feedObj.getString("location"));
// Title might be null sometimes
String feedTime = feedObj.isNull("title") ? null : feedObj
.getString("title");
s.setTitle(feedTime);
s.setTime(feedObj.getString("time"));
s.setLatitude(feedObj.getDouble("latitude"));
s.setLongitude(feedObj.getDouble("longitude"));
s.setUserId(feedObj.getString("user_id"));
s.setUsername(feedObj.getString("username"));
//Profile photo might be null sometimes
String image = feedObj.isNull("profile_photo") ? null : feedObj
.getString("profile_photo");
s.setProfilePhoto(image);
mSounds.add(s); }
// Notify data changes to list adapter
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
还有我的SoundAdapter.javaclass:
public class SoundAdapter extends ArrayAdapter<Sound> {
private Activity activity;
private LayoutInflater inflater;
private ArrayList<Sound> feedItems;
private Date now = new Date();
private long now1 = now.getTime();
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public SoundAdapter(Context context, int resource, ArrayList<Sound> feedItems) {
super(context, resource, feedItems);
Log.w("DEBUG", "It made it to the SoundAdapter creation!");
this.activity = activity;
this.feedItems = feedItems;
}
@Override
public int getCount() {
Log.w("DEBUG", "Now it's trying to getCount! Cue the crash.");
return feedItems.size();
}
@Override
public Sound getItem(int location) {
return feedItems.get(location);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.fragment_sound_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
Sound s = getItem(position);
TextView titleTextView = (TextView) convertView.findViewById(R.id.sound_title);
titleTextView.setText(s.getTitle().toString());
TextView usernameTextView = (TextView)convertView.findViewById(R.id.username_label);
usernameTextView.setText(s.getUsername().toString());
TextView locationTextView = (TextView)convertView.findViewById(R.id.sound_location);
locationTextView.setText(s.getLocation().toString());
String timestamp = (String) DateUtils.getRelativeTimeSpanString(Long.parseLong(s.getTime()), System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS);
TextView timeTextView = (TextView)convertView.findViewById(R.id.time_label);
timeTextView.setText(timestamp);
FeedImageView mSoundVizView = (FeedImageView) convertView.findViewById(R.id.sound_vis);
ImageView mapImageView = new ImageView(activity);
Picasso.with(activity)
.load("https://maps.googleapis.com/maps/api/staticmap?center=Rio+de+Janeiro,Brazil&zoom=11&size=250x150")
.into(mapImageView);
NetworkImageView profilePhotoView = (NetworkImageView) convertView.findViewById(R.id.profile_photo);
// Chcek for empty status message
if (!TextUtils.isEmpty(s.getTitle())) {
titleTextView.setText(s.getTitle());
titleTextView.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
titleTextView.setVisibility(View.GONE);
}
// user profile pic
profilePhotoView.setImageUrl(s.getProfilePhoto(), imageLoader);
// Feed image
if (s.getSoundViz() != null) {
mSoundVizView.setImageUrl(s.getSoundViz(), imageLoader);
mSoundVizView.setVisibility(View.VISIBLE);
mSoundVizView
.setResponseObserver(new FeedImageView.ResponseObserver() {
@Override
public void onError() {
}
@Override
public void onSuccess() {
}
});
} else {
mSoundVizView.setVisibility(View.GONE);
}
return convertView;
}
}
然后这是我的 XML 文件:
在fragment_sound_item.xml中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/pin_map_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignBottom="@+id/sound_location"
android:layout_alignParentLeft="true"
android:paddingBottom="2dp"
android:src="@drawable/pin_map_icon" />
<TextView
android:id="@+id/sound_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignRight="@+id/sound_title"
android:layout_marginTop="20dp"
android:text="@string/sound_location_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/time_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/sound_location"
android:layout_alignBottom="@+id/sound_location"
android:layout_alignParentRight="true"
android:text="@string/sound_time_label"
android:layout_marginRight="5dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:orientation="vertical"
android:layout_marginTop="45dp"
android:layout_marginBottom="10dp" >
<com.littlecloudcollective.waves.FeedImageView
android:id="@+id/sound_map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<ImageButton
android:id="@+id/sound_vis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@null"
android:cropToPadding="true"
android:scaleType="fitStart"
android:src="@drawable/sound_vis_2" />
</LinearLayout>
<TextView
android:id="@+id/username_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/container"
android:layout_marginLeft="8dp"
android:text="@string/user_username_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/sound_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider"
android:layout_marginBottom="10dp"
android:layout_marginLeft="8dp"
android:paddingBottom="20dp"
android:text="@string/sound_title_label"
android:textSize="14sp" />
<ImageView
android:id="@+id/divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/username_label"
android:layout_below="@+id/username_label"
android:src="@drawable/divider" />
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/profile_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/time_label"
android:layout_below="@+id/container"
android:src="@drawable/default_profile_thumbnail" />
</RelativeLayout>
和fragment_sound.xml:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@android:id/list" />
这是我遇到的错误:
02-19 14:02:11.229: W/DEBUG(20532): onResponse method hit within JsonObjectRequest
02-19 14:02:11.239: W/DEBUG(20532): AppController getInstance request queue thing hit.
02-19 14:02:11.239: W/DEBUG(20532): Made it to the end!!
02-19 14:02:11.239: W/DEBUG(20532): It made it to the SoundAdapter creation!
02-19 14:02:11.239: W/DEBUG(20532): ListAdapter set!
02-19 14:02:11.289: D/AbsListView(20532): Get MotionRecognitionManager
02-19 14:02:11.319: W/DEBUG(20532): Now it's trying to getCount! Cue the crash.
02-19 14:02:11.319: D/AndroidRuntime(20532): Shutting down VM
02-19 14:02:11.319: W/dalvikvm(20532): threadid=1: thread exiting with uncaught exception (group=0x41764438)
02-19 14:02:11.319: E/AndroidRuntime(20532): FATAL EXCEPTION: main
02-19 14:02:11.319: E/AndroidRuntime(20532): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.littlecloudcollective.waves/com.littlecloudcollective.waves.LandingActivity}: java.lang.NullPointerException
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2114)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.access0(ActivityThread.java:143)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.os.Handler.dispatchMessage(Handler.java:99)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.os.Looper.loop(Looper.java:137)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.main(ActivityThread.java:4963)
02-19 14:02:11.319: E/AndroidRuntime(20532): at java.lang.reflect.Method.invokeNative(Native Method)
02-19 14:02:11.319: E/AndroidRuntime(20532): at java.lang.reflect.Method.invoke(Method.java:511)
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
02-19 14:02:11.319: E/AndroidRuntime(20532): at dalvik.system.NativeStart.main(Native Method)
02-19 14:02:11.319: E/AndroidRuntime(20532): Caused by: java.lang.NullPointerException
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.littlecloudcollective.waves.SoundAdapter.getCount(SoundAdapter.java:42)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.widget.ListView.setAdapter(ListView.java:466)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.support.v4.app.ListFragment.setListAdapter(ListFragment.java:182)
次要错误,在对上下文进行 activity 更改并更新 SoundAdapter 中的 this.feedItems 位之后:
02-19 14:46:21.479: E/AndroidRuntime(21538): Caused by: java.lang.NullPointerException
02-19 14:46:21.479: E/AndroidRuntime(21538): at com.littlecloudcollective.waves.SoundAdapter.<init>(SoundAdapter.java:36)
02-19 14:46:21.479: E/AndroidRuntime(21538): at com.littlecloudcollective.waves.SoundFragment.onCreate(SoundFragment.java:97)
02-19 14:46:21.479: E/AndroidRuntime(21538): at android.support.v4.app.Fragment.performCreate(Fragment.java:1477)
这是我的第一个 Android 应用程序,所以我怀疑我在某个地方搞混了 Fragments。任何帮助将不胜感激。谢谢!
永远避免做
this.feedItems = feedItems;
这样更好:
//Initialize your List
private ArrayList<Sound> feedItems = new ArrayList<Sound>();
public SoundAdapter(Context context, int resource, ArrayList<Sound> feedItems) {
super(context, resource, feedItems);
this.feedItems.clear();
this.feedItems.addAll(feedItems);
}
这样 feedItems
将永远不会指向 null
对象。
您忘记初始化 mSounds
列表。在设置适配器之前将此行添加到您的 onCreate
方法中。当您调用 parseJsonFeed
时,还要确保您的适配器不为空。也许这就是您得到的 NPE。只是为了确保您应该先创建适配器:
@Override
public void onCreate(Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
// First check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
mSounds = new ArrayList<Sound>(); //<-- Add this line so your list is not null
//And initialize your adapter from the beggining
adapter = new SoundAdapter(getActivity(), com.littlecloudcollective.waves.R.layout.fragment_sound_item, mSounds);
setListAdapter(adapter);
Log.w("DEBUG", "ListAdapter set!");
...
}
当我的 ListAdapter 在初始化后调用 getCount() 时,我 运行 陷入了获取 NPE 的永久性问题。我使用 Volley 填充了我的 "Sound" 项数组,但应用程序仍然在启动时崩溃。
我一直在使用本教程寻求帮助:http://www.androidhive.info/2014/06/android-facebook-like-custom-listview-feed-using-volley/。我的应用程序的棘手之处在于我必须在片段内完成所有操作,因为我有一个选项卡式界面,并且我尝试构建的提要托管在一个选项卡中。
下面是我的代码:
相关代码来自LandingActivity.java:
Tab tab = actionBar.newTab()
.setIcon(R.drawable.feed_icon)
.setTabListener(new TabListener<SoundFragment>(this, "feed", SoundFragment.class));
actionBar.addTab(tab);
我的 SoundFragment.java 文件:
public class SoundFragment extends ListFragment {
private static final String TAG = "SoundFragment";
private ArrayList<Sound> mSounds;
private AudioRecorder mPlayer = new AudioRecorder();
private ImageButton mImageButton;
SoundAdapter adapter;
private String URL_FEED = "http://puncture.org/wavesdemo/feed.json";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_sound, parent, false);
return v;
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// First check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
if (entry != null) {
// Fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONObject(data));
Log.w("DEBUG", "JSON feed parsed from cache!");
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
Log.w("DEBUG", "UnsupportedEncodingException");
e.printStackTrace();
}
} else {
// making fresh volley request and getting JSON
Log.w("DEBUG", "onResponse method hit within JsonObjectRequest");
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
URL_FEED, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.w("DEBUG", "onResponse method hit within JsonObjectRequest");
VolleyLog.d(TAG, "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.w("DEBUG", "onErrorResponse method hit within JsonObjectRequest");
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
Log.w("DEBUG", "AppController getInstance request queue thing hit.");
}
Log.w("DEBUG", "Made it to the end!!");
adapter = new SoundAdapter(getActivity(), com.littlecloudcollective.waves.R.layout.fragment_sound_item, mSounds);
setListAdapter(adapter);
Log.w("DEBUG", "ListAdapter set!");
}
/** * Parsing JSON response and passing the data to feed view list adapter * */
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
Sound s = new Sound();
s.setId(feedObj.getInt("sound_id"));
s.setSound(feedObj.getString("sound"));
Log.w("DEBUG", feedObj.getString("sound"));
s.setSoundViz(feedObj.getString("sound_viz"));
Log.w("DEBUG", feedObj.getString("sound_viz"));
s.setLocation(feedObj.getString("location"));
// Title might be null sometimes
String feedTime = feedObj.isNull("title") ? null : feedObj
.getString("title");
s.setTitle(feedTime);
s.setTime(feedObj.getString("time"));
s.setLatitude(feedObj.getDouble("latitude"));
s.setLongitude(feedObj.getDouble("longitude"));
s.setUserId(feedObj.getString("user_id"));
s.setUsername(feedObj.getString("username"));
//Profile photo might be null sometimes
String image = feedObj.isNull("profile_photo") ? null : feedObj
.getString("profile_photo");
s.setProfilePhoto(image);
mSounds.add(s); }
// Notify data changes to list adapter
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
还有我的SoundAdapter.javaclass:
public class SoundAdapter extends ArrayAdapter<Sound> {
private Activity activity;
private LayoutInflater inflater;
private ArrayList<Sound> feedItems;
private Date now = new Date();
private long now1 = now.getTime();
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public SoundAdapter(Context context, int resource, ArrayList<Sound> feedItems) {
super(context, resource, feedItems);
Log.w("DEBUG", "It made it to the SoundAdapter creation!");
this.activity = activity;
this.feedItems = feedItems;
}
@Override
public int getCount() {
Log.w("DEBUG", "Now it's trying to getCount! Cue the crash.");
return feedItems.size();
}
@Override
public Sound getItem(int location) {
return feedItems.get(location);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.fragment_sound_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
Sound s = getItem(position);
TextView titleTextView = (TextView) convertView.findViewById(R.id.sound_title);
titleTextView.setText(s.getTitle().toString());
TextView usernameTextView = (TextView)convertView.findViewById(R.id.username_label);
usernameTextView.setText(s.getUsername().toString());
TextView locationTextView = (TextView)convertView.findViewById(R.id.sound_location);
locationTextView.setText(s.getLocation().toString());
String timestamp = (String) DateUtils.getRelativeTimeSpanString(Long.parseLong(s.getTime()), System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS);
TextView timeTextView = (TextView)convertView.findViewById(R.id.time_label);
timeTextView.setText(timestamp);
FeedImageView mSoundVizView = (FeedImageView) convertView.findViewById(R.id.sound_vis);
ImageView mapImageView = new ImageView(activity);
Picasso.with(activity)
.load("https://maps.googleapis.com/maps/api/staticmap?center=Rio+de+Janeiro,Brazil&zoom=11&size=250x150")
.into(mapImageView);
NetworkImageView profilePhotoView = (NetworkImageView) convertView.findViewById(R.id.profile_photo);
// Chcek for empty status message
if (!TextUtils.isEmpty(s.getTitle())) {
titleTextView.setText(s.getTitle());
titleTextView.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
titleTextView.setVisibility(View.GONE);
}
// user profile pic
profilePhotoView.setImageUrl(s.getProfilePhoto(), imageLoader);
// Feed image
if (s.getSoundViz() != null) {
mSoundVizView.setImageUrl(s.getSoundViz(), imageLoader);
mSoundVizView.setVisibility(View.VISIBLE);
mSoundVizView
.setResponseObserver(new FeedImageView.ResponseObserver() {
@Override
public void onError() {
}
@Override
public void onSuccess() {
}
});
} else {
mSoundVizView.setVisibility(View.GONE);
}
return convertView;
}
}
然后这是我的 XML 文件:
在fragment_sound_item.xml中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/pin_map_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignBottom="@+id/sound_location"
android:layout_alignParentLeft="true"
android:paddingBottom="2dp"
android:src="@drawable/pin_map_icon" />
<TextView
android:id="@+id/sound_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignRight="@+id/sound_title"
android:layout_marginTop="20dp"
android:text="@string/sound_location_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/time_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/sound_location"
android:layout_alignBottom="@+id/sound_location"
android:layout_alignParentRight="true"
android:text="@string/sound_time_label"
android:layout_marginRight="5dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:orientation="vertical"
android:layout_marginTop="45dp"
android:layout_marginBottom="10dp" >
<com.littlecloudcollective.waves.FeedImageView
android:id="@+id/sound_map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<ImageButton
android:id="@+id/sound_vis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@null"
android:cropToPadding="true"
android:scaleType="fitStart"
android:src="@drawable/sound_vis_2" />
</LinearLayout>
<TextView
android:id="@+id/username_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/container"
android:layout_marginLeft="8dp"
android:text="@string/user_username_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/sound_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider"
android:layout_marginBottom="10dp"
android:layout_marginLeft="8dp"
android:paddingBottom="20dp"
android:text="@string/sound_title_label"
android:textSize="14sp" />
<ImageView
android:id="@+id/divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/username_label"
android:layout_below="@+id/username_label"
android:src="@drawable/divider" />
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/profile_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/time_label"
android:layout_below="@+id/container"
android:src="@drawable/default_profile_thumbnail" />
</RelativeLayout>
和fragment_sound.xml:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@android:id/list" />
这是我遇到的错误:
02-19 14:02:11.229: W/DEBUG(20532): onResponse method hit within JsonObjectRequest
02-19 14:02:11.239: W/DEBUG(20532): AppController getInstance request queue thing hit.
02-19 14:02:11.239: W/DEBUG(20532): Made it to the end!!
02-19 14:02:11.239: W/DEBUG(20532): It made it to the SoundAdapter creation!
02-19 14:02:11.239: W/DEBUG(20532): ListAdapter set!
02-19 14:02:11.289: D/AbsListView(20532): Get MotionRecognitionManager
02-19 14:02:11.319: W/DEBUG(20532): Now it's trying to getCount! Cue the crash.
02-19 14:02:11.319: D/AndroidRuntime(20532): Shutting down VM
02-19 14:02:11.319: W/dalvikvm(20532): threadid=1: thread exiting with uncaught exception (group=0x41764438)
02-19 14:02:11.319: E/AndroidRuntime(20532): FATAL EXCEPTION: main
02-19 14:02:11.319: E/AndroidRuntime(20532): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.littlecloudcollective.waves/com.littlecloudcollective.waves.LandingActivity}: java.lang.NullPointerException
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2114)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.access0(ActivityThread.java:143)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.os.Handler.dispatchMessage(Handler.java:99)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.os.Looper.loop(Looper.java:137)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.app.ActivityThread.main(ActivityThread.java:4963)
02-19 14:02:11.319: E/AndroidRuntime(20532): at java.lang.reflect.Method.invokeNative(Native Method)
02-19 14:02:11.319: E/AndroidRuntime(20532): at java.lang.reflect.Method.invoke(Method.java:511)
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
02-19 14:02:11.319: E/AndroidRuntime(20532): at dalvik.system.NativeStart.main(Native Method)
02-19 14:02:11.319: E/AndroidRuntime(20532): Caused by: java.lang.NullPointerException
02-19 14:02:11.319: E/AndroidRuntime(20532): at com.littlecloudcollective.waves.SoundAdapter.getCount(SoundAdapter.java:42)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.widget.ListView.setAdapter(ListView.java:466)
02-19 14:02:11.319: E/AndroidRuntime(20532): at android.support.v4.app.ListFragment.setListAdapter(ListFragment.java:182)
次要错误,在对上下文进行 activity 更改并更新 SoundAdapter 中的 this.feedItems 位之后:
02-19 14:46:21.479: E/AndroidRuntime(21538): Caused by: java.lang.NullPointerException
02-19 14:46:21.479: E/AndroidRuntime(21538): at com.littlecloudcollective.waves.SoundAdapter.<init>(SoundAdapter.java:36)
02-19 14:46:21.479: E/AndroidRuntime(21538): at com.littlecloudcollective.waves.SoundFragment.onCreate(SoundFragment.java:97)
02-19 14:46:21.479: E/AndroidRuntime(21538): at android.support.v4.app.Fragment.performCreate(Fragment.java:1477)
这是我的第一个 Android 应用程序,所以我怀疑我在某个地方搞混了 Fragments。任何帮助将不胜感激。谢谢!
永远避免做
this.feedItems = feedItems;
这样更好:
//Initialize your List
private ArrayList<Sound> feedItems = new ArrayList<Sound>();
public SoundAdapter(Context context, int resource, ArrayList<Sound> feedItems) {
super(context, resource, feedItems);
this.feedItems.clear();
this.feedItems.addAll(feedItems);
}
这样 feedItems
将永远不会指向 null
对象。
您忘记初始化 mSounds
列表。在设置适配器之前将此行添加到您的 onCreate
方法中。当您调用 parseJsonFeed
时,还要确保您的适配器不为空。也许这就是您得到的 NPE。只是为了确保您应该先创建适配器:
@Override
public void onCreate(Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
// First check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(URL_FEED);
mSounds = new ArrayList<Sound>(); //<-- Add this line so your list is not null
//And initialize your adapter from the beggining
adapter = new SoundAdapter(getActivity(), com.littlecloudcollective.waves.R.layout.fragment_sound_item, mSounds);
setListAdapter(adapter);
Log.w("DEBUG", "ListAdapter set!");
...
}