由于数据连接不良导致适配器出现异常

时间:2012-10-09 17:18:50

标签: android nullpointerexception android-adapter

我有几个堆栈跟踪,就像我的应用程序从我的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. 更重要的是,我该如何防止这种情况?即使它像连接掉落时抛出一个吐司一样基本(任何东西而不是强制关闭?
  3. 修改: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;
    
        }
    }
    

3 个答案:

答案 0 :(得分:1)

  1. 您可以阅读here
  2. 的NullPointer异常
  3. 我认为,首先,您应该正确初始化对象而不是null。例如:

    InputStream is = null;
    
  4. 这样做:

    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的引用。这应该进行测试。

你也可以发送一个从TopTaskFragment的应用程序上下文的引用(但也许你应该避免它),这个引用是有效的:

TopTask

同时保留// in the onActivityCreated method new TopTask(getActivity().getApplicationContext()).execute(/*parameters*/); 的引用,但在ProgressDialog回调中对其进行初始化。