【问题标题】:Jumping markers on Android Maps API v2Android Maps API v2 上的跳跃标记
【发布时间】:2015-11-23 10:35:15
【问题描述】:

我看到标记在 Android Maps API v2 上的地图上跳来跳去,即使应用程序中没有发生任何事情。

这是该行为的视频:

https://youtu.be/cOUGD0T5Ojs

我的期望

标记应在其最初添加的纬度/经度处保持静止。

哪些步骤会重现问题?

    1. 构建、安装和运行 OneBusAway 的 v2.0.6 标签:
      • 一个。 git clone https://github.com/OneBusAway/onebusaway-android.git
      • 乙。 git checkout v2.0.6
      • c。 gradlew installObaGoogleDebug
      • d. adb shell am start -n com.joulespersecond.seattlebusbot/org.onebusaway.android.ui.HomeActivity
    1. 浏览到任何受支持的城市(例如西雅图或坦帕),并观看绿色的公交车站标记在地图上四处跳动

我应该补充一点,我不能总是重现这个。似乎在一段时间内一切正常,但当标记开始跳来跳去时,它们并没有停止。

标记实现细节

加载用于 9 种标记类型(8 个方向 + 无方向)的图标的代码如下: https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/google/java/org/onebusaway/android/map/googlemapsv2/StopOverlay.java#L175

我正在使用这个可绘制对象: https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/res/drawable/map_stop_icon.xml

...这是许多形状 - 这将创建带有白色轮廓和阴影的主要绿色圆圈。然后,我在这个可绘制对象的顶部为 8 个方向中的每一个绘制方向箭头 - 绘制方向的代码在这里:

https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/google/java/org/onebusaway/android/map/googlemapsv2/StopOverlay.java#L208

在加载图标的代码中,我缓存了从BitmapDescriptorFactory.fromBitmap() 返回的BitmapDescriptor,用于首次加载时的 9 种图标类型,因此每次在地图上放置标记时都不会这样做.

我还看到应用程序崩溃到“不幸的是,OneBusAway 已停止”。让应用在地图屏幕上停留几分钟后,在 Logcat 中看到了这个异常:

08-10 16:40:02.422  15843-15929/com.joulespersecond.seattlebusbot E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 8614
    Process: com.joulespersecond.seattlebusbot, PID: 15843
    java.lang.IllegalArgumentException: Comparison method violates its general contract!
            at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:831)
            at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:449)
            at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:372)
            at java.util.ComparableTimSort.sort(ComparableTimSort.java:178)
            at java.util.ComparableTimSort.sort(ComparableTimSort.java:142)
            at java.util.Arrays.sort(Arrays.java:1957)
            at java.util.Collections.sort(Collections.java:1864)
            at com.google.maps.api.android.lib6.gmm6.n.bl.a(Unknown Source)
            at com.google.maps.api.android.lib6.gmm6.n.l.a(Unknown Source)
            at com.google.maps.api.android.lib6.gmm6.n.l.b(Unknown Source)
            at com.google.maps.api.android.lib6.gmm6.n.cv.f(Unknown Source)
            at com.google.maps.api.android.lib6.gmm6.n.cv.run(Unknown Source)

我在 LG G4 和 Nexus 6 上看到了这一点。有关 LG 设备的更多详细信息如下。

  • 采用 Android 5.1 (LS991ZV4) 的 LG G4 LS991

  • Google Play 服务客户端库版本 = compile 'com.google.android.gms:play-services-maps:7.5.0'compile 'com.google.android.gms:play-services-maps:7.8.0'

  • 设备上的 Google Play 服务版本 - Google Play 服务 7.8.99 (2134222-440)

  • Android SDK 版本:compileSdkVersion 21 buildToolsVersion "21.1.2"

这个问题并不总是存在,这让我相信它是在某个时候更新到 Android Google Play 服务/地图时引入的。

我也在 gmaps-api-issues 上为此打开了一个问题,但在这篇文章中没有任何回应:

https://code.google.com/p/gmaps-api-issues/issues/detail?id=8455

还有其他人看过吗?有什么解决办法吗?

编辑

我应该补充一点,我不能总是重现这个。似乎在一段时间内一切正常,但当标记开始跳来跳去时,它们并没有停止。

