我正在尝试按照此tutorial制作自定义列表适配器。当我的对象从我的JSON数据中获取项目并将其添加到列表中时,我遇到了麻烦。我已经能够使用简单的列表适配器和哈希映射。我想摆脱简单的列表适配器和哈希映射。这是我的堆栈跟踪:
10-31 13:17:19.985: E/AndroidRuntime(15047): FATAL EXCEPTION: main
10-31 13:17:19.985: E/AndroidRuntime(15047): java.lang.NullPointerException
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.almyz125.ammobot.MainActivity$ViewHolder.<init>(MainActivity.java:62)
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.almyz125.ammobot.MainActivity$FancyAdapter.getView(MainActivity.java:44)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.AbsListView.obtainView(AbsListView.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.ListView.measureHeightOfChildren(ListView.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.ListView.onMeasure(ListView.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.View.measure(View.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.RelativeLayout.measureChild(RelativeLayout.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.View.measure(View.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.View.measure(View.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.View.measure(View.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.View.measure(View.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.Choreographer$CallbackRecord.run(Choreographer.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.Choreographer.doCallbacks(Choreographer.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.Choreographer.doFrame(Choreographer.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.os.Handler.handleCallback(Handler.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.os.Handler.dispatchMessage(Handler.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.os.Looper.loop(Looper.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at android.app.ActivityThread.main(ActivityThread.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at java.lang.reflect.Method.invokeNative(Native Method)
10-31 13:17:19.985: E/AndroidRuntime(15047): at java.lang.reflect.Method.invoke(Method.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
10-31 13:17:19.985: E/AndroidRuntime(15047): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
10-31 13:17:19.985: E/AndroidRuntime(15047): at dalvik.system.NativeStart.main(Native Method)
这是我的main_activity:
package com.almyz125.ammobot;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private String apiURLBase, ammoCat;
private ProgressDialog pDialog;
ArrayList<Ammo> arrayJSONList = new ArrayList<Ammo>();
private JSONArray ammos;
private FancyAdapter fa = null;
public class Ammo {
public String href;
public String desc;
public String stock;
public String price;
public String rd;
}
public class FancyAdapter extends ArrayAdapter<Ammo> {
FancyAdapter() {
super(MainActivity.this, android.R.layout.simple_list_item_1,
arrayJSONList);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = new ViewHolder(convertView);
if (convertView == null) {
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.populateFrom(arrayJSONList.get(position));
return (convertView);
}
}
public class ViewHolder {
public TextView desc = null, href = null, round = null,
stock = null, price = null;
ViewHolder(View row) {
desc = (TextView) row.findViewById(R.id.desc);
href = (TextView) row.findViewById(R.id.href);
round = (TextView) row.findViewById(R.id.rd);
stock = (TextView) row.findViewById(R.id.stock);
price = (TextView) row.findViewById(R.id.price);
}
void populateFrom(Ammo r) {
desc.setText(r.desc);
href.setText(r.href);
round.setText(r.rd);
stock.setText(r.stock);
price.setText(r.price);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
apiURLBase = getString(R.string.api_base_url);
ammoCat = "22lr";
new GetJSONTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class GetJSONTask extends AsyncTask<String, Void, ArrayList<Ammo>> {
@Override
protected void onPreExecute() {
if (pDialog != null) {
pDialog.dismiss();
}
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Please wait..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
@Override
protected void onPostExecute(ArrayList<Ammo> valid) {
if (pDialog != null) {
pDialog.dismiss();
}
ListView lv = (ListView)findViewById(R.id.mainList);
fa = new FancyAdapter();
lv.setAdapter(fa);
}
@Override
protected ArrayList<Ammo> doInBackground(String... arg0) {
try {
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(apiURLBase + ammoCat);
ammos = json.getJSONArray(ammoCat);
//System.out.println(ammos.toString());
for (int i = 0; i < ammos.length(); i++) {
JSONObject json_data = ammos.getJSONObject(i);
Ammo resultRow = new Ammo();
resultRow.desc = json_data.getString("desc");
resultRow.href = json_data.getString("href");
resultRow.price = json_data.getString("price");
resultRow.stock = json_data.getString("stock");
resultRow.rd = json_data.getString("rd");
arrayJSONList.add(resultRow);
}
} catch (Exception e) {
Log.e(ammoCat, "Error:", e);
}
return arrayJSONList;
}
}
}
这是我的JSON解析器类:
package com.almyz125.ammobot;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
错误来自第62行,即第62行:
public class ViewHolder {
public TextView desc = null, href = null, round = null,
stock = null, price = null;
ViewHolder(View row) {
desc = (TextView) row.findViewById(R.id.desc);
href = (TextView) row.findViewById(R.id.href);
round = (TextView) row.findViewById(R.id.rd);
stock = (TextView) row.findViewById(R.id.stock);
price = (TextView) row.findViewById(R.id.price);
}
void populateFrom(Ammo r) {
desc.setText(r.desc);
href.setText(r.href);
round.setText(r.rd);
stock.setText(r.stock);
price.setText(r.price);
}
}
和这一行:
desc = (TextView) row.findViewById(R.id.desc);
新的适配器类:
public class FancyAdapter extends ArrayAdapter<Ammo> {
FancyAdapter() {
super(MainActivity.this, android.R.layout.simple_list_item_1,
arrayJSONList);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
holder = new ViewHolder(convertView);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.populateFrom(arrayJSONList.get(position));
return (convertView);
}
}
我现在正在获得这个堆栈:
10-31 13:30:27.065: E/AndroidRuntime(16085): FATAL EXCEPTION: main
10-31 13:30:27.065: E/AndroidRuntime(16085): java.lang.NullPointerException
10-31 13:30:27.065: E/AndroidRuntime(16085): at com.almyz125.ammobot.MainActivity$FancyAdapter.getView(MainActivity.java:53)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.AbsListView.obtainView(AbsListView.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.ListView.measureHeightOfChildren(ListView.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.ListView.onMeasure(ListView.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.View.measure(View.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.RelativeLayout.measureChild(RelativeLayout.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.View.measure(View.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.View.measure(View.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.View.measure(View.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.View.measure(View.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.Choreographer$CallbackRecord.run(Choreographer.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.Choreographer.doCallbacks(Choreographer.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.Choreographer.doFrame(Choreographer.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.os.Handler.handleCallback(Handler.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.os.Handler.dispatchMessage(Handler.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.os.Looper.loop(Looper.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at android.app.ActivityThread.main(ActivityThread.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at java.lang.reflect.Method.invokeNative(Native Method)
10-31 13:30:27.065: E/AndroidRuntime(16085): at java.lang.reflect.Method.invoke(Method.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
10-31 13:30:27.065: E/AndroidRuntime(16085): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
10-31 13:30:27.065: E/AndroidRuntime(16085): at dalvik.system.NativeStart.main(Native Method)
错误似乎在这里:
holder.populateFrom(arrayJSONList.get(position));
上述行仍然出现错误。
这是我现在的观点:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
convertView.setTag(holder);
holder = new ViewHolder(convertView);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.populateFrom(arrayJSONList.get(position));
return (convertView);
}
答案 0 :(得分:0)
尝试在onPostExecute
中设置适配器,因为您无法从工作线程更新UI。
@Override
protected void onPostExecute(ArrayList<Ammo> valid) {
if (pDialog != null) {
pDialog.dismiss();
}
ListView lv = (ListView)findViewById(R.id.mainList);
fa = new FancyAdapter();
lv.setAdapter(fa);
}
修改: - 定义Ammo
类,如下所示
public class Ammo {
public String href;
public String desc;
public String stock;
public String price;
public String rd;
public Ammo(String href, String desc, String stock, String price, String rd) {
this.href = href;
this.desc = desc;
this.stock = stock;
this.price = price;
this.rd = rd;
}
public String getHref() {
return href;
}
public String getDesc() {
return desc;
}
public String getStock() {
return stock;
}
public String getPrice() {
return price;
}
public String getRd() {
return rd;
}
}
答案 1 :(得分:0)
ViewHolder holder = new ViewHolder(convertView);
在这一行中,convertView可能为null。在充气convertView = inflater.inflate(R.layout.row, null);
答案 2 :(得分:0)
正如njzk2所说,你必须在创建视图后移动ViewHolder holder = new ViewHolder(convertView);
。
您还必须设置convertView.setTag(holder);
,否则在访问NullPointerException
时会有holder = (ViewHolder) convertView.getTag();
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null) {
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
ViewHolder holder = new ViewHolder(convertView);
convertView.setTag(holder);
holder.populateFrom(arrayJSONList.get(position));
return (convertView);
}