0

MySQL DB からデータを取得するための呼び出しがあるときはいつでも、アプリ全体に以下のようなスタックトレースがいくつかあります。接続が切れてタイムアウトした場合、次のスタック トレースが表示されます。

例:

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)

この 2 番目の 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例外とは何かを読むことができます
  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 だけでなく、すべての Exception もキャッチします。

于 2012-10-09T17:31:04.020 に答える
1

この例外の意味

データベース接続が失敗したために表示されないコメントで既に述べたようにNullPointerException(この場合、別のエラーが発生し、はるかに高速になります)、Android がアクティビティとフラグメントを使用する方法を考慮していないために表示されます。 (より正確には、ライフサイクル)。

これらの例外に関する追加の詳細があるかどうかはわかりませんが、ユーザーが問題のある場所に移動しFragmentProgressDialog(そしてタスクが開始され)、電話を回転させたときに例外が表示されると思います。この時点で、Android はアクティビティを含むフラグメントとともにアクティビティを再作成します。これはコードで処理する必要がありますが、代わりに、特に悪いことをしたため、NullPointerException.

TopTaskクラスを宣言した方法を見ると、 Fragment. 内部クラスであるということは、囲んでいるFragmentインスタンスへの「接続」があり、フラグメントのメソッド ( などgetActivity()) を使用できることを意味します。ユーザが に移動するFragmentと、タスクが開始され、電話機がローテーションされます。この時点で、アクティビティとフラグメントが再作成されますが、タスク (まだ実行中) は最初のフラグメント (今では死んでいます) への特別な参照を保持します。ローテーションの後、この最初のフラグメント参照はアクティビティから切り離され、そのgetActivityメソッドは を返しnullます。(あなたの場合は a 呼び出しを介して)に渡すnullと、表示される例外がスローされます(これは、デバイスからのものですArrayAdaptersuperICS)。アダプターに渡す配列はnull、アダプターの初期化のすぐ上で宣言したとおりにすることはできません。これも別の例外をスローします。

さらに重要なことに、どうすればこれを防ぐことができますか? 接続が切断されたときにトーストを投げるのと同じくらい基本的であっても(強制終了の代わりに何か?

最も簡単な方法は、構成の変更に伴ってフラグメントを破棄しないことです。これは a のsetRetainInstance(true)メソッドを使用して行われるFragmentため、 への参照Fragmentは有効に保たれます (たとえば、 のonCreateコールバックで)。Fragmentまた、TopTaskクラスを静的クラスとして作成Fragmentし、 のコンストラクターでへの参照を渡しTopTaskます。これはテストする必要があります。

Fragment次のように から にアプリケーション コンテキストへの参照を送信することもできますTopTask(ただし、これは避ける必要があります)。これは有効です。

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

の参照も保持しますが、コールバックProgressDialogで初期化します。onPreExecute

于 2012-10-12T11:29:08.760 に答える
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 に答える