英文:
Android Maps Activity memory issue
问题
我正在制作一个具有Google地图活动的应用程序,并在地图上显示叠加层和标记。这些标记是可点击的,它们会转到另一个显示有关位置信息的活动。在测试时,来回切换地图活动和信息活动,大约在第8次返回地图活动时崩溃。通过在Android Studio的分析器中进一步调查,我注意到每次返回地图活动时,内存使用量都会大幅增加,而不会下降。就像每次重新打开地图活动时,它都会重新加载我在onCreate调用中启动的所有内容,以及之前加载的内容。这很奇怪,因为我在转到信息活动时并没有销毁MapS活动,所以不应该重新加载所有图像和变量。分析器还显示地图活动只是停止而没有被销毁。
我尝试在返回主菜单时使用MapS.super.finish
来看看GC是否会释放内存,但没有效果。
MapS活动:
public class MapS extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastKnownLocation;
private LocationCallback locationCallback;
private final float DEFAULT_ZOOM = 18;
private View mapView;
private Overlay[] floor0;
private Overlay[] floor1;
private int height = 120;
private int width = 90;
private HashMap<String, Bitmap> icons = new HashMap<>();
Circle mapCircle = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.MapS);
assert mapFragment != null;
mapFragment.getMapAsync(this);
mapView = mapFragment.getView();
mFusedLocationProviderClient = getFusedLocationProviderClient(MapS.this);
Places.initialize(MapS.this, "MY API KEY GOES HERE");
// 这里我定义了一些按钮,并创建了我的叠加层对象(它们包含了BitmapDescriptorFactory、坐标和一些整数)
// 当按钮转到除信息活动之外的另一个活动时,我使用MapS.super.finish()来销毁地图活动
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 51) {
if (resultCode == RESULT_OK) {
getDeviceLocation();
}
}
}
@SuppressLint("MissingPermission")
private void getDeviceLocation() {
// 获取设备位置
}
@Override
public void onMapReady(final GoogleMap googleMap) {
googleMap.clear();
// 这是初始化叠加层和标记的部分
// 在开始时显示0楼
// 这里有添加叠加层到地图的代码,允许用户在不同楼层之间切换,并添加标记。还检查用户是否在某个标记的一定范围内,如果是,则可以单击标记并转到其信息活动
}
@Override
public void onDestroy() {
super.onDestroy();
Runtime.getRuntime().gc();
}
}
希望这有助于解决你的问题。如果你需要进一步的帮助,请随时提出。
英文:
I'm making an app with a google maps activity and I display overlays and markers on it. The markers are clickable and they go to another activity with info about the location. From this activity the user goes back to the map activity. When testing this and going back and forth between the map activity and the info activity, around the 8th time going back to the map activity it crashes. Upon further investigation with the profiler in Android Studio I noticed that whenever I go back to the map activity, there is a big increase in memory usage that doesn't go back down. It's like every time you reopen the maps activity it reloads everything that I initiate in the onCreate call on top of what it previously loaded in. Which would be strange as I don't destroy the MapS activity when going to the info activity, so it shouldn't reload all the images and variables. The profiler also says that the Maps activity is just stopped and not destroyed.
I tried using MapS.super.finish when going back to the main menu to see if GC would free up the memory, but it doesn't.
MapS activity;
public class MapS extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastKnownLocation;
private LocationCallback locationCallback;
private final float DEFAULT_ZOOM = 18;
private View mapView;
private Overlay[] floor0;
private Overlay[] floor1;
private int height = 120;
private int width = 90;
private HashMap<String,Bitmap> icons = new HashMap<>();
Circle mapCircle = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.MapS);
assert mapFragment != null;
mapFragment.getMapAsync(this);
mapView = mapFragment.getView();
mFusedLocationProviderClient = getFusedLocationProviderClient(MapS.this);
Places.initialize(MapS.this, ("MY API KEY GOES HERE"));
HERE I DEFINE SOME BUTTONS AND I CREATE MY OVERLAY OBJECTS (THESE CONTAIN A BITMAPDESCRIPTORFACTORY,COORDINATES AND SOME INTEGERS)
WHEN THE BUTTONS GO TO ANOTHER ACTIVITY THAN THE INFO ACTIVITY OF A LOCATION, I DO MapS.super.finish() TO DESTROY THE MAPS ACTIVITY
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 51) {
if (resultCode == RESULT_OK) {
getDeviceLocation();
}
}
}
@SuppressLint("MissingPermission")
private void getDeviceLocation() {
GET DEVICE LOCATION
}
@Override
public void onMapReady(final GoogleMap googleMap) {
googleMap.clear();
//This is the part that initializes the overlays and the markers
//display floor 0 at the start
HERE I HAVE THE CODE THAT ADDS THE OVERLAYS TO THE MAP? LET'S THE USER SWITCH BETWEEN FLOORS AND ADDS THE MARKERS, IT ALSO CHECKS IF THE USER IS INSIDE A CERTAIN RANGE OF A MARKER AND IF SO HE CAN CLICK THE MARKER AND GO TO IT'S INFO ACTIVITY
}
@Override
public void onDestroy() {
super.onDestroy();
Runtime.getRuntime().gc();
}
}
答案1
得分: 0
我认为我解决了最大的问题,因为现在它是可行的,在性能分析器中似乎没有内存问题。从地图活动转到信息活动时,我没有清除地图,所以当用户返回到地图时,它重新加载了所有内容。尽管使用LeakCanary仍然会收到内存泄漏警告:
LeakCanary报告:
┬───
│ GC Root:原生代码中的全局变量
│
├─ com.google.android.gms.internal.location.zzat实例
│ 泄漏:未知
│ ↓ zzat.zzda
│ ~~~~
├─ com.google.android.gms.common.api.internal.ListenerHolder实例
│ 泄漏:未知
│ ↓ ListenerHolder.zajk
│ ~~~~
├─ com.kulak.discoverkoelak.MapS$8实例
│ 泄漏:未知
│ com.google.android.gms.location.LocationCallback的匿名子类
│ ↓ MapS$8.this$0
│ ~~~~~~
╰→ com.kulak.discoverkoelak.MapS实例
泄漏:是的(ObjectWatcher正在监视此对象,因为com.kulak.discoverkoelak.MapS收到了Activity#onDestroy()回调,Activity#mDestroyed为true)
关键 = 7b56a75c-cafa-4963-8d7f-27eb78fb3efc
观看持续时间毫秒 = 5131
保留的持续时间毫秒 = 128
如果有人知道是什么原因引起的,请随时在此问题下回答。
英文:
I think I fixed the biggest issue as it's now workable and in the profiler there doesn't seem to be a big memory issue. hen going from the map activity to the info activity I didn't clear the map, so when the user returned to the map it reloaded everything on top. When using LeakCanary I still get a leak warning though:
Report LeakCanary:
┬───
│ GC Root: Global variable in native code
│
├─ com.google.android.gms.internal.location.zzat instance
│ Leaking: UNKNOWN
│ ↓ zzat.zzda
│ ~~~~
├─ com.google.android.gms.common.api.internal.ListenerHolder instance
│ Leaking: UNKNOWN
│ ↓ ListenerHolder.zajk
│ ~~~~
├─ com.kulak.discoverkoelak.MapS$8 instance
│ Leaking: UNKNOWN
│ Anonymous subclass of com.google.android.gms.location.LocationCallback
│ ↓ MapS$8.this$0
│ ~~~~~~
╰→ com.kulak.discoverkoelak.MapS instance
Leaking: YES (ObjectWatcher was watching this because com.kulak.discoverkoelak.MapS received Activity#onDestroy() callback and Activity#mDestroyed is true)
key = 7b56a75c-cafa-4963-8d7f-27eb78fb3efc
watchDurationMillis = 5131
retainedDurationMillis = 128
If anybody knows what is causing this feel free to answer underneath this question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论