编辑 2

我在 Github 上创建了一个较小的演示项目,它使用相同的标记实现:

https://github.com/barbeau/maps-demo

但是,我还没有看到同样的问题。

编辑 3

我已更改为缓存 Bitmaps 而不是 https://github.com/OneBusAway/onebusaway-android/commit/01b35e9a07313a627843819d66b3f6a9bb7e848f 中的 BitmapDescriptors

我们会看看这是否能解决问题。它是间歇性的,所以我知道的唯一方法是我是否在一段时间内不再看到问题。

编辑 4

我仍然看到问题,所以看起来从缓存BitmapDescriptors 切换到Bitmaps,并更改为使用ContextCompat.getDrawable(),没有任何效果。

编辑 5

不确定这是否相关,但发生这种情况时,我还在 Logcat 中看到以下输出:

09-01 10:46:00.339 9278-9278/? E/libEGL: validate_display:255 错误 3008 (EGL_BAD_DISPLAY) 09-01 10:46:00.339 9278-9278/? E/libEGL: validate_display:255 错误 3008 (EGL_BAD_DISPLAY)

9-01 10:46:00.069 9278-9278/? W/ResourcesManager:资产路径'/system/framework/com.google.android.maps.jar'不存在或不包含资源。

09-01 10:46:16.019 1137-4311/? W/ActivityManager:计划在 1000 毫秒内重新启动崩溃的服务 com.google.android.gms/.usagereporting.service.UsageReportingService 09-01 10:46:16.019 1137-4311/? W/ActivityManager:计划在 11000 毫秒内重新启动崩溃的服务 com.google.android.gms/.icing.service.IndexService

09-01 10:48:38.609 5402-26676/? E/SQLiteDatabase:错误插入 context_name=8 end_time=1441118918490 context_family=7 module_id=com.google.android.contextmanager.module.PowerConnectionModule version=1 sync_state_mod_time_millis=1441118918532 start_time=1441118643058 sync_state=0 context_id=9680c4f4-789a-4 43d2098e89b8 time_type=3 proto_blob=[B@28265a3 android.database.sqlite.SQLiteConstraintException:唯一约束失败:context.context_id(代码 2067) 在 android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(本机方法) 在 android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:790) 在 android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:926) 在 android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86) 在 android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1581) 在 android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1451) 在 com.google.android.contextmanager.q.ak.a(SourceFile:405) 在 com.google.android.contextmanager.q.ak.b(SourceFile:380) 在 com.google.android.contextmanager.q.ak.a(SourceFile:346) 在 com.google.android.contextmanager.q.ak.b(SourceFile:373) 在 com.google.android.contextmanager.g.a.j.a(SourceFile:58) 在 com.google.android.contextmanager.g.a.a.run(SourceFile:52) 在 com.google.android.contextmanager.g.i.handleMessage(SourceFile:214) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:135) 在 android.os.HandlerThread.run(HandlerThread.java:61)

编辑 6 我最近没有看到这个问题,我注意到 LG G4 设备上的 Google Play 服务被撞到了8.1.15 (2250156-240)。那么,也许它是通过更新 Google Play 服务来解决的?我稍后再报告。

编辑 7 我在8.1.15 (2250156-240)8.1.18 (2272748-240) 中再次看到了这一点,尽管它看起来不像以前那么糟糕(即,更少的标记跳来跳去,并且跳跃不太明显)。它似乎主要是在应用程序处于后台一段时间后恢复应用程序时触发的。如果我杀死应用程序然后重新启动它,问题就会消失。

编辑 8 我找到了一种方法来始终如一地重现这一点 - 请参阅: https://code.google.com/p/gmaps-api-issues/issues/detail?id=8455#c2

