0

每当有调用从我的 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();


            }
        }

所以我的问题是:

  1. 这个异常是什么意思(是的,我知道 NullPointerException 是什么)?
  2. 更重要的是,我该如何防止这种情况发生? 即使它就像连接断开时举杯一样基本(任何东西而不是强制关闭?

编辑: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;

    }
}
4

3 回答 3

1
  1. NullPointer Exception 是什么,您可以在此处阅读
  2. 我认为,首先,您应该正确初始化对象,而不是使用 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。

于 2012-10-09T17:31:04.020 回答
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));
于 2012-10-11T19:36:06.490 回答
1

这个异常是什么意思

正如我在评论中已经说过的那样,NullPointerException由于数据库连接失败(在这种情况下会发生不同的错误并且速度更快)而没有出现,它出现是因为您没有考虑 Android 使用活动和片段的方式(更准确地说是它们的生命周期)。

我不知道您是否有关于这些异常的更多详细信息,我的猜测是当用户进入有问题的地方Fragment看到ProgressDialog(并且任务已启动)然后旋转手机时会出现异常。此时,Android 将重新创建活动以及任何包含的片段。这应该由您的代码处理,但相反,您做了一些特别糟糕的事情,这将抛出NullPointerException.

查看您声明TopTask该类的方式可以肯定地说它是Fragment. 作为一个内部类意味着它与封闭Fragment实例有一个“连接”,允许它使用片段的方法(如getActivity())。所以用户去Fragment,任务开始,然后旋转手机。此时将重新创建活动和片段,但您的任务(仍在运行)将保留对初始片段(现在已死)的特殊引用。旋转后,这个初始片段引用将与活动分离,其getActivity方法将返回null。传递null给一个ArrayAdapter(在你的情况下通过super调用)将抛出你看到的异常(来自一个设备ICS)。您传递给适配器的数组不能null像您在适配器初始化上方声明的那样。这也会引发不同的异常。

更重要的是,我该如何防止这种情况发生?即使它就像连接断开时举杯一样基本(任何东西而不是强制关闭?

最简单的做法是不要随着配置更改而破坏片段。这是通过使用 a 的setRetainInstance(true)方法来完成的,Fragment因此对 的引用Fragment将保持有效(例如在onCreate回调中Fragment)。我还会将该TopTask类设为静态类,并FragmentTopTask. 这应该被测试。

您还可以将应用程序上下文的引用从 发送FragmentTopTask类似这样(但也许您应该避免它),这将是有效的:

// in the onActivityCreated method
new TopTask(getActivity().getApplicationContext()).execute(/*parameters*/);

还要保留对的引用,ProgressDialog但在onPreExecute回调中对其进行初始化。

于 2012-10-12T11:29:08.760 回答