问题描述
我的应用程序“Sensor Recording”出现内存泄漏问题。它有几个活动,其中一个是地图活动(基于 osmdroid 6.1.8),我在其中显示背景 MAPNIK 和一些 GroundOverlay s 包含天气图。
当我在活动之间切换时——或者当我将设备从纵向旋转到横向再向后旋转时——每次重建地图时,内存消耗都会增加。迟早(取决于设备内存)我会收到 OutOfMemoryError。
对于一些更详细的信息,这里是 Java 源代码的摘录,清除了它周围的所有垃圾。 地图活动:
@Override
public void onCreate (Bundle savedInstanceState)
{
.
.
.
// basic map
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setTileSource(TileSourceFactory.MAPNIK);
// overlays
mapView.getoverlays().clear();
WeatherOverlay weatherOverlay = new WeatherOverlay(this,mapView,wdStack);
mapView.getoverlays().add(0,weatherOverlay);
.
.
.
} // onCreate
和类 WeatherOverlay:
public class WeatherOverlay extends Overlay implements Runnable
{
private GroundOverlay[] groundOverlay;
private ConnectivityManager connectivityManager;
private Context context;
private MapView mapView;
private WeatherStack wdStack;
// constructor
public WeatherOverlay(Context context,MapView mapView,WeatherStack wdStack)
{
super();
this.context = context;
this.mapView = mapView;
this.wdStack = wdStack;
groundOverlay = new GroundOverlay[wdStack.getSize()];
for (int index = 0; index < wdStack.getSize(); index++)
{
groundOverlay[index] = new GroundOverlay();
groundOverlay[index].setPosition(
wdStack.getEntry(index).northWest,wdStack.getEntry(index).southEast);
mapView.getoverlays().add(0,groundOverlay[index]);
}
connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
} // constructor
@Override
public void draw(Canvas canvas,boolean shadow)
{
if (shadow) return;
new Thread(this).start();
} // draw
@Override
public void run()
{
final NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
final boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (!isConnected)
{
return;
}
// get URL
InputStream inputStream = null;
HttpsURLConnection connection;
String UrlString = "";
// try to get input stream
try
{
for (int index = 0; index < wdStack.getSize(); index++)
{
if ((wdStack.getEntry(index).URL != null) &&
(wdStack.getEntry(index).onOff))
{
UrlString = wdStack.getEntry(index).URL; // e.g. "https://en.sat24.com/image?type=km®ion=de" for "Germany"
URL url = new URL(UrlString);
connection = (HttpsURLConnection) url.openConnection();
inputStream = connection.getInputStream(); // possible OutOfMemoryError
// read the image
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
inputStream = null;
// and put it into ground overlay
if ((bitmap != null) && (groundOverlay[index] != null))
{
groundOverlay[index].setimage(bitmap);
wdStack.getEntry(index).downloaded = true;
}
// show on the map
mapView.postInvalidateDelayed(100);
} // if onOff
} // for index
}
catch (Throwable e)
{
}
} // run
} // class
任何想法,我如何追踪并修复内存泄漏?
解决方法
onDraw(...)
是一个重要的方法,必须高效。例如,我们不应该定义任何新变量。因为每当您的视图/叠加层有任何更改时,它都会调用以在屏幕上绘制最新信息。
因此您应该使用承包商来初始化变量,即您的线程。
那么您应该在 Overlay 类中覆盖 onDetach(MapView)。因为基于 OsmDroid 文档,您应该释放此方法中的所有资源。 (在您的情况下,停止并杀死线程并清除其他大量资源)
public void onDetach(MapView mapView)
覆盖以在关闭前执行资源清理。默认情况下 什么都不做。
,避免内存泄漏的解决方案是活动中的以下代码:
@Override
protected void onStop ()
{
mapView.onDetach();
super.onStop();
} // onStop
感谢您的帮助。