旋转手机时如何最好地重新创建标记/折线(方向更改)

时间:2013-06-03 17:34:51

标签: android android-maps-v2

背景

  • 开发使用Android Google Map v2的原生Android应用,使用android.support.v4.app.FragmentActivity。在Android v2.2上运行。

目的:

  • 在电话方向改变之前,在地图上“保留标记/折线”。

问题(S):

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

    在审核标记getID()的说明时,当Marker.getId() method的Google文档声明如下时,我感到困惑:

      

    从捆绑包恢复地图时,该地图上的标记也会恢复。但是,这些标记将由不同的标记对象表示。标记的id可用于在恢复之后检索Marker对象的新实例。

    Google文档(上面的粗体文字)听起来就像Marker's只是自动恢复而无需采取任何行动。那不是我的经历......也许我错误地解释了所陈述的内容。或者你可能必须在Bundle中明确保存地图?有人可以澄清这意味着什么吗?

  2. 假设我必须通过适当的savedInstance.put...方法明确地将标记和折线保存到包中,我应该保存整个标记还是应该保存标记ID并使用标记检索标记信息id重新显示标记?我找不到允许我保存整个标记的put方法。

    我注意到Google Maps Android API v2的MapFragment section声明了以下内容:

      

    从GoogleMap获取的任何对象都与视图相关联。重要的是不要在视图的生命之外保持对象(例如标记)。否则会导致内存泄漏,因为视图无法释放。

    这句话让我相信我不应该尝试保存标记本身,而是尝试保存标记ID,然后根据与标记id关联的标记对象重新生成标记。同样对于PolyLines。我的假设是否正确?

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

  4. 问候。

2 个答案:

答案 0 :(得分:14)

  

我可以将标记/折线“保存”为捆绑包的一部分,只需使用适当的“savedInstance.put ..”方法将它们保存在onSaveInstanceState中,然后使用onCreate中的“恢复”它们重新显示它们适当的“savedInstanceState.get ..”方法。

没有

  

Google文档(上面的粗体文字)听起来就像Marker's只是自动恢复而无需采取任何行动。那不是我的经历......也许我错误地解释了所陈述的内容。或者你可能必须在Bundle中明确保存地图?有人可以澄清这意味着什么吗?

你没有误解任何事情。文档不正确。

  

我应该保存标记ID并使用标记ID检索标记信息以重新显示标记

标记ID在配置更改中不是永久性的 - 它取决于可视对象创建的顺序(首先调用addMarker返回ID为“m1”的对象,第二个“m2”)。你不能以任何方式使用这个值(从API版本3.1.36开始)和恕我直言,它确实没有任何意义。我实际上是在an issue related to ID进行了总结。 <{1}}至少应该有一个函数GoogleMap.getMarkerById(String)没有意义。

  

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

是。保持对Marker.getId()或任何其他可视对象的静态引用会导致泄漏。


并非回答所有问题和疑虑使其更接近解决方案,所以这是我的主张。

我假设你有一个数据集MarkerMarkers是从中创建的,并且可能在从webservice获取后存储在数据库中。现在,如果您从Polylines AsyncTask中的数据库加载它,或者甚至不将其存储在Activity中,但只能直接获取DB - 这很糟糕。

尝试尽可能使数据可访问,因此只需在进程被终止后(或在内存不足时丢弃它)后重新加载到内存中。如果你这样做 - 这很好。当然不是全部:如果您有20000个标记,并且每个标记都在信息窗口中显示,则可以等待......

现在你拥有了在内存中创建标记所需的所有数据,只需像第一次那样创建它们。无需其他代码。

我们可以争论这是好的还是坏的想法,我会改进答案,但这需要更多关于背景的信息:

  • 有多少标记和折线
  • 您有哪些其他数据
  • 你在哪里保留你的模特

当然还有另一种方式:您可以在Activity中发送MarkerOptions。如果您保持最新状态,或者onSaveInstanceState没有更改,并且没有更多,那么这可能对您有用。在每次旋转或按下HOME按钮时,我都无法通过IPC发送数千个对象。

答案 1 :(得分:12)

在我看来,在包含地图的片段上调用setRetainInstance(true);会通过暂停,方向更改等保留地图上的所有内容,而不必担心设置和获取。有什么理由说这不是推荐的方法吗?