即使在AsyncTask中运行,android.os.NetworkOnMainThreadException也会出错

时间:2013-06-20 18:29:17

标签: java android thread-synchronization

当我尝试连接到互联网时,我得到了android.os.NetworkOnMainThreadException错误。我知道android(HoneyComb以后版本)的更新版本不允许你在UI线程上执行网络IO这就是为什么我是在代码上使用AsyncTask.no错误但是当它运行时,我得到android.os.NetworkOnMainThreadException错误 代码:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainactivity);
    new GetProductDetails().execute();
}

class GetProductDetails extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Loading product details. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Getting product details in background thread
     * */
    protected String doInBackground(String... params) {

        // updating UI from Background Thread
        runOnUiThread(new Runnable() {
            public void run() {
                // Check for success tag
                int success;
                try {
                    // Building Parameters
                    List<NameValuePair> params = new ArrayList<NameValuePair>();
                    params.add(new BasicNameValuePair("pid", pid));

                    // getting product details by making HTTP request
                    // Note that product details url will use GET request
                    JSONObject json = jsonParser.makeHttpRequest(
                            url_product_details, "GET", params);

                    // check your log for json response
                    Log.d("Single Product Details", json.toString());

                    // json success tag
                    success = json.getInt(TAG_SUCCESS);
                    if (success == 1) {
                        // successfully received product details
                        JSONArray productObj = json
                                .getJSONArray(TAG_PRODUCT); // JSON Array

                        // get first product object from JSON Array
                        JSONObject product = productObj.getJSONObject(0);


                        txtName = (EditText) findViewById(R.id.inputName);
                        txtPrice = (EditText) findViewById(R.id.inputPrice);
                        txtDesc = (EditText) findViewById(R.id.inputDesc);

                        // display product data in EditText
                        txtName.setText(product.getString(TAG_NAME));
                        txtPrice.setText(product.getString(TAG_PRICE));
                        txtDesc.setText(product.getString(TAG_DESCRIPTION));


                    }else{
                        // product with pid not found
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        return null;
    }


    /**
     * After completing background task Dismiss the progress dialog
     * **/
    protected void onPostExecute(String file_url) {
        // dismiss the dialog once got all details
        pDialog.dismiss();
    }
}

我已经读过一个可能的解决方案是使用StrictMode策略,但我有点不愿意使用它,因为它仅在开发环境中推荐。这里有什么问题?

3 个答案:

答案 0 :(得分:6)

  

这里有什么问题?

您正在主应用程序线程上进行网络I / O,从Runnable runOnUiThread()内部进行。{/ p>

摆脱runOnUiThread()Runnable。将网络代码放在doInBackground()中。在onPostExecute()更新您的小部件。您可以通过doInBackground()的返回值(成为传递给onPostExecute()的参数)或doInBackground()内的数据成员将数据从onPostExecute()传递到AsyncTask本身。

答案 1 :(得分:1)

您正在使用AsyncTask但在doInBackground中正在调用

// updating UI from Background Thread
        runOnUiThread(new Runnable() {
            public void run() {

在这些字符串中,您可以在主UI线程中运行doInBackground中的所有下一个代码,并删除所有AsyncTask效果。

比你跑

JSONObject json = jsonParser.makeHttpRequest(
                            url_product_details, "GET", params);

它在主线程中运行,如下所述。因此,它抛出异常。

将所有网络代码移出Runnable并将您的Runnable放在doInBackground的末尾,只更新小部件 - 它应该有效。

答案 2 :(得分:0)

您正在ui线程上运行与网络相关的操作。

您在runOnUiThread内使用doInbackground()。在runOnUiThread内你有以下

JSONObject json = jsonParser.makeHttpRequest(
                        url_product_details, "GET", params);

这会导致NetworkOnMainThreadException

您还缺少@OverridedoInBackground()的{​​{1}}注释。

A可以在onPostExecute()中发出json请求,并在doInbackground()中更新ui。

如果您使用onPostExecute()使用它来更新ui并在runOnUiThread中移动所有与网络相关的操作。

您也可以将以下内容移至doInbackground

onCreate

txtName = (EditText) findViewById(R.id.inputName); txtPrice = (EditText) findViewById(R.id.inputPrice); txtDesc = (EditText) findViewById(R.id.inputDesc); 中返回背景计算的结果。 doInbackground的结果是onPostExecute的参数。您可以使用相同的方法在doInbackground中更新ui。

有关详细信息,请查看文档

http://developer.android.com/reference/android/os/AsyncTask.html