【问题标题】:Android java.lang.IllegalStateException, not on the main threadAndroid java.lang.IllegalStateException,不在主线程上
【发布时间】:2016-09-01 04:49:20
【问题描述】:

我在 Android 中使用谷歌地图时遇到问题。我想从互联网上获取一些数据(比如地图可见部分的单位)。当我想从 onPostExecute 中的地图中清除所有以前的标记时,问题就开始了。代码如下:

private class GetNewPins extends AsyncTask<Void, String, Unit[]>
{

    @Override
    protected Unit[] doInBackground(Void... f_url)
    {
        try
        {
            LatLng campos = map.getCameraPosition().target;
            VisibleRegion vr = map.getProjection().getVisibleRegion();
            double left = vr.latLngBounds.southwest.longitude;
            double top = vr.latLngBounds.northeast.latitude;
            double right = vr.latLngBounds.northeast.longitude;
            double bottom = vr.latLngBounds.southwest.latitude;
            Location middleLeftCornerLocation = new Location("right");
            Location center = new Location("center");
            middleLeftCornerLocation.setLatitude(right);
            middleLeftCornerLocation.setLongitude(vr.latLngBounds
                    .getCenter().longitude);
            center.setLatitude(vr.latLngBounds.getCenter().latitude);
            center.setLongitude(vr.latLngBounds.getCenter().longitude);
            float dis = center.distanceTo(middleLeftCornerLocation);
            System.out.println("Gettin' data from " + campos.latitude + " "
                    + campos.longitude + " " + dis);
            Unit[] units = new FreechargingAPI().GetUnitsOnMap(
                    campos.latitude, campos.longitude, dis);
            if (units != null)
            {
                return units;
            }

        } catch (Exception e)
        {
            System.out.println(e);
        }
        return null;
    }

    @Override
    protected void onPostExecute(final Unit[] units)
    {
        if (units == null)
        {
            return;
        }

        MapView.this.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                map.clear();
                for (Unit u : units)
                {
                    // Creating an instance of MarkerOptions to set position
                    MarkerOptions markerOptions = new MarkerOptions();

                    // Setting position on the MarkerOptions
                    markerOptions.position(new LatLng(Double.parseDouble(u
                            .getUnitgpslatitude()), Double.parseDouble(u
                            .getUnitgpslongitude())));

                    // Adding marker on the GoogleMap
                    Marker marker = map.addMarker(markerOptions.title(
                            u.getUnitname()).snippet(
                            DistanceConverter.convert(u.getDistance())));

                    // Showing InfoWindow on the GoogleMap
                    marker.showInfoWindow();

                }
            }// public void run() {
        });


    }
}

如您所见,我已经尝试对问题 map.clear() “未运行主线程”进行一些研究,但没有成功,因为 asynctask 根本没有运行,我得到的只是只是这个非法状态异常:不在主线程上。

EDIT1:不,它甚至在普通的 onpostexecute 中都不起作用,而且我仍然没有在主线程上工作

EDIT2:由于我完全忘记了堆栈跟踪,我意识到我在后台进程中有一个 try catch 块,抱歉,我在凌晨 4 点编写了该代码。所以堆栈跟踪是:

 11-05 10:48:56.504: W/System.err(5498): java.lang.IllegalStateException: Not on the main thread
 11-05 10:48:56.504: W/System.err(5498):    at com.google.j.a.cl.b(Unknown Source)
 11-05 10:48:56.504: W/System.err(5498):    at com.google.maps.api.android.lib6.c.br.b(Unknown Source)
 11-05 10:48:56.504: W/System.err(5498):    at com.google.maps.api.android.lib6.c.dw.a(Unknown Source)
 11-05 10:48:56.504: W/System.err(5498):    at com.google.android.gms.maps.internal.l.onTransact(SourceFile:51)
 11-05 10:48:56.505: W/System.err(5498):    at android.os.Binder.transact(Binder.java:380)
 11-05 10:48:56.505: W/System.err(5498):    at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a.getCameraPosition(Unknown Source)
 11-05 10:48:56.505: W/System.err(5498):    at com.google.android.gms.maps.GoogleMap.getCameraPosition(Unknown Source)
 11-05 10:48:56.505: W/System.err(5498):    at com.reddatura.freecharging_beta.MapView$GetNewPins.doInBackground(MapView.java:241)
 11-05 10:48:56.505: W/System.err(5498):    at com.reddatura.freecharging_beta.MapView$GetNewPins.doInBackground(MapView.java:1)
 11-05 10:48:56.505: W/System.err(5498):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
 11-05 10:48:56.505: W/System.err(5498):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 11-05 10:48:56.505: W/System.err(5498):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
 11-05 10:48:56.505: W/System.err(5498):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
 11-05 10:48:56.505: W/System.err(5498):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
 11-05 10:48:56.505: W/System.err(5498):    at java.lang.Thread.run(Thread.java:818)

