【问题标题】:Multiple request in AsyncTask AndroidAsyncTask Android中的多个请求
【发布时间】:2014-11-11 12:36:39
【问题描述】:

我在使用 Android 中的 AsyncTask 时遇到了一些问题。因此,当单击地图时,它会通过在 AsyncTask 类中传递一个 Event 对象作为参数来执行该方法,以获取基于坐标 X 和 Y 的地址:

mMapView.setOnSingleTapListener(new OnSingleTapListener() {
        public void onSingleTap(float x, float y) {
            final Point point = mMapView.toMapPoint(x, y);
                eventModel.setEventX(String.valueOf(point.getX()));
                eventModel.setEventY(String.valueOf(point.getY()));
                 new MyAsyncTask(new MyAsyncTask.OnRoutineFinished() {
                        public void onFinish() {
                             CreateEvent.createEventDialog(context, point.getX(),
                                    point.getY(), eventAddress);  //this will be called after the task finishes
                        }
                    }).execute(eventModel);         
            }
    });
    new MyAsyncTask().execute();
}

MyAsyncTask 类

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

用户单击地图后,会弹出一个对话框询问用户输入:

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(capitalize(eventAddress));

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

    AddDialog.setNegativeButton("Cancel",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    dialog.dismiss();
                }
            });
    AddDialog.show();

    return addEventModel;
}

一旦用户点击 Okay,它将通过 servlet 将 DB 插入 MySQL。 onConfirmAddEventClicked() 基本上是获取每个属性的所有用户输入和设置值,并作为 Event 对象返回。

然而,我现在遇到的问题是,即使用户点击取消,它仍然只使用坐标 X 和 Y 执行 DB 插入。我猜这是因为 MyAsynctask 中的 if 语句接受了一个参数。

有什么方法可以只在用户点击 Okay 时执行 DB 插入?提前致谢。

编辑

mMapView.setOnSingleTapListener(new OnSingleTapListener() {
        private static final long serialVersionUID = 1L;

        public void onSingleTap(float x, float y) {
            final Point point = mMapView.toMapPoint(x, y);
                eventModel.setEventX(String.valueOf(point.getX()));
                eventModel.setEventY(String.valueOf(point.getY()));
                 new MyAsyncTask().execute(eventModel);         
            }
    });
    new MyAsyncTask().execute();
}

protected void onPostExecute(Double result) {
        if(mCallbacks !=null)
            mCallbacks.onFinish(); //call interface on finish
         CreateEvent.createEventDialog(context, Double.parseDouble(eventModel.getEventX()),
                    Double.parseDouble(eventModel.getEventY()), eventAddress);
    }

使用这些代码,我收到以下错误消息:

11-11 21:41:29.457: D/dalvikvm(7062): GC_CONCURRENT freed 457K, 12% free 11022K/12423K, paused 74ms+124ms
11-11 21:41:34.074: D/dalvikvm(7062): GC_CONCURRENT freed 620K, 13% free 11021K/12551K, paused 56ms+237ms
11-11 21:41:37.589: D/dalvikvm(7062): GC_CONCURRENT freed 597K, 13% free 11018K/12615K, paused 29ms+7ms
11-11 21:41:39.441: D/AndroidRuntime(7062): Shutting down VM
11-11 21:41:39.441: W/dalvikvm(7062): threadid=1: thread exiting with uncaught exception (group=0x40c7e1f8)
11-11 21:41:39.464: E/AndroidRuntime(7062): FATAL EXCEPTION: main
11-11 21:41:39.464: E/AndroidRuntime(7062): java.lang.NullPointerException
11-11 21:41:39.464: E/AndroidRuntime(7062):     at java.lang.StringToReal.parseDouble(StringToReal.java:244)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at java.lang.Double.parseDouble(Double.java:295)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at nyp.edu.eneighbourhood.ENeighbourhoodActivity$MyAsyncTask.onPostExecute(ENeighbourhoodActivity.java:227)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at nyp.edu.eneighbourhood.ENeighbourhoodActivity$MyAsyncTask.onPostExecute(ENeighbourhoodActivity.java:1)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.os.AsyncTask.finish(AsyncTask.java:602)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.os.AsyncTask.access$600(AsyncTask.java:156)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.os.Looper.loop(Looper.java:137)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at android.app.ActivityThread.main(ActivityThread.java:4512)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at java.lang.reflect.Method.invokeNative(Native Method)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at java.lang.reflect.Method.invoke(Method.java:511)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:982)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
11-11 21:41:39.464: E/AndroidRuntime(7062):     at dalvik.system.NativeStart.main(Native Method)
11-11 21:41:56.082: I/dalvikvm(7062): threadid=3: reacting to signal 3
11-11 21:41:56.160: I/dalvikvm(7062): Wrote stack traces to '/data/anr/traces.txt'

【问题讨论】:

  • 让选民介意解释一下?

标签: java android mysql android-asynctask


【解决方案1】:

我认为这个错误的发生是因为当用户重复输入时会运行多个AsyncTasks

如果可能,请尝试将您的 dialog.dismiss();setPositiveButton 移动到 onPostExecute。这样做将确保dialogAsyncTask 完成其任务之前不会关闭,因此(我认为)将摆脱该错误。

更新

我刚刚意识到你执行了 AsyncTask 2 次:

mMapView.setOnSingleTapListener(new OnSingleTapListener() {
        public void onSingleTap(float x, float y) {
            final Point point = mMapView.toMapPoint(x, y);
                eventModel.setEventX(String.valueOf(point.getX()));
                eventModel.setEventY(String.valueOf(point.getY()));
                 new MyAsyncTask(new MyAsyncTask.OnRoutineFinished() {
                        public void onFinish() {
                             CreateEvent.createEventDialog(context, point.getX(),
                                    point.getY(), eventAddress);  //this will be called after the task finishes
                        }
                    }).execute(eventModel);  //1st       
            }
    });
    //new MyAsyncTask().execute(); //2nd, try to comment this
}

如果它仍然不起作用,请查看我的 cmets 并尝试将 createEventDialog 移动到 onPostExecute(不再需要使用 callbackonFInish

【讨论】:

  • 但是现在的问题是,例如我在地图上单击,它获取坐标 X 和 Y 并立即执行 eventCtrl.createEvent 而不是进入 createEventDialog 并仅在用户单击确定后执行。 :(
  • @IWasSoLost 请查看我的更新答案。尝试仅使用 1 个 AsyncTask 来简化您的代码
  • 我需要单击 asyncTask 来获取地址并将其传递给 createEventDialog
  • 尝试删除onFinish,把createEventDialog移到onPostExecute...看看有什么不同
  • 实际上我需要 onFinish 以便 createDialogEvent 填充 eventAddress。那么你有什么想法吗?
猜你喜欢
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多