我已经像这样添加了Map to Fragment
public class SomeFragment extends Fragment {
MapView mapView;
GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.some_layout, container, false);
// Gets the MapView from the XML layout and creates it
mapView = (MapView) v.findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
// Gets to GoogleMap from the MapView and does initialization stuff
map = mapView.getMap();
map.getUiSettings().setMyLocationButtonEnabled(false);
map.setMyLocationEnabled(true);
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
try {
MapsInitializer.initialize(this.getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
// Updates the location and zoom of the MapView
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
map.animateCamera(cameraUpdate);
return v;
}
@Override
public void onResume() {
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
我从这篇文章中得到了这个想法
https://stackoverflow.com/a/26174573/1393695
它正在工作,但我遇到的问题是内存泄漏。我已经制作了第二个片段(用addToBackStack(null)
取代(替换不添加))只有视图和一个带manager.popBackStackImmediate()
的按钮,我正在用Canary Leak测试它(没有捕获任何东西)和Android Profiler 。每次我去那个片段并返回地图片段内存上升大约10MB。
为了测试我移除了MapView
并且交换片段在返回时没有增加内存,所以我可以说问题出在MapView上。
我还尝试将mapView.onDestroy()
放入onDestroyView()
(此处也添加了mapView = null
),就像有人在该帖子的评论中所说的那样,这确实有所帮助,而且记忆力没有得到满足交换(它仍然是,但它每次我交换时它不是1 - 5 MB)。但问题是当我交换碎片20次以上应用程序崩溃并且我收到错误
java.lang.NullPointerException:尝试获取null数组的长度 java.nio.DirectByteBuffer.put(DirectByteBuffer.java:385)
所以我去搜索造成这种情况的原因,我发现了几个关于此的帖子(只会发布一个)
我在那里尝试了解决方案但它没有工作(我仍然得到这个错误)。但正如我所看到的,有些人仍在经历这一点。我也读过其他帖子,但没有找到我的案例。现在我的问题。
我在这里缺少什么?我应该如何在没有“膨胀”(保持对MapView的引用)内存的情况下交换片段。
我可以在Activity中创建MapView并在此Fragment中引用它(这样它不会每次都重新创建),因为我的应用程序中的所有内容都围绕着它
将地图放在一个活动中,将其余部分的碎片放在其他活动中(所有碎片都以某种方式与地图进行通信,这就是为什么我这样做的原因)
也许我做错了,可能有更好的方法吗? (不确定)
答案 0 :(得分:6)
好的,我想出了问题是什么(我想我做了)因为我不再在地图上看到泄漏了。
我将此添加到片段onDestroyView
@Override
public void onDestroyView() {
googleMap.clear()
mMapView?.onDestroy()
mMapView = null
super.onDestroyView()
}
我在帖子中读到googleMap.clear()和MapView onDestroy()应该在onDestroyView()而不是在onDestroy()方法中。摆脱了错误,但替换片段的内存问题仍然存在。一旦我添加mMapView = null从我可以告诉哪里没有任何泄漏(我仍然会更好地调试这个,如果我发现任何新的,我将在这里发布)。
答案 1 :(得分:1)
交换片段的最佳方法是附加分离
public void replaceFragment(Fragment fragment)
{
fm = FragmentManager;
ft = fm.BeginTransaction();
if (fragment == MapsFragment)
{
if (MapsFragment == null)
{
MapsFragment = new PoSLocationMapView(this);
ft.Add(Resource.Id.frame_container, MapsFragment, "MapsFragment");
}
else
{
ft.Detach(FragmentManager.FindFragmentByTag("ListFragment"));
ft.Attach(MapsFragment);
}
}
else if (fragment == ListFragment)
{
if (ListFragment == null)
{
ListFragment = new ServicePointDHLList(this);
ft.Add(Resource.Id.frame_container, ListFragment, "ListFragment");
}
else
{
ft.Detach(FragmentManager.FindFragmentByTag("MapsFragment"));
ft.Attach(ListFragment);
}
}
ft.SetTransition(FragmentTransit.FragmentOpen);
ft.Commit();
}
private void setCurrentTabFragment(int tabPosition)
{
switch (tabPosition)
{
case 0:
replaceFragment(MapsFragment);
break;
case 1:
replaceFragment(ListFragment);
break;
}
}
这是我最近在Xamarin android中做到的 这段代码在一个活动里面,我需要两个标签,所以我用setCurrentTabFragment()在两者之间交换 您可以轻松地将其转换为Java Android。
以及内存泄漏问题 在onLowMemory()中使用java系统垃圾收集器同样在你的片段的onDestroy()中使用GoogleMapsObject.Clear()清除你的googlemaps对象但是要确保你调用这个clear()方法,你不需要不再映射因此,所有标记创建的位图缓存也会被它清除
好运!