我有 3 个微调器和一个列表视图。在第一个微调器中,用户选择一个状态。然后下一个微调器将填充该州的所有县。然后用户选择一个县,最后一个微调器将填充该县的城市。最后,用户选择了一个城市,列表视图中填充了该城市的医院。所有这些数据都是从数据库中提取的,并且工作正常。我遇到的问题是,如果我想返回并更改应用程序崩溃的县、州或城市。
这是堆栈跟踪:
04-20 23:26:33.604: E/AndroidRuntime(1781): FATAL EXCEPTION: AsyncTask #5
04-20 23:26:33.604: E/AndroidRuntime(1781): java.lang.RuntimeException: An error occured while executing doInBackground()
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.os.AsyncTask$3.done(AsyncTask.java:299)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.lang.Thread.run(Thread.java:856)
04-20 23:26:33.604: E/AndroidRuntime(1781): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:2588)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:608)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.View.setFlags(View.java:8405)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.view.View.setFocusable(View.java:5767)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.widget.AdapterView.checkFocus(AdapterView.java:718)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:812)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:286)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.widget.ArrayAdapter.add(ArrayAdapter.java:182)
04-20 23:26:33.604: E/AndroidRuntime(1781): at com.photosbychristian.ems.Edit$LoadCity.doInBackground(Edit.java:315)
04-20 23:26:33.604: E/AndroidRuntime(1781): at com.photosbychristian.ems.Edit$LoadCity.doInBackground(Edit.java:1)
04-20 23:26:33.604: E/AndroidRuntime(1781): at android.os.AsyncTask$2.call(AsyncTask.java:287)
04-20 23:26:33.604: E/AndroidRuntime(1781): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
04-20 23:26:33.604: E/AndroidRuntime(1781): ... 4 more
04-20 23:26:43.693: E/WindowManager(1781): Activity com.photosbychristian.ems.Edit has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b32d40f0 V.E..... R.....ID 0,0-564,230} that was originally added here
04-20 23:26:43.693: E/WindowManager(1781): android.view.WindowLeaked: Activity com.photosbychristian.ems.Edit has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b32d40f0 V.E..... R.....ID 0,0-564,230} that was originally added here
04-20 23:26:43.693: E/WindowManager(1781): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
04-20 23:26:43.693: E/WindowManager(1781): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
04-20 23:26:43.693: E/WindowManager(1781): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
04-20 23:26:43.693: E/WindowManager(1781): at android.app.Dialog.show(Dialog.java:281)
04-20 23:26:43.693: E/WindowManager(1781): at com.photosbychristian.ems.Edit$LoadCity.onPreExecute(Edit.java:293)
04-20 23:26:43.693: E/WindowManager(1781): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
04-20 23:26:43.693: E/WindowManager(1781): at android.os.AsyncTask.execute(AsyncTask.java:534)
04-20 23:26:43.693: E/WindowManager(1781): at com.photosbychristian.ems.Edit$LoadCounty$2.onItemSelected(Edit.java:272)
04-20 23:26:43.693: E/WindowManager(1781): at android.widget.AdapterView.fireOnSelected(AdapterView.java:892)
04-20 23:26:43.693: E/WindowManager(1781): at android.widget.AdapterView.access$200(AdapterView.java:49)
04-20 23:26:43.693: E/WindowManager(1781): at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:860)
04-20 23:26:43.693: E/WindowManager(1781): at android.os.Handler.handleCallback(Handler.java:725)
04-20 23:26:43.693: E/WindowManager(1781): at android.os.Handler.dispatchMessage(Handler.java:92)
04-20 23:26:43.693: E/WindowManager(1781): at android.os.Looper.loop(Looper.java:137)
04-20 23:26:43.693: E/WindowManager(1781): at android.app.ActivityThread.main(ActivityThread.java:5039)
04-20 23:26:43.693: E/WindowManager(1781): at java.lang.reflect.Method.invokeNative(Native Method)
04-20 23:26:43.693: E/WindowManager(1781): at java.lang.reflect.Method.invoke(Method.java:511)
04-20 23:26:43.693: E/WindowManager(1781): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-20 23:26:43.693: E/WindowManager(1781): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-20 23:26:43.693: E/WindowManager(1781): at dalvik.system.NativeStart.main(Native Method)
我的代码是:
package com.photosbychristian.ems;
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.ListActivity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
public class Edit extends ListActivity {
private ProgressDialog stateDialog;
private ProgressDialog countyDialog;
private ProgressDialog cityDialog;
private ProgressDialog hospitalDialog;
JSONParser stateParser = new JSONParser();
JSONParser countyParser = new JSONParser();
JSONParser cityParser = new JSONParser();
JSONParser hospitalParser = new JSONParser();
private static String url_state = "http://www.photosbychristian.com/ems/states.php";
private static String url_county = "http://www.photosbychristian.com/ems/countys.php";
private static String url_city = "http://www.photosbychristian.com/ems/citys.php";
private static String url_hospital = "http://www.photosbychristian.com/ems/hospitals.php";
private static final String TAG_STATE_DISPLAY = "display";
private static final String TAG_COUNTY_DISPLAY = "display";
private static final String TAG_CITY_DISPLAY = "display";
private static final String TAG_HOSPITAL_DISPLAY = "display";
JSONArray statesArray = null;
JSONArray countysArray = null;
JSONArray citysArray = null;
JSONArray hospitalArray = null;
ArrayAdapter<String> stateAdapter;
ArrayAdapter<String> countyAdapter;
ArrayAdapter<String> cityAdapter;
ArrayAdapter<String> hospitalAdapter;
Spinner state;
Spinner county;
Spinner city;
String stateLabel;
String cityLabel;
String hospitalLabel;
ListView hosps;
ArrayList<String> hosp = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.edit);
TabHost th = (TabHost) findViewById(R.id.tabhost);
th.setup();
TabSpec specs = th.newTabSpec("tag1");
specs.setContent(R.id.tab1);
specs.setIndicator("My Hospitals");
th.addTab(specs);
specs = th.newTabSpec("tag2");
specs.setContent(R.id.tab2);
specs.setIndicator("Add Hospitals");
th.addTab(specs);
new LoadStates().execute();
state = (Spinner) findViewById(R.id.sState);
county = (Spinner) findViewById(R.id.sCounty);
city = (Spinner) findViewById(R.id.sCity);
hosps = getListView();
stateAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item);
countyAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item);
cityAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item);
hospitalAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, hosp);
}
class LoadStates extends AsyncTask<String, String, String> {
// Before starting background thread Show State Progress Dialog
@Override
protected void onPreExecute() {
super.onPreExecute();
stateDialog = new ProgressDialog(Edit.this);
stateDialog.setMessage("Loading States. Please wait...");
stateDialog.setIndeterminate(false);
stateDialog.setCancelable(false);
stateDialog.show();
}
/** Get states form Internet **/
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = stateParser.makeHttpRequest(url_state, "GET",
params);
// Check your log cat for JSON response
Log.d("All States: ", json.toString());
stateAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
stateAdapter.add("Select A State");
try {
// products found
// Getting Array of Products
statesArray = json.getJSONArray("states");
// looping through All Products
for (int i = 0; i < statesArray.length(); i++) {
JSONObject c = statesArray.getJSONObject(i);
// Storing each JSON item in variable
// String id = c.getString(TAG_HID);
String disp = c.getString(TAG_STATE_DISPLAY);
stateAdapter.add(disp);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/** After completing background task Dismiss the progress dialog **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
stateDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// add states to spinner
state.setAdapter(stateAdapter);
}
});
state.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
// On selecting a spinner item
String label = parent.getItemAtPosition(position)
.toString();
if (label == "Select A State") {
} else {
stateLabel = label;
// load county spinner
new LoadCounty().execute();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
}
class LoadCounty extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
countyDialog = new ProgressDialog(Edit.this);
countyDialog.setMessage("Loading Countys. Please wait...");
countyDialog.setIndeterminate(false);
countyDialog.setCancelable(false);
countyDialog.show();
}
// Get states form Internet
@Override
protected String doInBackground(String... args) {
// TODO Auto-generated method stub
// Building Parameters
List<NameValuePair> Countyparams = new ArrayList<NameValuePair>();
Countyparams.add(new BasicNameValuePair("state", stateLabel));
// getting JSON string from URL
JSONObject Countyjson = countyParser.makeHttpRequest(url_county,
"GET", Countyparams);
// Check your log cat for JSON response
Log.d("All Countys: ", Countyjson.toString());
countyAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
countyAdapter.add("Select A County");
try {
// products found
// Getting Array of Products
countysArray = Countyjson.getJSONArray("county");
// looping through All Products
for (int i = 0; i < countysArray.length(); i++) {
JSONObject c = countysArray.getJSONObject(i);
// Storing each JSON item in variable
// String id = c.getString(TAG_HID);
String disp = c.getString(TAG_COUNTY_DISPLAY);
countyAdapter.add(disp);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// After completing background task Dismiss the progress dialog
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
countyDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// add states to spinner
county.setAdapter(countyAdapter);
}
});
county.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
// On selecting a spinner item
String label = parent.getItemAtPosition(position)
.toString();
if (label == "Select A County") {
} else {
// load city spinner
hospitalAdapter.clear();
hospitalAdapter.notifyDataSetChanged();
cityAdapter.clear();
cityAdapter.notifyDataSetChanged();
cityLabel = label;
new LoadCity().execute();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
}
class LoadCity extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
cityDialog = new ProgressDialog(Edit.this);
cityDialog.setMessage("Loading Citys. Please wait...");
cityDialog.setIndeterminate(false);
cityDialog.setCancelable(false);
cityDialog.show();
}
// Get states form Internet
@Override
protected String doInBackground(String... args) {
// TODO Auto-generated method stub
// Building Parameters
List<NameValuePair> Cityparams = new ArrayList<NameValuePair>();
Cityparams.add(new BasicNameValuePair("state", stateLabel));
Cityparams.add(new BasicNameValuePair("county", cityLabel));
// getting JSON string from URL
JSONObject Cityjson = cityParser.makeHttpRequest(url_city, "GET",
Cityparams);
// Check your log cat for JSON response
Log.d("All Citys: ", Cityjson.toString());
cityAdapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cityAdapter.add("Select A City");
try {
// products found
// Getting Array of Products
citysArray = Cityjson.getJSONArray("city");
// looping through All Products
for (int i = 0; i < citysArray.length(); i++) {
JSONObject c = citysArray.getJSONObject(i);
// Storing each JSON item in variable
// String id = c.getString(TAG_HID);
String disp = c.getString(TAG_CITY_DISPLAY);
cityAdapter.add(disp);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// After completing background task Dismiss the progress dialog
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
cityDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// add states to spinner
city.setAdapter(cityAdapter);
}
});
city.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
// On selecting a spinner item
String label = parent.getItemAtPosition(position)
.toString();
hospitalLabel = label;
if (label == "Select A City") {
} else {
// load hospitals
new LoadHospitals().execute();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
}
class LoadHospitals extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
hospitalDialog = new ProgressDialog(Edit.this);
hospitalDialog.setMessage("Loading Hospitals. Please wait...");
hospitalDialog.setIndeterminate(false);
hospitalDialog.setCancelable(false);
hospitalDialog.show();
hospitalAdapter.clear();
hospitalAdapter.notifyDataSetChanged();
}
// Get states form Internet
@Override
protected String doInBackground(String... args) {
// TODO Auto-generated method stub
// Building Parameters
List<NameValuePair> hospitalparams = new ArrayList<NameValuePair>();
hospitalparams.add(new BasicNameValuePair("state", stateLabel));
hospitalparams.add(new BasicNameValuePair("county", cityLabel));
hospitalparams.add(new BasicNameValuePair("city", hospitalLabel));
// getting JSON string from URL
JSONObject Cityjson = hospitalParser.makeHttpRequest(url_hospital, "GET",
hospitalparams);
// Check your log cat for JSON response
Log.d("All Hospital: ", Cityjson.toString());
try {
// products found
// Getting Array of Products
hospitalArray = Cityjson.getJSONArray("hospital");
// looping through All Products
for (int i = 0; i < hospitalArray.length(); i++) {
JSONObject c = hospitalArray.getJSONObject(i);
// Storing each JSON item in variable
// String id = c.getString(TAG_HID);
String disp = c.getString(TAG_HOSPITAL_DISPLAY);
hosp.add(disp);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// After completing background task Dismiss the progress dialog
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
hospitalDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// display hospitals
setListAdapter(hospitalAdapter);
hospitalAdapter.notifyDataSetChanged();
}
});
}
}
}