【发布时间】:2021-02-11 15:12:00
【问题描述】:
我的应用程序“传感器记录”中存在内存泄漏问题。它有几个活动,其中一个是地图活动(基于 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, MapView mapView, 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
任何想法,我可以如何追踪和修复内存泄漏?
【问题讨论】:
-
我认为你应该在overlay的destroy中取消runnable并释放资源(特别是线程)。
-
这听起来很合理,但是怎么做呢?你能提供一个代码sn-p吗?我使用 myThread.stop() 和 myThread.destroy() 进行的所有测试都以应用程序崩溃告终。
标签: android out-of-memory overlay android-mapview osmdroid