我有几个堆栈跟踪,就像我的应用程序从我的MySQL数据库中获取数据一样。如果连接断开并超时,我会得到以下堆栈跟踪:
示例:
java.lang.NullPointerException
at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:128)
at com.---.---.profile.MyReviewAdapter.<init>(MyReviewAdapter.java:20)
at com.---.---.profile.UserFragmentActivity$CommentFragment$MyCommentTask.onPostExecute(UserFragmentActivity.java:559)
at com.---.---.profile.UserFragmentActivity$CommentFragment$MyCommentTask.onPostExecute(UserFragmentActivity.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
示例:
java.lang.NullPointerException
at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:128)
at com.---.---.master.TopItemAdapter.<init>(TopItemAdapter.java:18)
at com.---.---.master.MainFragmentActivity$TopFrag$TopTask.onPostExecute(MainFragmentActivity.java:961)
at com.---.---.master.MainFragmentActivity$TopFrag$TopTask.onPostExecute(MainFragmentActivity.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
以下是使用第二个LogCat调用的示例代码:
class TopTask extends AsyncTask<String, String, Void> {
private MyProgressDialog progressDialog = new MyProgressDialog(
getActivity());
InputStream is = null;
String result = "";
protected void onPreExecute() {
progressDialog.setMessage("Loading...");
progressDialog.show();
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
TopTask.this.cancel(true);
}
});
}
@Override
protected Void doInBackground(String... params) {
String url_select = "http://www.---.com/---/master_cat_items.php";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
param.add(new BasicNameValuePair("Sort", Sort));
try {
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// read content
is = httpEntity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error converting result " + e.toString());
}
return null;
}
protected void onPostExecute(Void v) {
String item, cat;
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int i = 0; i < jArray.length(); i++) {
json_data = jArray.getJSONObject(i);
item = json_data.getString("item");
cat = json_data.getString("category");
items.add(item);
cats.add(cat);
}
} catch (JSONException e1) {
} catch (ParseException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
// toast to notify user to reload
}
TopItemAndTrendingObject[] mco = new TopItemAndTrendingObject[items
.size()];
int index = 0;
for (@SuppressWarnings("unused")
String i : items) {
mco[index] = new TopItemAndTrendingObject(items.get(index),
cats.get(index));
index++;
}
adapter = new TopItemAdapter(getActivity(), mco); // this is what is referenced in LogCat
setListAdapter(adapter);
progressDialog.dismiss();
}
}
所以我的问题是:
修改:TopItemAdapter
的代码
public class TopItemAdapter extends ArrayAdapter<TopItemAndTrendingObject> {
private final Context context;
public TopItemAdapter(Context context, TopItemAndTrendingObject[] items) {
super(context, 0, items);
this.context = context;
}
static class ViewHolder {
public TextView tv1;
public TextView tv2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
rowView = inflater
.inflate(R.layout.master_cat_all_time, null, true);
holder = new ViewHolder();
holder.tv1 = (TextView) rowView.findViewById(R.id.myMastCat_Cat);
holder.tv2 = (TextView) rowView.findViewById(R.id.myMasterCat_Item);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
TopItemAndTrendingObject mco = getItem(position);
String item = mco.item;
String cat = mco.cat;
holder.tv2.setText(String.valueOf(position + 1) + ". " + item);
holder.tv1.setText(cat);
return rowView;
}
}
答案 0 :(得分:1)
我认为,首先,您应该正确初始化对象而不是null。例如:
InputStream is = null;
这样做:
InputStream is = new InputStream();
你只有一个用null初始化的对象!
修改强>
我认为问题在于:
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int i = 0; i < jArray.length(); i++) {
json_data = jArray.getJSONObject(i);
item = json_data.getString("item");
cat = json_data.getString("category");
items.add(item);
cats.add(cat);
}
} catch (JSONException e1) {
} catch (ParseException e1) {
e1.printStackTrace();
}
这样做:
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int i = 0; i < jArray.length(); i++) {
json_data = new JSONOBject(jArray.getJSONObject(i).toString());
item = json_data.getString("item");
cat = json_data.getString("category");
items.add(item);
cats.add(cat);
}
} catch (JSONException e1) {
} catch (ParseException e1) {
e1.printStackTrace();
}
并且还捕获所有异常,不仅是JSONException和ParseException。
答案 1 :(得分:1)
如果您的主要问题只是强制关闭,并且您希望您的应用程序永远不会显示强制关闭,那么您可以使用UncaughtExceptionHandler。
public class UncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler
{
private final Context myContext;
public UncaughtExceptionHandler(Context context) {
myContext = context;
}
public void uncaughtException(Thread thread, Throwable exception) {
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);
Intent intent = new Intent(myContext, AnyActivity.class);
myContext.startActivity(intent);
Process.killProcess(Process.myPid());
System.exit(10);
}
}
并在活动
中的 setContentView 之前写下此行Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler (this));
答案 2 :(得分:1)
这个例外是什么意思
正如我在评论中已经说过NullPointerException
没有出现因为数据库连接失败(在这种情况下会发生不同的错误而且速度更快),因为你没有接受考虑Android使用活动和片段的方式(更确切地说是他们的生命周期)。
我不知道您是否有关于这些例外的额外详细信息,我的猜测是,当用户访问有问题的Fragment
看到ProgressDialog
(并且任务已启动)时会出现异常然后旋转手机。此时,Android将重新创建活动以及任何包含的片段。这应该由您的代码处理,但相反,您做了一些特别糟糕的事情,这将抛出NullPointerException
。
查看您声明TopTask
类的方式可以说是Fragment
中的内部类。作为内部类意味着它与封闭的Fragment
实例具有“连接”,允许它使用片段的方法(如getActivity()
)。因此,用户转到Fragment
,任务开始,然后旋转手机。此时将重新创建活动和片段,但您的任务(仍在运行)将保留对初始片段的特殊引用(现在已经死了)。轮换后,此初始片段引用将与活动分离,其getActivity
方法将返回null
。将null
传递给ArrayAdapter
(在您的情况下通过a super
调用)会抛出您看到的异常(来自具有ICS
的设备)。传递给适配器的数组不能是null
,因为您在适配器的初始化之上声明它。这也会引发一个不同的例外。
更重要的是,我该如何防止这种情况发生?即使它像连接掉落时抛出一个吐司一样基本(任何东西而不是力量关闭?
最简单的方法是不要在配置更改时销毁碎片。这是通过使用Fragment
的{{3}}方法完成的,因此对Fragment
的引用将保持有效(在onCreate
的{{1}}回调中例)。我还将Fragment
类作为静态类,并在TopTask
的构造函数中传递对Fragment
的引用。这应该进行测试。
你也可以发送一个从TopTask
到Fragment
的应用程序上下文的引用(但也许你应该避免它),这个引用是有效的:
TopTask
同时保留// in the onActivityCreated method
new TopTask(getActivity().getApplicationContext()).execute(/*parameters*/);
的引用,但在ProgressDialog
回调中对其进行初始化。