为此感谢彼得。所以问题似乎并不像我最初想象的那样出在 onPostExecute,但它是 doinbackground,我想在其中获取 campos 变量

EDIT3:正如 Adogeon 建议的那样,我已将整个事情放在主循环中,但有一个例外,我知道,只是为了我使用 asynctask 的原因......但我倾向于其他建议

11-05 11:28:06.926: W/System.err(6417): android.os.NetworkOnMainThreadException
11-05 11:28:06.927: W/System.err(6417):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
11-05 11:28:06.927: W/System.err(6417):     at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249)
11-05 11:28:06.927: W/System.err(6417):     at libcore.io.IoBridge.recvfrom(IoBridge.java:553)
11-05 11:28:06.927: W/System.err(6417):     at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485)
11-05 11:28:06.927: W/System.err(6417):     at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
11-05 11:28:06.927: W/System.err(6417):     at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
11-05 11:28:06.927: W/System.err(6417):     at com.android.okio.Okio$2.read(Okio.java:113)
11-05 11:28:06.927: W/System.err(6417):     at com.android.okio.RealBufferedSource.indexOf(RealBufferedSource.java:147)
11-05 11:28:06.927: W/System.err(6417):     at com.android.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:94)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:175)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:616)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:379)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)
11-05 11:28:06.928: W/System.err(6417):     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:190)
11-05 11:28:06.928: W/System.err(6417):     at com.reddatura.serverside.FreechargingAPI.ExecuteGET(FreechargingAPI.java:42)
11-05 11:28:06.928: W/System.err(6417):     at com.reddatura.serverside.FreechargingAPI.GetUnitsOnMap(FreechargingAPI.java:100)
11-05 11:28:06.928: W/System.err(6417):     at com.reddatura.freecharging_beta.MapView$1.onMapSettled(MapView.java:101)
11-05 11:28:06.928: W/System.err(6417):     at com.reddatura.listeners.MapStateListener.settleMap(MapStateListener.java:119)
11-05 11:28:06.928: W/System.err(6417):     at com.reddatura.listeners.MapStateListener$4$1.run(MapStateListener.java:78)
11-05 11:28:06.928: W/System.err(6417):     at android.os.Handler.handleCallback(Handler.java:739)
11-05 11:28:06.928: W/System.err(6417):     at android.os.Handler.dispatchMessage(Handler.java:95)
11-05 11:28:06.928: W/System.err(6417):     at android.os.Looper.loop(Looper.java:135)
11-05 11:28:06.928: W/System.err(6417):     at android.app.ActivityThread.main(ActivityThread.java:5221)
11-05 11:28:06.928: W/System.err(6417):     at java.lang.reflect.Method.invoke(Native Method)
11-05 11:28:06.929: W/System.err(6417):     at java.lang.reflect.Method.invoke(Method.java:372)
11-05 11:28:06.929: W/System.err(6417):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
11-05 11:28:06.929: W/System.err(6417):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

EDIT X:没关系,伙计们,我把它弄得很丑,但现在它似乎有效......在 asynctask 执行之前移动了所有“基于地图的东西”,所以我在线程之间传递东西,这非常不安全,但它确实有效,其他都不重要。愿上帝怜悯我的灵魂,因为我将犯下的罪... 谢谢大家的帮助:)

【问题讨论】:

  • OnPostExecute 已经在主线程中了,你不应该需要runOnUiThread,把你的代码放在那里
  • 我也试过了,但结果一样
  • 在询问有关异常的问题时,请始终包含完整的堆栈跟踪。
  • 你如何调用你的异步任务?

标签: java android multithreading google-maps


【解决方案1】:

您应该在主线程上调用该操作。您不能在主线程以外的地方操作视图(例如在 doInBackground 方法中)。 只需删除异步任务即可。

【讨论】:

  • 但 Unit[] 单位 = new FreechargingAPI().GetUnitsOnMap(campos.latitude, campos.longitude, dis);是网络运营
【解决方案2】:

Adogeon 说“你应该在主线程上调用操作。你不能在主线程以外的地方操作视图(例如在 doInBackground 方法中)”时是正确的。

Citrus,更具体地说,您的问题在以下代码块上:

LatLng campos = map.getCameraPosition().target;
VisibleRegion vr = map.getProjection().getVisibleRegion();

当您调用 ma​​p.someFunction() 时。你不能在那里调用视图的方法。

【讨论】:

    【解决方案3】:

    我是这样做的:

    vr = map.getProjection().getVisibleRegion();
    LatLng curPos = map.getCameraPosition().target;
    if (prevPos.latitude != curPos.latitude
            || prevPos.longitude != curPos.longitude)
    {
        new GetNewPins().execute(curPos);
    }
    

    vr 是 VisibleRegion,它是类中的私有字段,将由 GetNewPins 使用。另外我已经将参数更改为 GetNewPins 的 LatLng,所以现在所有与谷歌地图相关的东西都在主线程上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-11
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 2017-01-11
      • 1970-01-01
      相关资源
      最近更新 更多