feat(step097): preserve B fixes for unified V15 source
This commit is contained in:
@@ -729,12 +729,8 @@ jni::jboolean NativeMapView::setContinuousLayerRange(JNIEnv& env,
|
||||
}
|
||||
|
||||
jni::jboolean NativeMapView::setRenderSegmentPlan(JNIEnv& env, const jni::String& planJson) {
|
||||
const auto plan = parseRenderSegmentPlanJSON(jni::Make<std::string>(env, planJson));
|
||||
if (plan) return map->setRenderSegmentPlan(*plan);
|
||||
RenderSegmentPlan invalid;
|
||||
invalid.schemaVersion = 0;
|
||||
map->setRenderSegmentPlan(std::move(invalid));
|
||||
return false;
|
||||
auto plan = renderSegmentPlanFromJSONOrInvalid(jni::Make<std::string>(env, planJson));
|
||||
return map->setRenderSegmentPlan(std::move(plan));
|
||||
}
|
||||
|
||||
jni::Local<jni::String> NativeMapView::getRenderSegmentDiagnostics(JNIEnv& env) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RestrictTo;
|
||||
import androidx.annotation.Size;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
@@ -43,6 +44,7 @@ import org.maplibre.android.log.Logger;
|
||||
import org.maplibre.android.offline.OfflineRegionDefinition;
|
||||
import org.maplibre.android.style.expressions.Expression;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -68,6 +70,7 @@ public final class MapLibreMap {
|
||||
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
|
||||
private final List<Style.OnStyleLoaded> awaitingStyleGetters = new ArrayList<>();
|
||||
private final List<OnDeveloperAnimationListener> developerAnimationStartedListeners;
|
||||
private final List<OnDestroyListener> onDestroyListeners = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Style.OnStyleLoaded styleLoadedCallback;
|
||||
@@ -91,6 +94,19 @@ public final class MapLibreMap {
|
||||
|
||||
private boolean debugActive;
|
||||
private boolean started;
|
||||
private boolean destroyed;
|
||||
|
||||
/** Internal map-lifetime observer used by map-owned integrations. */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
public interface OnDestroyListener {
|
||||
void onDestroy();
|
||||
}
|
||||
|
||||
/** Removable registration for an internal observer of this concrete map's destruction. */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
public interface OnDestroyListenerRegistration {
|
||||
void remove();
|
||||
}
|
||||
|
||||
MapLibreMap(NativeMap map, Transform transform, UiSettings ui, Projection projection,
|
||||
OnGesturesManagerInteractionListener listener, CameraChangeDispatcher cameraChangeDispatcher,
|
||||
@@ -254,6 +270,24 @@ public final class MapLibreMap {
|
||||
}
|
||||
}
|
||||
|
||||
/** Registers a removable observer for destruction of this concrete map instance. */
|
||||
@NonNull
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
public OnDestroyListenerRegistration addOnDestroyListener(@NonNull OnDestroyListener listener) {
|
||||
if (destroyed) {
|
||||
listener.onDestroy();
|
||||
return () -> { };
|
||||
}
|
||||
onDestroyListeners.add(listener);
|
||||
WeakReference<MapLibreMap> mapReference = new WeakReference<>(this);
|
||||
return () -> {
|
||||
MapLibreMap map = mapReference.get();
|
||||
if (map != null) {
|
||||
map.onDestroyListeners.remove(listener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the hosting Activity/Fragment onStart() method is called.
|
||||
*/
|
||||
@@ -304,6 +338,16 @@ public final class MapLibreMap {
|
||||
* Called when the hosting Activity/Fragment onDestroy()/onDestroyView() method is called.
|
||||
*/
|
||||
void onDestroy() {
|
||||
if (destroyed) {
|
||||
return;
|
||||
}
|
||||
destroyed = true;
|
||||
List<OnDestroyListener> listeners = new ArrayList<>(onDestroyListeners);
|
||||
onDestroyListeners.clear();
|
||||
for (OnDestroyListener listener : listeners) {
|
||||
listener.onDestroy();
|
||||
}
|
||||
disposeWeatherRuntime();
|
||||
locationComponent.onDestroy();
|
||||
if (style != null) {
|
||||
style.clear();
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.maplibre.android.maps;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/** Exercises the concrete MapLibreMap.onDestroy() dispatch path used by Android integrations. */
|
||||
public class MapLibreMapDestroyListenerTest {
|
||||
private MapLibreMap newMap() {
|
||||
MapLibreMap map = new MapLibreMap(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Mockito.mock(CameraChangeDispatcher.class),
|
||||
Collections.emptyList());
|
||||
map.injectLocationComponent(Mockito.mock(org.maplibre.android.location.LocationComponent.class));
|
||||
return map;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroyNotifiesRegisteredListenerOnceAndLateRegistrationImmediately() {
|
||||
MapLibreMap map = newMap();
|
||||
AtomicInteger notifications = new AtomicInteger();
|
||||
map.addOnDestroyListener(notifications::incrementAndGet);
|
||||
|
||||
map.onDestroy();
|
||||
map.onDestroy();
|
||||
|
||||
assertEquals(1, notifications.get());
|
||||
map.addOnDestroyListener(notifications::incrementAndGet);
|
||||
assertEquals(2, notifications.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removedListenerIsNotCalledByOnDestroy() {
|
||||
MapLibreMap map = newMap();
|
||||
AtomicInteger notifications = new AtomicInteger();
|
||||
MapLibreMap.OnDestroyListenerRegistration registration =
|
||||
map.addOnDestroyListener(notifications::incrementAndGet);
|
||||
registration.remove();
|
||||
|
||||
map.onDestroy();
|
||||
|
||||
assertEquals(0, notifications.get());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user