从上述问题:

  1. 构建、安装和运行 OneBusAway 的 v2.0.6 标签:

    一个。 git clone https://github.com/OneBusAway/onebusaway-android.git

    b. git checkout v2.0.6

    c。 gradlew installObaGoogleDebug

    d。 adb shell am start -n com.joulespersecond.seattlebusbot/org.onebusaway.android.ui.HomeActivity

  2. 纵向握住设备

  3. 如果您实际上不在西雅图或坦帕(或任何受支持的地区),则需要转到“设置->您的地区”并手动设置地区。完成此操作后,将地图滚动到该地区(或在出现提示时选择“带我去那里”)。
  4. 点击地图上的巴士站
  5. 点击到达时间旁边的 3 个点“更多”按钮(或在滑动面板的列表中点击到达)
  6. 点击“在地图上显示路线”选项
  7. 在地图上加载路线后,将设备方向更改为横向。
  8. 在地图重新加载后观察标记跳来跳去

在 LG G4 上拍摄的完整视频显示了制作和发布的新步骤: https://youtu.be/oiBoMTPDVrU

【问题讨论】:

  • 您是否尝试在地图上调用 clear 方法而不是在每个标记上调用 remove?
  • 我避免使用GoogleMap.clear(),因为这会产生闪烁。当地图移动时,应用程序会使用边界框视图访问服务器,并返回位于该边界框内的公交车站。我在内部有一个HashMap,它正在跟踪哪些站点已经添加到地图中,所以我只添加新的站点。最初我尝试调用.clear() 并重新添加所有站点,但这会严重闪烁。另外,我不想清除地图上的其他标记。目前,当我超过阈值时,我为所有标记调用 Marker.remove(),然后重新开始。

标签: android google-play-services google-maps-android-api-2


【解决方案1】:

我认为这肯定与同时存在的多个SupportMapFragment 实例有关。在v2.0.6 中,当 Activity 被销毁并使用 savedInstanceState 重新创建时(即,当 Activity 在后台运行一段时间后或在方向改变时被杀死时),我没有正确处理片段。

v2.0.6 中,我的代码如下所示:

public class HomeActivity ...{

    BaseMapFragment mMapFragment;

    ...

    private void showMap() {
        FragmentManager fm = getSupportFragmentManager();
        if (mMapFragment == null) {
                mMapFragment = BaseMapFragment.newInstance();
                fm.beginTransaction()
                    .add(R.id.main_fragment_container, mMapFragment)
                    .commit();
        }
    }
    ...
}

因此,在这些情况下,我泄露了 BaseMapFragment 的一个实例(它扩展了 SupportMapFragment) - FragmentManager 中已经存在一个实例,但我没有对它的本地引用。当我正在处理的另一个片段复制操作栏菜单项时,我实际上注意到了这个问题。

我将代码更改为如下所示,它首先检查FragmentManager 是否有一个现有的BaseMapFragment

public class HomeActivity ...{

    BaseMapFragment mMapFragment;

    ...

    private void showMap() {
        FragmentManager fm = getSupportFragmentManager();            
        // First check to see if an instance of BaseMapFragment already exists            
        mMapFragment = (BaseMapFragment) fm.findFragmentByTag(BaseMapFragment.TAG);

        if (mMapFragment == null) {
            mMapFragment = BaseMapFragment.newInstance();
            fm.beginTransaction()
                    .add(R.id.main_fragment_container, mMapFragment, BaseMapFragment.TAG)
                    .commit();
        }
    }
    ...
}

主分支中的 UI 流程发生了变化(我不再打开新的 Activity 来查看路由),因此如果在此代码更改后问题仍然可重现,我无法直接在那里测试。

然而,我创建了这个分支,它从 master 分支,但更改为具有与 v2.0.6 相同的 UI 流程,并包括上述片段泄漏修复:

https://github.com/CUTR-at-USF/onebusaway-android/tree/jumpingMarkersTest

通过对该分支的一些快速测试,似乎在方向更改时正确处理片段(即,不泄漏片段)可能已经修复了跳跃标记问题 - 至少使用上述步骤它不再在装有 Android 5.1 的 LG G4 上重现。

【讨论】:

  • 我遇到了完全相同的问题。通过按照上面的建议修复片段,它还修复了跳跃标记。
  • 我没有泄漏片段实例的问题。但是我遇到了这个跳跃标记问题任何帮助
猜你喜欢
  • 1970-01-01
  • 2013-03-30
  • 2014-01-28
  • 1970-01-01
  • 2012-12-31
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-11-25
相关资源
最近更新 更多