按照本教程,但我仍然坚持使用asyncTask

时间:2015-05-05 16:21:05

标签: java android android-asynctask

我是一个学习开发Android应用程序的初学者,我目前正在http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/上关注这个简单的教程,但在其中一个页面上我遇到了NetworkOnMainThreadException的问题,在我研究之后,android 3.0及以上版本在UI线程上执行http请求时会抛出异常,并且我必须使用AsyncTask。我一直在尝试修改代码以执行请求onPostExecute,但我一直在收到错误。

这是java代码:

package com.example.test;

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.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class EditProductActivity extends Activity {

    EditText txtName;
    EditText txtPrice;
    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_product_details = "http://api.kerjaapa.com/android_connect/get_product_details.php";

    //url to update product
    private static final String url_update_product = "http://api.kerjaapa.com/android_connect/update_product.php";

    //url to delete product
    private static final String url_delete_product = "http://api.kerjaapa.com/android_connect/delete_product.php";

    //JSON Node names
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_PRODUCT = "product";
    private static final String TAG_PID = "pid";
    private static final String TAG_NAME = "name";
    private static final String TAG_PRICE = "price";
    private static final String TAG_DESCRIPTION = "description";

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

        //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();
            }
        });

        //Delete button click event
        btnDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //deleting product in background thread
                new DeleteProduct().execute();
            }
        });
    }

    //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(EditProductActivity.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);

                            //product with this pid found
                            //Edit text
                            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();
        }

    }

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

        //Before starting background thread, show dialog
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("Saving product ...");
            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 = txtPrice.getText().toString();
            String description = txtDesc.getText().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_PRICE, price));
            params.add(new BasicNameValuePair(TAG_DESCRIPTION, description));

            //sending modified data through http request
            //Notice that update product url accepts POST method
            JSONObject json = jsonParser.makeHttpRequest(url_update_product, 
                "POST", params);

            //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();
                } else {
                    //failed to update product
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        //After completing background task, dismiss dialog
        protected void onPostExecute(String file_url) {
            //dismiss dialog
            pDialog.dismiss();
        }    
    }

    //Background async task to delete product
    class DeleteProduct extends AsyncTask<String, String, String> {

        //Before starting, show progress dialog
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("Deleting Product...");
            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_product, "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();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        //After completing background task dismiss dialog
        protected void onPostExecute(String file_url) {
            //dismiss dialog once finish
            pDialog.dismiss();
        }
    }

}

问题出在GetProductDetails类中,它使用runOnUiThread(new Runnable(){public void run(),我试图擦除这些块并且应用程序会运行,但有时它会起作用,有时它会导致RunTimeException,并且应用程序会崩溃。我也尝试将变量成功传递给onPostExecute(),然后在onPostExecute()中,如果成功== 1,则显示JSON调用的结果,但在调整代码后,我不断收到错误并且无法#39;解决它。在像这样的项目中使用asyncTask的最佳做法是什么?

非常感谢任何指导。

提前谢谢

3 个答案:

答案 0 :(得分:1)

请勿修改doInBackground中的用户界面。

在这种情况下,我认为您应该将product对象传递给您的onPostExecute,它在UI线程上运行,您可以在其中修改UI:

//Background Async Task to Get Complete Product Details
class GetProductDetails extends AsyncTask<String, String, JSONObject> {
    //Before starting background thread show progress dialog
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(EditProductActivity.this);
        pDialog.setMessage("Loading product details. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    //getting product details in background thread
    protected JSONObject doInBackground(String... params) {
        //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);

                return product;

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

        return null;
    }

    //After completing background task dismiss the progress dialog
    protected void onPostExecute(JSONObject product) {
        //Edit text
        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));

        //dismiss the dialog once got all details
        pDialog.dismiss();
    }

}

答案 1 :(得分:0)

我可以在您的代码中找到很多错误。最大的问题是,你确实需要解决的问题是你runOnUiThread(new Runnable() {上不需要doInBackground(),这主要是因为这种方法可以在后台运行,你可以在那里做你的要求。请求的结果必须传递给onPostExecute(),此方法已在ui线程中运行。所以你应该更新那里的ui。

必须在onCreate()中调用findViewById方法。试试这个并告诉我会发生什么。

答案 2 :(得分:0)

@Charas,

我调查您的代码并删除您的问题。您在后台调用“UI线程”并在UI上调用网络操作。所以你面对这类问题。请使用以下代码并享受编码....

    package com.example.test;

    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.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;

    public class EditProductActivity extends Activity {

        EditText txtName;
        EditText txtPrice;
        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_product_details = "http://api.kerjaapa.com/android_connect/get_product_details.php";

        //url to update product
        private static final String url_update_product = "http://api.kerjaapa.com/android_connect/update_product.php";

        //url to delete product
        private static final String url_delete_product = "http://api.kerjaapa.com/android_connect/delete_product.php";

        //JSON Node names
        private static final String TAG_SUCCESS = "success";
        private static final String TAG_PRODUCT = "product";
        private static final String TAG_PID = "pid";
        private static final String TAG_NAME = "name";
        private static final String TAG_PRICE = "price";
        private static final String TAG_DESCRIPTION = "description";

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

            //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();
                }
            });

            //Delete button click event
            btnDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    //deleting product in background thread
                    new DeleteProduct().execute();
                }
            });
        }

        //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(EditProductActivity.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) {

                        //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);

                        } 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();

 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);

                                //product with this pid found
                                //Edit text
                                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
                            }
            }

        }

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

            //Before starting background thread, show dialog
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pDialog = new ProgressDialog(EditProductActivity.this);
                pDialog.setMessage("Saving product ...");
                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 = txtPrice.getText().toString();
                String description = txtDesc.getText().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_PRICE, price));
                params.add(new BasicNameValuePair(TAG_DESCRIPTION, description));

                //sending modified data through http request
                //Notice that update product url accepts POST method
                JSONObject json = jsonParser.makeHttpRequest(url_update_product, 
                    "POST", params);

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


                } catch (JSONException e) {
                    e.printStackTrace();
                }

                return null;
            }

            //After completing background task, dismiss dialog
            protected void onPostExecute(String file_url) {
                //dismiss dialog
                pDialog.dismiss();
 if (success == 1) {
                        //successfully updated
                        Intent i = getIntent();
                        //send result code 100 to notify about product update
                        setResult(100, i);
                        finish();
                    } else {
                        //failed to update product
                    }
            }    
        }

        //Background async task to delete product
        class DeleteProduct extends AsyncTask<String, String, String> {

            //Before starting, show progress dialog
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pDialog = new ProgressDialog(EditProductActivity.this);
                pDialog.setMessage("Deleting Product...");
                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_product, "POST", params);

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

                    //json success tag
                    success = json.getInt(TAG_SUCCESS);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                return null;
            }

            //After completing background task dismiss dialog
            protected void onPostExecute(String file_url) {
                //dismiss dialog once finish
                pDialog.dismiss();
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();
                    }
            }
        }

    }