【问题标题】:IndexOutOfBound Exception throwing Android抛出 Android 的 IndexOutOfBound 异常
【发布时间】:2012-09-25 13:02:44
【问题描述】:

我已经制作了一个 android 应用程序,因为数据来自服务器,所以这是一个耗时的过程,所以我创建了一个进度对话框..

下面是我的代码

  @Override
protected void onResume() {
    super.onResume();
    if (placesListItems != null)
        placesListItems.clear();
    new LoadPlaces().execute();
}

@Override
public void onPause() {
    super.onPause();
    if (pDialog != null)
        pDialog.dismiss();
}


  class LoadPlaces extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage(Html.fromHtml("<b>Search</b><br/>Loading Places..."));
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
    }



  protected String doInBackground(String... args) {

        GooglePlaces googlePlaces = new GooglePlaces();

        try {
            double radius = 1000; // 10000 meters

            // get nearest places
            if (query != null) {
                nearPlaces = googlePlaces.search(lat, lon, radius, query);
                if (nearPlaces != null) {

                    for (Place p : nearPlaces.results) {
                        reference = p.reference;
                        lat = p.geometry.location.lat;
                        lon = p.geometry.location.lng;
                        break;
                    }
                }
            }

            String types = "bar|restaurant|night_club|gym|health|food|shopping_mall|hospital";

            if (reference != null) {
                PlaceDetails placeDetails = googlePlaces.getPlaceDetails(reference);
                if (placeDetails != null) {
                    String status = placeDetails.status;

                    // check place deatils status
                    // Check for all possible status
                    if (status.equals("OK")) {
                        if (placeDetails.result != null) {
                            lat = placeDetails.result.geometry.location.lat;
                            lon = placeDetails.result.geometry.location.lng;
                            nearDeals = googlePlaces.search(lat, lon, radius, types);

在下面的代码中,如果我在从服务器获取数据期间按下主页按钮或屏幕消失(您可以说进度对话框正在运行),如果我回到我的应用程序,我收到错误 ARRAY INDEX OUT OF BOUND

                    // int total = ;
                            for (int i = nearDeals.results.size() - 1; i >= 0; i--) {
                                // Log.i("WHAT THE HELL",nearPlaces.results.get(i).name);
                                if (getResult(nearDeals.results.get(i).name, nearDeals.results.get(i).geometry.location.lat,
                                        nearDeals.results.get(i).geometry.location.lng) == 0) {
                                    // nearDeals.results.add(nearPlaces.results.get(i));
                                    nearDeals.results.remove(i);

                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

下面是logcat

  09-25 18:23:13.429: W/System.err(4375): java.lang.IndexOutOfBoundsException: Invalid index 15, size is 15
  09-25 18:23:13.429: W/System.err(4375):   at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
  09-25 18:23:13.429: W/System.err(4375):   at java.util.ArrayList.get(ArrayList.java:311)
  09-25 18:23:13.429: W/System.err(4375):   at com.eheuristics.android.diegodeals.googleplacesandmaps.MainActivity$LoadPlaces.doInBackground(MainActivity.java:204)
  09-25 18:23:13.429: W/System.err(4375):   at com.eheuristics.android.diegodeals.googleplacesandmaps.MainActivity$LoadPlaces.doInBackground(MainActivity.java:1)
  09-25 18:23:13.429: W/System.err(4375):   at android.os.AsyncTask$2.call(AsyncTask.java:185)
  09-25 18:23:13.439: W/System.err(4375):   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
  09-25 18:23:13.439: W/System.err(4375):   at java.util.concurrent.FutureTask.run(FutureTask.java:138)
  09-25 18:23:13.439: W/System.err(4375):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
  09-25 18:23:13.439: W/System.err(4375):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  09-25 18:23:13.439: W/System.err(4375):   at java.lang.Thread.run(Thread.java:1019)

如果我不按主页键,或者在进度对话框运行期间屏幕不熄灭,那么一切正常

//从大家那里得到解决方案后,我已经按照所有人的建议进行了打击,但我遇到了另一个错误,例如打击

    LoadPlaces ob;


    protected void onResume() {
    super.onResume();
    if (placesListItems != null)
        placesListItems.clear();
    ob.execute();
}

@Override
public void onPause() {
    super.onPause();
    if(ob!=null)
    if(ob.getStatus() == AsyncTask.Status.RUNNING){
       ob.cancel(true);
    }

    if (pDialog != null)
        pDialog.dismiss();
}

然后我得到如下错误

   09-25 18:53:30.609: E/AndroidRuntime(4674): java.lang.RuntimeException: Unable to resume activity {com.eheuristics.android.diegodeals/com.eheuristics.android.diegodeals.googleplacesandmaps.MainActivity}: java.lang.IllegalStateException: Cannot execute task: the task is already running.
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2241)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2256)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:965)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.os.Handler.dispatchMessage(Handler.java:99)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.os.Looper.loop(Looper.java:130)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.app.ActivityThread.main(ActivityThread.java:3835)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at java.lang.reflect.Method.invokeNative(Native Method)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at java.lang.reflect.Method.invoke(Method.java:507)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at dalvik.system.NativeStart.main(Native Method)
  09-25 18:53:30.609: E/AndroidRuntime(4674): Caused by: java.lang.IllegalStateException: Cannot execute task: the task is already running.
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.os.AsyncTask.execute(AsyncTask.java:380)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at com.eheuristics.android.diegodeals.googleplacesandmaps.MainActivity.onResume(MainActivity.java:137)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150)
  09-25  18:53:30.609: E/AndroidRuntime(4674):  at android.app.Activity.performResume(Activity.java:3832)
  09-25  18:53:30.609: E/AndroidRuntime(4674):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2231)
  09-25 18:53:30.609: E/AndroidRuntime(4674):   ... 10 more

【问题讨论】:

  • 你能指出 MainActivity.java 中的第 204 行吗?您的neardeals.results 列表大小为 0,这意味着它没有索引,这意味着它没有被填充。
  • 你怎么能说列表大小为零,如果它是零,我不会得到像 Invalid index 15, size is 15 这样的异常
  • 请不要在你的代码中骂人 (;_;)
  • 204 行是 if (getResult(nearDeals.results.get(i).name, nearDeals.results.get(i).geometry.location.lat, nearDeals.results.get(i) ).geometry.location.lng) == 0) {
  • nearDeals.results 线程安全吗?即在迭代时大小可能会改变吗?

标签: java android exception


【解决方案1】:

每次显示活动时,您都会启动 asynctask。所以,你应该在退出时取消任务(AsyncTask.cancel(true)),或者在onResume方法中检查它是否还在运行。

【讨论】:

  • 你说得对,我每次都在启动 asynctask,因为如果用户回到以前的活动,他应该得到新的刷新数据
  • 好的,但是每次执行“new LoadPlaces().execute();”时,最后一个异步任务和新的异步任务同时执行!
  • 首先谢谢,我已经更改了代码,但仍然出现另一个错误
【解决方案2】:

如果你得到错误 onResume() 被再次调用,启动一个新的 AsyncTask。现在您有多个 AsyncTask 同时访问和更改 nearDeals.results 的大小(您在其上调用 remove)。当一个 asyncTask 从列表中删除一个项目时,第二个 asyncTask 可能会遇到 ArrayIndexOutOfBounds,因为列表大小已更改。

编辑:这实际上不是删除项目,而是您在 googlePlaces.search 中设置了列表的新实例,并且此列表的大小可能与旧 asynctask 使用的大小不同。

解决方案:在 onPause(或 onResume 开始前)中对正在运行的异步任务调用取消 新任务)

【讨论】:

  • 首先谢谢,我已经更改了代码,但仍然出现另一个错误
  • 您需要在onResume中创建一个新的AsyncTask实例,您无法重新启动之前取消的任务。
  • 是的,但是如果我按下主页按钮并再次返回 2 到 3 次,仍然会发生同样的错误,而不是会发生错误:(
  • 哪一个?非法状态还是 indexoutofbounds?
  • 如果我正确理解你的代码,nearDeals 当前是你的 Activity 的成员变量。也许首先在异步任务中创建一个局部变量是有意义的,然后遍历操作列表的结果,并且只有在你完成将新列表设置为全局成员变量之后。这应该可以消除同时访问的大部分副作用。
猜你喜欢
  • 2012-01-31
  • 1970-01-01
  • 2012-09-30
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-12
相关资源
最近更新 更多