Java runOnUiThread给出错误NetworkOnMainThreadException

时间:2018-12-07 14:48:03

标签: java android http android-asynctask

我正在关注https://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/上的CRUD教程。

我根据自己的需要更改了设置,但是像本教程一样的runOnUiThread强制我关闭了应用程序。

如果我用其他方式替换代码,则该活动将运行,但不会填充字段。

我的代码:

package nl.app.app.recipefinder;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

public class EditIngredientActivity extends Activity {

// spinner text fields to select from
Spinner spinner;
String[] volume = {
        "Liter",
        "Mililiter",
        "Kilogram",
        "Gram",
        "Stuk(s)"
};

EditText txtName;
EditText txtQuantity;
EditText txtDesc;
EditText txtCreatedAt;
Button btnSave;
Button btnDelete;

String pid;

// Progress Dialog
private ProgressDialog pDialog;

// JSON parser class
JSONParser jsonParser = new JSONParser();

// single product url
private static final String url_ingredient_details = "http://www.linktosite";

// url to update product
private static final String url_update_ingredient = "http://www.linktosite";

// url to delete product
private static final String url_delete_ingredient = "http://www.linktosite";

// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_INGREDIENT = "ingredients";
private static final String TAG_PID = "pid";
private static final String TAG_NAME = "name";
private static final String TAG_QUANTITY = "quantity";
private static final String TAG_DESCRIPTION = "description";
private static final String TAG_VOLUME = "volume";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.edit_ingredient);

    // Get reference of SpinnerView from layout/current_layout.xml
    spinner = (Spinner)findViewById(R.id.DropDownVolume);

    ArrayAdapter<String> adapter= new ArrayAdapter<String>(this,android.
            R.layout.simple_spinner_dropdown_item ,volume);

    spinner.setAdapter(adapter);

    // save button
    btnSave = (Button) findViewById(R.id.btnSave);
    btnDelete = (Button) findViewById(R.id.btnDelete);

    // getting product details from intent
    Intent i = getIntent();

    // getting product id (pid) from intent
    pid = i.getStringExtra(TAG_PID);

    // Getting complete product details in background thread
    new GetProductDetails().execute();

    // save button click event
    btnSave.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // starting background task to update product
            new SaveProductDetails().execute();
            Log.d("good", "Created new ingredient");

        }
    });

    // Delete button click event
    btnDelete.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // deleting product in background thread
            new DeleteProduct().execute();
            Log.d("good", "Deleted ingredient");
        }
    });

}

/**
 * Background Async Task to Get complete product details
 * */
class GetProductDetails extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(EditIngredientActivity.this);
        pDialog.setMessage("Loading ingredient 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_ingredient_details, "GET", params);

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

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

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

                        // product with this pid found
                        // Edit Text
                        txtName = (EditText) findViewById(R.id.inputName);
                        txtQuantity = (EditText) findViewById(R.id.inputQuantity);
                        txtDesc = (EditText) findViewById(R.id.inputDesc);
                        spinner = (Spinner) findViewById(R.id.DropDownVolume);

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

                        Log.d("good", "shows ingredient");
                    }else{
                        // product with pid not found
                        Log.d("bad", "ingredient 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();
    }
}

/**
 * Background Async Task to  Save product Details
 * */
class SaveProductDetails extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(EditIngredientActivity.this);
        pDialog.setMessage("Saving ingredient ...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Saving product
     * */
    protected String doInBackground(String... args) {

        // getting updated data from EditTexts
        String name = txtName.getText().toString();
        String price = txtQuantity.getText().toString();
        String description = txtDesc.getText().toString();
        String volume = spinner.getSelectedItem().toString();


        // Building Parameters
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair(TAG_PID, pid));
        params.add(new BasicNameValuePair(TAG_NAME, name));
        params.add(new BasicNameValuePair(TAG_QUANTITY, price));
        params.add(new BasicNameValuePair(TAG_DESCRIPTION, description));
        params.add(new BasicNameValuePair("TAG_VOLUME", volume));


        // sending modified data through http request
        // Notice that update product url accepts POST method
        JSONObject json = jsonParser.makeHttpRequest(url_update_ingredient,
                "POST", params);
        Log.d("good", "Posted ingredient");

        // check json success tag
        try {
            int success = json.getInt(TAG_SUCCESS);

            if (success == 1) {
                // successfully updated
                Intent i = getIntent();
                // send result code 100 to notify about product update
                setResult(100, i);
                finish();
                Log.d("good", "finished update");

            } else {
                // failed to update product
                Log.d("bad", "Update ingredient failed");

            }
        } 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 product uupdated
        pDialog.dismiss();
    }
}

/*****************************************************************
 * Background Async Task to Delete Product
 * */
class DeleteProduct extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(EditIngredientActivity.this);
        pDialog.setMessage("Deleting ingredient...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Deleting product
     * */
    protected String doInBackground(String... args) {

        // 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
            JSONObject json = jsonParser.makeHttpRequest(
                    url_delete_ingredient, "POST", params);

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

            // json success tag
            success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // product successfully deleted
                // notify previous activity by sending code 100
                Intent i = getIntent();
                // send result code 100 to notify about product deletion
                setResult(100, i);
                finish();
                Log.d("good", "Deleted ingredient");
            }
        } 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 product deleted
        pDialog.dismiss();

    }

}
}

1 个答案:

答案 0 :(得分:2)

我不确定您对此感到困惑。例外很明显。您正在UI线程上执行网络操作。这在Android中是不允许的。将HTTP请求移到runonuithread块之外。在post execute方法中执行所有UI内容。在我看来,您不太了解AsyncTask的功能。以下是一些信息:https://developer.android.com/reference/android/os/AsyncTask


简而言之,doInBackground()方法在非UI线程上运行,onPostExecute()方法(在doInBackground()方法完成后运行)在UI线程上运行。这就是为什么您不应该像过去那样将runonuithread块放入doInBackground()方法内(其中,runonuithread是在doInBackground()方法中唯一运行的东西)。如果这样做,那么使用AsyncTask是没有意义的。

我还快速浏览了您的教程链接。本教程未将runonUiThread块放入其asynctask的doInBackground()方法中。有没有理由将其放入?