【问题标题】:Android AsyncTask #2 Fatal ExceptionAndroid AsyncTask #2 致命异常
【发布时间】:2014-11-11 09:30:54
【问题描述】:

我在 Android 中遇到了 AsyncTask #2 致命异常的问题。所以我要做的是单击地图,获取坐标 X 和 Y 并将它们传递给 AsyncTask() 类以执行获取地址的方法。这是我的单击和 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) {
    }
}

以及EventController中根据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;
}

通过单击获得地址后,我将其传递给此方法:

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

但是,使用这些代码,我通过单击打印出地址,它显示了地址。但是当我提示对话框时,它应该显示地址。但是,它没有显示任何内容,几秒钟后,应用程序关闭并显示错误消息:

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

提前致谢。

编辑

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

所以这是用户从对话框中选择 Okay 的部分,它将获取用户输入,在这种情况下,它是在 onConfirmEventClicked 中完成的。然后它会调用 MyAsyncTask 执行 DB 插入。

【问题讨论】:

  • 你能说一下ENeighbourhoodActivity.java:213是哪一行吗?
  • eventCtrl.plotEventOnMap(context);
  • ResourcesNotFoundException 检查资源和 ID
  • resourceNotFoundException 是因为在我的 AsyncTask 中,我只传入了一个参数。所以无论我从对话框中单击确定还是取消,它都只是使用空字段数据执行数据库插入。当我尝试在地图上绘制标记时,它无法加载图像。

标签: java android android-asynctask


【解决方案1】:

请改为在postExecute 上致电eventCtrl.plotEventOnMap(context);。这个方法似乎改变了在doInBackground上无法完成的UI

编辑

您必须在 AsyncTask 完成后调用CreateEvent.createEventDialog。为此,我建议创建一个界面并将其传递给您的任务。这将需要一些编码。让我们开始吧:

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) {
    }
}

接下来,当你创建你的异步任务时,传递你想要在异步完成时调用的事件:

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

【讨论】:

  • 但是当对话框显示时,地址没有显示。我试图在单击方法中将其打印出来,它确实返回了一些东西。你有什么想法吗?
  • 您在启动异步任务后立即调用创建对话框例程。请记住,在您调用异步任务后代码将继续运行,这意味着不会填充 eventAddress。我建议您也将createEventDialog 呼叫更改为onPostExecute
  • 但是这样,即使我从对话框中选择了取消,如果传入的参数为1,它仍然执行if语句中的createEvent。你有什么想法可以扭转这种局面吗?
  • 那是因为添加事件的是你的异步。如果用户单击“是”而不是您的异步​​任务,您应该只调用 eventCtrl.createEvent
  • eventCtrl.createEvent 需要在 myAynstask 中,因为它正在访问我的 servlet 中的方法
猜你喜欢
  • 2015-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 2015-07-12
相关资源
最近更新 更多