我开始使用 Leak Canary,在使用 MapView 旋转片段后,我得到了这个内存泄漏。
10-04 22:01:51.530 17969-18044/cz.united121.android.revizori I/art: hprof: heap dump "/storage/emulated/0/Download/leakcanary/suspected_leak_heapdump.hprof" starting...
10-04 22:02:30.872 17969-20755/cz.united121.android.revizori D/LeakCanary: In cz.united121.android.revizori:1.0:1.
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * cz.united121.android.revizori.activity.MapActivity has leaked:
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * GC ROOT com.google.android.gms.location.internal.f.a
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.android.gms.location.internal.e.h
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.maps.api.android.lib6.d.w.e
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.maps.api.android.lib6.d.ak.b
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.c.p.a
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.c.y.mParent
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references android.widget.FrameLayout.mParent
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * references com.google.android.gms.maps.MapView.mContext
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * leaks cz.united121.android.revizori.activity.MapActivity instance
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * Reference Key: 58a52845-81c4-4562-a45c-c831a92629c3
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * Device: motorola motorola XT1032 falcon_tescogbsl
10-04 22:02:30.880 17969-20755/cz.united121.android.revizori D/LeakCanary: * Android Version: 5.0.2 API: 21 LeakCanary: 1.3.1
这就是我向活动添加片段的方式(我在活动中的 onCreate 中调用它,并在导航菜单中选择项目后)它使用简单的原则,即片段不被破坏但只覆盖地图片段 - 我不必关心保留状态:
public void changeFragment(String toFragment, Bundle args){
Log.d(TAG, "changeFragment");
Util.hideSoftKeyboard(this);
Fragment fragment = null;
String backStateName = toFragment;
Fragment mCurrentFragment = getFragmentManager().findFragmentById(R.id
.fragment_place);
if(mCurrentFragment == null){
fragment = instantiateFragment(toFragment,args);
getFragmentManager().beginTransaction()
.setCustomAnimations(
R.animator.fragment_slide_in, R.animator.fragment_slide_out, 0, 0)
.add(R.id.fragment_place, fragment, backStateName)
.addToBackStack(backStateName)
.commit();
return;
}
if(mCurrentFragment.getClass().getName().equals(toFragment)){
return;
}
boolean fragmentPopped = getFragmentManager().popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && getFragmentManager().findFragmentByTag(backStateName) == null){ //fragment not in back stack, create it.
fragment = instantiateFragment(toFragment,args);
getFragmentManager().beginTransaction()
.setCustomAnimations(
R.animator.fragment_slide_in, R.animator.fragment_slide_out, 0, 0)
.add(R.id.fragment_place, fragment, backStateName)
.addToBackStack(backStateName)
.commit();
}
}
和片段代码
public static final String KEY_POINTS = "points";
private final static String BUNDLE_KEY_MAP_STATE = "mapData";
@Bind(R.id.map)
MapView mMapView;
GoogleMap mMap;
private static int PERIOD_BETWEEN_REPORTING = 10 * 1000; // ms
private static boolean isTimeValid = true;
private static MyCountingThread mThread;
public static TestMapFragment newInstance() {
TestMapFragment fragment = new TestMapFragment();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View mapLayout = inflater.inflate(R.layout.fragment_map, container, false);
ButterKnife.bind(this, mapLayout);
Bundle mapState = null;
if (savedInstanceState != null) {
// Load the map state bundle from the main savedInstanceState
mapState = savedInstanceState.getBundle(BUNDLE_KEY_MAP_STATE);
}
mMapView.onCreate(mapState);
return mapLayout;
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.d(TAG, "onSaveInstanceState");
// Save the map state to it's own bundle
Bundle mapState = new Bundle();
mMapView.onSaveInstanceState(mapState);
// Put the map bundle in the main outState
outState.putBundle(BUNDLE_KEY_MAP_STATE, mapState);
super.onSaveInstanceState(outState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onPause() {
Log.d(TAG, "onPause");
mMapView.onPause();
super.onPause();
//mMap = null;
}
@Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
setUpMapIfNeeded();
mMapView.onResume();
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
}
@Override
public void onStop() {
super.onStop();
if (BuildConfig.DEBUG) {
Log.d(TAG, "onStop");
}
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
mMapView.onDestroy();
mMap = null;
ButterKnife.unbind(this);
super.onDestroy();
}
public void onLowMemory() {
Log.d(TAG, "onLowMemory");
super.onLowMemory();
mMapView.onLowMemory();
}
;
private void setUpMapIfNeeded() {
Log.d(TAG, "setUpMapIfNeeded");
if (mMap == null) {
mMapView.getMapAsync(this);
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady");
mMap = googleMap;
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.setOnMapClickListener(this);
mMap.setOnCameraChangeListener(this);
refreshMap();
CameraPosition lastCameraPosition = TestGetterLocation.getCameraPosition();
if(lastCameraPosition != null){
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(lastCameraPosition.target, lastCameraPosition.zoom));
}
}
@Override
public void onMapClick(LatLng latLng) {
Log.d(TAG, "onMapClick");
//mMap.addMarker(new MarkerOptions().position(latLng));
//TestGetterLocation.addLocationMarker(latLng);
LocationGetter.addReport(new ReportInspector(ParseUser.getCurrentUser(), new ParseGeoPoint(latLng.latitude,latLng.longitude), TypeOfVehicle.BUS.name()));
}
@Override
public void onCameraChange(CameraPosition cameraPosition) {
Log.d(TAG, "onCameraChange");
TestGetterLocation.setCameraPosition(cameraPosition);
}
@OnClick(R.id.reporting_insperctor)
public void OnReportinInspectorClick(View view){
refreshMap();
}
private void refreshMap(){
mMap.clear();
for (ReportInspector report : LocationGetter.getReports()) {
mMap.addMarker(new MarkerOptions()
.position(report.getLocation())
.icon(BitmapDescriptorFactory.fromResource(report
.getTypeOfVehicle()
.getMarkerImageResource())));
}
}
知道为什么会发生内存泄漏吗?