Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 片段内存泄漏中的MapView_Android_Google Maps_Android Fragments_Memory Leaks - Fatal编程技术网

Android 片段内存泄漏中的MapView

Android 片段内存泄漏中的MapView,android,google-maps,android-fragments,memory-leaks,Android,Google Maps,Android Fragments,Memory Leaks,我已经像这样在片段中添加了贴图 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_l

我已经像这样在片段中添加了贴图

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();
}

}
我从这篇文章中得到了这个想法

它正在工作,但我遇到的问题是内存泄漏。我制作了第二个片段(用
addToBackStack(null)
替换(替换而不是添加)它),只需查看和带有
manager.popbackimmediate()
的按钮,我正在用Canary Leak(没有捕获任何内容)和Android Profiler测试它。每次我转到那个片段并返回地图片段时,内存都会增加大约10MB

为了进行测试,我删除了
MapView
,当返回时,交换片段的内存没有增加,所以我可以说问题出在MapView上

我还尝试将
mapView.onDestroy()
放在
onDestroyView()
(这里也添加了
mapView=null
)中,正如有人在那篇文章的评论中所说的那样,这样做有一定的帮助,并且在交换时内存没有被填满(仍然是,但每次交换时都没有1-5MB那么糟糕)。但问题是,当我交换了20多次碎片后,应用程序崩溃了,我出现了错误

java.lang.NullPointerException:尝试在以下位置获取空数组的长度: DirectByteBuffer.put(DirectByteBuffer.java:385)

所以我去搜索是什么导致了这一点,我找到了关于这一点的两个帖子(将只发布一个)

我在那里尝试了这个解决方案,但没有成功(我仍然得到这个错误)。但正如我看到的,有些人仍在经历这种情况。我也读了其他帖子,但没有找到任何关于我的案例。现在来回答我的问题

  • 我错过了什么?如何在不“膨胀”(保留对MapView的引用)内存的情况下交换片段

  • 我可以在Activity中创建MapView并在这个片段中引用它(这样它就不会每次都重新创建),因为我的应用程序中的所有内容都围绕着它

  • 将map放在一个活动中,其余的片段放在另一个活动中(所有片段都以某种方式与map通信,这就是为什么我在start中这样做的原因)

  • 也许我做错了,也许有更好的办法?(不确定)


  • 交换片段的最佳方法是附加和分离片段

     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()方法,以便使用它清除由于所有标记而创建的位图缓存


    祝你好运

    好吧,我知道问题出在哪里了(我想是的),因为我再也看不到地图上的漏洞了

    我将此添加到onDestroyView的片段中

    @Override
    public void onDestroyView() {
        googleMap.clear()
        mMapView?.onDestroy()
        mMapView = null
        super.onDestroyView()
    }
    

    我在一篇博文中读到,googleMap.clear()和MapView onDestroy()应该在onDestroyView()中,而不是在onDestroy()方法中,因为没有调用该回调函数。这消除了错误,但替换片段时仍然存在内存问题。一旦我在那里添加了mMapView=null,我可以告诉你哪里没有任何泄漏(我会更好地调试它,如果我发现任何新的,我会在这里发布)

    谢谢你的意见。如果有任何查询,将尝试类似此还原的操作。如果在
    onDestroy()
    中有类似的代码,请将其移动到
    onDestroyView()
    。现在,当交换两个地图片段时,内存使用率在一瞬间下降了50%,然后又回到了片段交换之前的值,所以我假设它已经解决了。