Fix UI memory leak on rotate / Merge with master special tests will be needed of this branch

Conflicts:
	OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java
	OsmAnd/src/net/osmand/plus/osmo/OsMoPlugin.java
	OsmAnd/src/net/osmand/plus/render/MapRenderRepositories.java
This commit is contained in:
Victor Shcherb 2015-07-07 14:54:02 +03:00
parent 5e2b0b013d
commit 6d9567fd98
5 changed files with 80 additions and 24 deletions

View file

@ -3,6 +3,7 @@ package net.osmand.plus;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@ -67,22 +68,28 @@ public class OsmandSettings {
}
private abstract class PreferenceWithListener<T> implements OsmandPreference<T> {
private List<StateChangedListener<T>> l = null;
private List<WeakReference<StateChangedListener<T>>> l = null;
@Override
public void addListener(StateChangedListener<T> listener) {
if(l == null) {
l = new LinkedList<StateChangedListener<T>>();
l = new LinkedList<WeakReference<StateChangedListener<T>>>();
}
if(!l.contains(listener)) {
l.add(listener);
if(!l.contains(new WeakReference<StateChangedListener<T>>(listener))) {
l.add(new WeakReference<StateChangedListener<T>>(listener));
}
}
public void fireEvent(T value){
if (l != null) {
for (StateChangedListener<T> t : l) {
t.stateChanged(value);
Iterator<WeakReference<StateChangedListener<T>>> it = l.iterator();
while(it.hasNext()) {
StateChangedListener<T> t = it.next().get();
if(t == null) {
it.remove();
} else {
t.stateChanged(value);
}
}
}
}
@ -90,7 +97,13 @@ public class OsmandSettings {
@Override
public void removeListener(StateChangedListener<T> listener) {
if(l != null) {
l.remove(listener);
Iterator<WeakReference<StateChangedListener<T>>> it = l.iterator();
while(it.hasNext()) {
StateChangedListener<T> t = it.next().get();
if(t == listener) {
it.remove();
}
}
}
}
}

View file

@ -102,7 +102,9 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
if(!mapView.isLayerVisible(distanceCalculatorLayer)) {
activity.getMapView().addLayer(distanceCalculatorLayer, 4.5f);
}
registerWidget(activity);
if(distanceControl == null) {
registerWidget(activity);
}
} else {
MapInfoLayer mapInfoLayer = activity.getMapLayers().getMapInfoLayer();
if(distanceCalculatorLayer != null) {

View file

@ -90,6 +90,10 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
@Override
public void registerLayers(MapActivity activity) {
registerWidget(activity);
}
private void registerWidget(MapActivity activity) {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
monitoringControl = createMonitoringControl(activity);
@ -100,8 +104,17 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
@Override
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
if(monitoringControl == null) {
registerLayers(activity);
if (isActive()) {
if (monitoringControl == null) {
registerWidget(activity);
}
} else {
if (monitoringControl != null) {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
layer.removeSideWidget(monitoringControl);
layer.recreateControls();
monitoringControl = null;
}
}
}

View file

@ -30,6 +30,7 @@ import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import net.osmand.plus.osmo.OsMoService.SessionInfo;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget;
import net.osmand.util.Algorithms;
@ -169,21 +170,49 @@ public class OsMoPlugin extends OsmandPlugin implements OsMoReactor {
super.registerMapContextMenuActions(mapActivity, latitude, longitude, adapter, selectedObj);
}
@Override
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
if(isActive()) {
if(olayer == null) {
registerLayers(activity);
}
if(osmoControl == null) {
registerSideWidget(activity);
}
} else {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
if (layer != null && osmoControl != null) {
layer.removeSideWidget(osmoControl);
osmoControl = null;
layer.recreateControls();
}
if(olayer != null) {
activity.getMapView().removeLayer(olayer);
olayer = null;
}
}
}
@Override
public void registerLayers(MapActivity activity) {
super.registerLayers(activity);
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
osmoControl = createOsMoControl(activity);
layer.registerSideWidget(osmoControl,
R.drawable.ic_osmo_dark, R.string.osmo_control, "osmo_control", false, 18);
layer.recreateControls();
registerSideWidget(activity);
if(olayer != null) {
activity.getMapView().removeLayer(olayer);
}
olayer = new OsMoPositionLayer(activity, this);
activity.getMapView().addLayer(olayer, 5.5f);
}
private void registerSideWidget(MapActivity activity) {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
if (layer != null) {
osmoControl = createOsMoControl(activity);
layer.registerSideWidget(osmoControl, R.drawable.ic_osmo_dark, R.string.osmo_control, "osmo_control",
false, 18);
layer.recreateControls();
}
}
@Override
public void mapActivityPause(MapActivity activity) {

View file

@ -731,24 +731,23 @@ public class MapRenderRepositories {
Bitmap reuse = prevBmp;
this.prevBmp = this.bmp;
this.prevBmpLocation = this.bmpLocation;
if (reuse != null && reuse.getWidth() == currentRenderingContext.width && reuse.getHeight() == currentRenderingContext.height) {
// necessary for transparent, otherwise 2 times smaller
Config cfg = transparent ? Config.ARGB_8888 : Config.RGB_565;
if (reuse != null && reuse.getWidth() == currentRenderingContext.width && reuse.getHeight() == currentRenderingContext.height &&
cfg == reuse.getConfig()) {
bmp = reuse;
bmp.eraseColor(currentRenderingContext.defaultColor);
} else {
if(reuse != null){
log.warn(String.format("Create new image ? %d != %d (w) %d != %d (h) ", currentRenderingContext.width, reuse.getWidth(), currentRenderingContext.height, reuse.getHeight()));
}
if(transparent) {
// necessary
bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, Config.ARGB_8888);
} else {
// better picture ?
bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, Config.ARGB_8888);
bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, cfg);
if(reuse != null) {
reuse.recycle();
}
}
this.bmp = bmp;
this.bmpLocation = tileRect;
if(nativeLib != null) {
renderer.generateNewBitmapNative(currentRenderingContext, nativeLib, cNativeObjects, bmp, renderingReq, notifyList);
} else {