我正在关注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();
}
}
}
答案 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()方法中。有没有理由将其放入?