2013-06-03 93 views
13

背景如何最好地重新创建标记/折线:当手机被旋转(方向改变)

  • 开发一个原生Android应用程序使用Android的谷歌地图V2,采用android.support.v4.app.FragmentActivity。在Android v2.2上运行。

目的:

  • 在地图上保留 “绘制” 标记/折线手机方向改变之前。

问题(S):

  1. 我可以标记/折线“保存”作为包的一部分,只是必须使用适当的节省他们在onSaveInstanceState他们重新显示savedInstance.put..方法,然后使用适当的savedInstanceState.get..方法在onCreate中“恢复”它们。

    在审查标记getID()说明我很困惑,当谷歌文档Marker.getId() method状态如下:

    地图时从包恢复,标志将原本地图上也恢复。但是,这些标记将由不同的标记对象表示。标记的ID可用于在恢复之后检索标记对象的新实例。

    谷歌文档(上面的粗体文本)使得它听起来像标记只是自动恢复而不必采取任何行动。那不是我的经历......也许我错误地解释了陈述内容。或者,也许你必须明确地将地图保存在Bundle中?有人可以澄清这是什么意思?

  2. 假设我将必须明确地通过适当的savedInstance.put...方法的标记和折线保存到束应该我保存整个标记或应保存的标记ID和使用标记ID来检索标记信息重新显示标记?我找不到能够保存整个标记的put方法。

    我注意到谷歌地图API的Android V2的MapFragment section其规定如下:

    从GoogleMap的获得的任何物体与视图关联。不要坚持物体(例如标记)超出视野的生命。否则会导致内存泄漏,因为视图无法释放。

    此声明使我相信我不应该尝试保存标记本身,而是尝试保存标记ID,然后根据与标记ID关联的标记对象重新生成标记。对于PolyLines也是如此。我的假设是否正确?

  3. 另外,我是否应该避免将标记作为类变量?我担心的是,如果Marker是一个类变量,并且Activity Map片段被放置在后端堆栈上,这可能会导致内存泄漏,因为它将有效地“保留到对象”,如上述文档中所述。这是我应该关心的吗?

问候。

回答

14

我可以标记/折线“保存”作为包的一部分,只是必须使用适当的节省他们在他们的onSaveInstanceState重新显示“savedInstance.put ..”方法,然后选择“恢复”他们在onCreate中使用适当的“savedInstanceState.get ..”方法。

的谷歌文档(以上黑体字)使得它听起来像标记的只是自动的恢复,而不必采取任何行动。那不是我的经历......也许我错误地解释了陈述内容。或者,也许你必须明确地将地图保存在Bundle中?有人可以澄清这是什么意思?

你不会误解任何东西。该文档不正确。

我应该保存标记ID和使用标记ID重新显示标记

标记ID是不能跨越的配置更改的东西永久检索标记信息 - 这取决于视觉序列创建对象(首先调用addMarker返回ID为“m1”的对象,第二个为“m2”)。你不能以任何方式使用这个值(如API版本3.1.36),恕我直言,它的存在确实没有意义。我实际上已经登录an issue related to ID。应该至少有一个功能GoogleMap.getMarkerById(String)Marker.getId()没有什么意义。

3)另外,我是否应该避免将标记作为类变量?我担心的是,如果Marker是一个类变量,并且Activity Map片段被放置在后端堆栈上,这可能会导致内存泄漏,因为它将有效地“保留到对象”,如上述文档中所述。这是我应该关心的吗?

是的。保留对Marker或任何其他可视对象的静态引用会导致泄漏。


不是回答你所有的问题和担忧使它更接近解决方案,所以这里是我的主张。

我假设你有一个数据集,其中MarkersPolylines是从Web服务中获取并可能存储在数据库中。现在,如果您从ActivityAsyncTask中将数据从DB加载,或者甚至不将其存储在DB中,但只能直接在Activity中获取 - 这很糟糕。

尽量让您的数据尽可能可访问,因此只有在进程死亡后(或者在内存不足时将其放下后)才能重新加载到内存中。如果你这么做 - 那很好。当然不是全部:如果您有20000个标记,并且每个标记的图像都显示在信息窗口中,则可以等待...

现在您已经拥有了在内存中创建标记所需的全部数据,只需像第一次那样创建它们即可。无需额外的代码。

我们可以争论这是好还是坏主意,我会改进的答案,但是这需要有关上下文的详细信息:

  • 多少标记和折线
  • 你有什么额外的数据
  • 你在哪里保存你的模型

当然还有另一种方法:你可以发送MarkerOptions in onSaveInstanceState。如果你保持它的最新状态或者你的Markers没有改变,并且没有那么多,这可能对你有用。每次旋转或按HOME按钮都无法通过IPC发送数千个对象。

+0

谢谢梅西......只是澄清一下可以做什么和不可以做什么是非常有帮助的。希望有人针对Google文档提交了一个问题。 – user2101068

+0

作为背景......我只有一个标记,我在这里担心,两条多段线连接到这个标记。标记代表用户在屏幕上点击的位置(tapMarker)。第一条多段线将用户当前的GPS连接连接到tapMarker,第二条多段线将点击标记连接到指定的LatLng。指定的LatLng的数据将存储在数据库中。 – user2101068

+0

在这种情况下,您只需在'onSaveInstanceState'中发送'LatLng'。这是有道理的,因为它是用户活动(就像编辑文本字段一样)。可选择两个'ArrayList '重新创建折线。我认为我的答案会更有用;) –

11

在我看来,在保存地图的片段上调用setRetainInstance(true);可以通过暂停,方向更改等保留地图上的所有内容,而无需担心设置和获取。有没有理由不推荐这种方法?

+0

我可以确认它工作正常!就这么简单。为什么这个帖子没有标记为答案? –

+0

对于一个它不起作用,如果你的地图片段嵌套在另一个片段内。你会得到一个运行时异常。 –

+0

那么如果你在两个碎片上设置了RainainInstance会发生什么? (对不起,远离测试环境,但仍然好奇) – lucas