问题
I am having some problem with AsyncTask #2 fatal exception in Android. So what I am trying to do is single tap on map, get the coordinates X and Y and pass them to AsyncTask() class to execute a method to get the address. Here is the codes of my single tap and MyAsyncTask():
mMapView.setOnSingleTapListener(new OnSingleTapListener() {
public void onSingleTap(float x, float y) {
eventModel.setEventX(String.valueOf(point.getX()));
eventModel.setEventY(String.valueOf(point.getY()));
new MyAsyncTask().execute(eventModel);
CreateEvent.createEventDialog(context, point.getX(),
point.getY(), eventAddress);
Log.i("Addr", eventAddress);
}
});
new MyAsyncTask().execute();
}
public static class MyAsyncTask extends AsyncTask<Event, Integer, Double> {
@Override
protected Double doInBackground(Event... params) {
try {
eventAddress = eventCtrl.getStreetAddressFromGeometry(eventModel.getEventX(), eventModel.getEventY());
eventCtrl.retrieveEventJSON();
if (params.length == 1) {
eventCtrl.createEvent(params[0]);
// Refresh map after successfully added event
eventCtrl.retrieveEventJSON();
eventCtrl.plotEventOnMap(context);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
}
protected void onProgressUpdate(Integer... progress) {
}
}
And the method in EventController to get the address based on XY:
public String getStreetAddressFromGeometry(String eventX, String eventY) {
String streetName = "";
try {
URL url = new URL("http://www.onemap.sg/API/services.svc/revgeocode?token=qo/s2TnSUmfLz+32CvLC4RMVkzEFYjxqyti1KhByvEacEdMWBpCuSSQ+IFRT84QjGPBCuz/cBom8PfSm3GjEsGc8PkdEEOEr&location="+eventX+","+eventY+"");
URLConnection conn = (URLConnection) url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String responseString;
while ((responseString = br.readLine()) != null) {
try {
JSONObject rawObj = new JSONObject(responseString);
JSONArray searchResults = rawObj.getJSONArray("GeocodeInfo");
for (int i = 0; i < searchResults.length(); i++) {
streetName = searchResults.getJSONObject(i).getString(
"BLOCK")
+ " " + searchResults.getJSONObject(i).getString("ROAD") + " SINGAPORE";
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return streetName;
}
After I get the address from single tap, I pass it to this method:
public static Event createEventDialog(final Context context,
final double x, final double y, final String eventAddress) {
AlertDialog.Builder AddDialog = new AlertDialog.Builder(context);
AddDialog.setTitle("Add Event");
LayoutInflater li = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dialogView = li.inflate(R.layout.create_event, null);
txtEventName = (EditText) dialogView.findViewById(R.id.txtEventName);
txtEventDesc = (EditText) dialogView.findViewById(R.id.txtEventDesc);
txtEventAddr = (EditText) dialogView.findViewById(R.id.txtEventAddr);
txtEventAddr.setText(eventAddress);
AddDialog.setView(dialogView);
AddDialog.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
AddDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
AddDialog.show();
return addEventModel;
}
However, with these codes, I printed out the address from single tap, it's showing the address. But when I prompt out the dialog box, it supposed to display the address. However, it is not showing anything and after a few seconds, the application shut down with the error message:
11-11 17:18:28.889: E/AndroidRuntime(4439): FATAL EXCEPTION: AsyncTask #2
11-11 17:18:28.889: E/AndroidRuntime(4439): java.lang.RuntimeException: An error occured while executing doInBackground()
11-11 17:18:28.889: E/AndroidRuntime(4439): at android.os.AsyncTask$3.done(AsyncTask.java:278)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
11-11 17:18:28.889: E/AndroidRuntime(4439): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.lang.Thread.run(Thread.java:856)
11-11 17:18:28.889: E/AndroidRuntime(4439): Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0
11-11 17:18:28.889: E/AndroidRuntime(4439): at android.content.res.Resources.getValue(Resources.java:1019)
11-11 17:18:28.889: E/AndroidRuntime(4439): at android.content.res.Resources.getDrawable(Resources.java:663)
11-11 17:18:28.889: E/AndroidRuntime(4439): at Controller.EventController.plotEventOnMap(EventController.java:101)
11-11 17:18:28.889: E/AndroidRuntime(4439): at nyp.edu.eneighbourhood.ENeighbourhoodActivity$MyAsyncTask.doInBackground(ENeighbourhoodActivity.java:213)
11-11 17:18:28.889: E/AndroidRuntime(4439): at nyp.edu.eneighbourhood.ENeighbourhoodActivity$MyAsyncTask.doInBackground(ENeighbourhoodActivity.java:1)
11-11 17:18:28.889: E/AndroidRuntime(4439): at android.os.AsyncTask$2.call(AsyncTask.java:264)
11-11 17:18:28.889: E/AndroidRuntime(4439): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
11-11 17:18:28.889: E/AndroidRuntime(4439): ... 5 more
11-11 17:18:35.725: W/SurfaceView(4439): CHECK surface infomation creating=false formatChanged=false sizeChanged=false visible=false visibleChanged=true surfaceChanged=true realSizeChanged=false redrawNeeded=false left=false top=false
11-11 17:18:37.022: E/WindowManager(4439): Activity nyp.edu.eneighbourhood.ENeighbourhoodActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4169d570 that was originally added here
11-11 17:18:37.022: E/WindowManager(4439): android.view.WindowLeaked: Activity nyp.edu.eneighbourhood.ENeighbourhoodActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4169d570 that was originally added here
11-11 17:18:37.022: E/WindowManager(4439): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:428)
11-11 17:18:37.022: E/WindowManager(4439): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:267)
11-11 17:18:37.022: E/WindowManager(4439): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
11-11 17:18:37.022: E/WindowManager(4439): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
11-11 17:18:37.022: E/WindowManager(4439): at android.view.Window$LocalWindowManager.addView(Window.java:537)
11-11 17:18:37.022: E/WindowManager(4439): at android.app.Dialog.show(Dialog.java:278)
11-11 17:18:37.022: E/WindowManager(4439): at android.app.AlertDialog$Builder.show(AlertDialog.java:932)
11-11 17:18:37.022: E/WindowManager(4439): at nyp.edu.eneighbourhood.CreateEvent.createEventDialog(CreateEvent.java:124)
11-11 17:18:37.022: E/WindowManager(4439): at nyp.edu.eneighbourhood.ENeighbourhoodActivity$3.onSingleTap(ENeighbourhoodActivity.java:192)
11-11 17:18:37.022: E/WindowManager(4439): at com.esri.android.map.MapOnTouchListener.onSingleTap(Unknown Source)
11-11 17:18:37.022: E/WindowManager(4439): at com.esri.android.map.MapGestureDetector$a.onSingleTapConfirmed(Unknown Source)
11-11 17:18:37.022: E/WindowManager(4439): at android.view.GestureDetector$GestureHandler.handleMessage(GestureDetector.java:393)
11-11 17:18:37.022: E/WindowManager(4439): at android.os.Handler.dispatchMessage(Handler.java:99)
11-11 17:18:37.022: E/WindowManager(4439): at android.os.Looper.loop(Looper.java:137)
11-11 17:18:37.022: E/WindowManager(4439): at android.app.ActivityThread.main(ActivityThread.java:4512)
11-11 17:18:37.022: E/WindowManager(4439): at java.lang.reflect.Method.invokeNative(Native Method)
11-11 17:18:37.022: E/WindowManager(4439): at java.lang.reflect.Method.invoke(Method.java:511)
11-11 17:18:37.022: E/WindowManager(4439): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:982)
11-11 17:18:37.022: E/WindowManager(4439): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
11-11 17:18:37.022: E/WindowManager(4439): at dalvik.system.NativeStart.main(Native Method)
11-11 17:18:38.209: I/Process(4439): Sending signal. PID: 4439 SIG: 9
Thanks in advance.
Edit
AddDialog.setView(dialogView);
AddDialog.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addEventModel = new Event();
addEventModel = onConfirmAddEventClicked(context, x, y);
new MyAsyncTask().execute(addEventModel);
dialog.dismiss();
}
});
So here is the part when user select Okay from dialogue box, it will get the user inputs, in this case it was done in onConfirmEventClicked. Then it will call the MyAsyncTask to execute DB insertion.
回答1:
Call eventCtrl.plotEventOnMap(context);
on postExecute
instead. This method appears to change the UI which can't be done on doInBackground
Edit
You will have to call CreateEvent.createEventDialog
only after your AsyncTask finishes. For that I recomend creating an interface and pass it to your task. That will require some coding. Let's get started:
public static class MyAsyncTask extends AsyncTask<Event, Integer, Double> {
public interface OnRoutineFinished{ //interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public MyAsyncTask(OnRoutineFinished callback){ //constructor with interface
mCallbacks = callback;
}
public MyAsyncTask(){} //empty constructor to maintain compatibility
@Override
protected Double doInBackground(Event... params) {
try {
eventAddress = eventCtrl.getStreetAddressFromGeometry(eventModel.getEventX(), eventModel.getEventY());
eventCtrl.retrieveEventJSON();
if (params.length == 1) {
eventCtrl.createEvent(params[0]);
// Refresh map after successfully added event
eventCtrl.retrieveEventJSON();
eventCtrl.plotEventOnMap(context);
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
if(mCallbacks !=null)
mCallbacks.onFinish(); //call interface on finish
}
protected void onProgressUpdate(Integer... progress) {
}
}
Next when you create your asyntask pass the event you want to call when the async finishes:
new MyAsyncTask(new MyAsyncTask.OnRoutineFinished() {
@Override
public void onFinish() {
CreateEvent.createEventDialog(context, point.getX(),
point.getY(), eventAddress); //this will be called after the task finishes
}
}).execute(eventModel);
来源:https://stackoverflow.com/questions/26861594/android-asynctask-2-fatal-exception