2020import com .google .android .gms .maps .MapView ;
2121import com .google .android .gms .maps .GoogleMap ;
2222import com .codename1 .impl .android .AndroidNativeUtil ;
23+
24+ import java .util .ArrayList ;
2325import java .util .HashMap ;
26+ import java .util .Timer ;
27+ import java .util .TimerTask ;
2428
2529import com .google .android .gms .maps .OnMapReadyCallback ;
2630import com .google .android .gms .maps .model .Marker ;
@@ -77,58 +81,159 @@ public void run() {
7781 android .util .Log .d ("CN1 Mapss" , "Did not initialize maps because activity was null" );
7882 }
7983 AndroidNativeUtil .registerViewRenderer (MapView .class , new AndroidNativeUtil .BitmapViewRenderer () {
80- private boolean rendering ;
81- public Bitmap renderViewOnBitmap (View v , int w , int h ) {
82- if (rendering ) {
84+
85+ public Bitmap renderViewOnBitmap (View v , final int w , final int h ) {
86+
87+ PeerImage pi = PeerImage .getPeerImage (v );
88+ if (pi == null ) {
89+ PeerImage .submitUpdate (v , w , h );
8390 return null ;
8491 }
85- rendering = true ;
86- try {
87- // prevent potential exception during transitions
88- if (w < 10 || h < 10 ) {
89- rendering = false ;
90- return null ;
91- }
92- final MapView mv = (MapView )v ;
93- if (mv .getParent () == null || mv .getHeight () < 10 || mv .getWidth () < 10 ) {
94- return null ;
95- }
96- final Bitmap [] finished = new Bitmap [1 ];
97- AndroidNativeUtil .getActivity ().runOnUiThread (new Runnable () {
98-
99- public void run () {
100- mv .getMap ().snapshot (new GoogleMap .SnapshotReadyCallback () {
101- public void onSnapshotReady (Bitmap snapshot ) {
102-
103- synchronized (finished ) {
104- finished [0 ] = snapshot ;//bmOverlay;
105- finished .notify ();
106- }
107- }
108- });
109- }
92+ if (pi .peerImage == null || pi .peerW != w || pi .peerH != h ) {
93+ PeerImage .submitUpdate (v , w , h );
94+ return null ;
95+ }
96+ pi .lastUsed = System .currentTimeMillis ();
97+ return pi .peerImage ;
11098
111- });
99+ }
100+ });
101+ }
112102
113- com .codename1 .ui .Display .getInstance ().invokeAndBlock (new Runnable () {
114- @ Override
115- public void run () {
116- synchronized (finished ) {
117- while (finished [0 ] == null ) {
118- try {
119- finished .wait (100 );
120- } catch (InterruptedException er ) {}
121- }
122- }
103+ private static class PeerImage {
104+
105+ Bitmap peerImage ;
106+ int peerW ;
107+ int peerH ;
108+ Timer timer ;
109+ long lastUsed ;
110+
111+
112+ PeerImage () {
113+ lastUsed = System .currentTimeMillis ();
114+ }
115+
116+ public static PeerImage getPeerImage (View v ) {
117+ return peerImages .get (v );
118+ }
119+
120+ public void update (View v , final int w , final int h ) {
121+ // prevent potential exception during transitions
122+ if (w < 10 || h < 10 ) {
123+
124+ return ;
125+ }
126+ final MapView mv = (MapView )v ;
127+ if (mv .getParent () == null || mv .getHeight () < 10 || mv .getWidth () < 10 ) {
128+ return ;
129+ }
130+ AndroidNativeUtil .getActivity ().runOnUiThread (new Runnable () {
131+
132+ public void run () {
133+ mv .getMap ().snapshot (new GoogleMap .SnapshotReadyCallback () {
134+ public void onSnapshotReady (Bitmap snapshot ) {
135+ peerImage = snapshot ;
136+ peerW = w ;
137+ peerH = h ;
138+ lastUsed = System .currentTimeMillis ();
123139 }
124140 });
125- return finished [0 ];
126- } finally {
127- rendering = false ;
141+ }
142+
143+ });
144+
145+ }
146+
147+
148+
149+
150+ private static PendingUpdate findPendingUpdate (View v ) {
151+ synchronized (pendingUpdates ) {
152+ for (PendingUpdate u : pendingUpdates ) {
153+ if (u .view == v ) {
154+ return u ;
155+ }
128156 }
129157 }
130- });
158+ return null ;
159+ }
160+
161+ private static void submitUpdate (View v , int w , int h ) {
162+ synchronized (pendingUpdates ) {
163+ PendingUpdate existing = findPendingUpdate (v );
164+ if (existing == null ) {
165+ existing = new PendingUpdate ();
166+ existing .view = v ;
167+ existing .w = w ;
168+ existing .h = h ;
169+ pendingUpdates .add (existing );
170+ existing .schedule ();
171+ }
172+ existing .w = w ;
173+ existing .h = h ;
174+ }
175+
176+ }
177+
178+ private static void clearOldest () {
179+ synchronized (peerImages ) {
180+ int maxNum = 5 ;
181+ long currMark = System .currentTimeMillis ();
182+ ArrayList <PeerImage > toRemove = new ArrayList <PeerImage >();
183+ while (peerImages .size () > 5 ) {
184+ View oldest = null ;
185+ PeerImage oldestImg = null ;
186+ for (View vimg : peerImages .keySet ()) {
187+ PeerImage img = peerImages .get (vimg );
188+ if (oldest == null || img .lastUsed < oldestImg .lastUsed ) {
189+ oldest = vimg ;
190+ oldestImg = img ;
191+ }
192+ }
193+ if (oldest != null ) {
194+ peerImages .remove (oldest );
195+ }
196+
197+ }
198+
199+ }
200+ }
201+
131202 }
203+
204+ static HashMap <View , PeerImage > peerImages = new HashMap <View ,PeerImage >();
205+ private static class PendingUpdate {
206+ private View view ;
207+ private int w ;
208+ private int h ;
209+ long requestTime ;
210+ Timer timer ;
211+
212+
213+
214+ private void schedule () {
215+ timer = new Timer ();
216+ TimerTask tt = new TimerTask () {
217+ @ Override
218+ public void run () {
219+ synchronized (pendingUpdates ) {
220+ pendingUpdates .remove (PendingUpdate .this );
221+ }
222+ PeerImage pe = peerImages .get (view );
223+ if (pe == null ) {
224+ pe = new PeerImage ();
225+ peerImages .put (view , pe );
226+ }
227+ pe .update (view , w , h );
228+
229+ }
230+ };
231+ timer .schedule (tt , 1000L );
232+ }
233+ }
234+ static java .util .ArrayList <PendingUpdate > pendingUpdates = new java .util .ArrayList <PendingUpdate >();
235+
236+
132237 private static boolean initialized = false ;
133238 private static void initMaps () {
134239 if (!initialized ) {
@@ -172,8 +277,10 @@ public void run() {
172277 listeners .put (m , key );
173278 }
174279 markerLookup .put (key , m );
280+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
175281 }
176282 });
283+
177284 return key ;
178285 }
179286
@@ -186,6 +293,7 @@ public void setPosition(final double lat, final double lon) {
186293 AndroidNativeUtil .getActivity ().runOnUiThread (new Runnable () {
187294 public void run () {
188295 mapInstance .moveCamera (CameraUpdateFactory .newLatLng (new LatLng (lat , lon )));
296+ PeerImage .submitUpdate (view , view .getWidth (), view .getHeight ());
189297 }
190298 });
191299 }
@@ -195,6 +303,7 @@ public float getZoom() {
195303 AndroidImplementation .runOnUiThreadAndBlock (new Runnable () {
196304 public void run () {
197305 result [0 ] = mapInstance .getCameraPosition ().zoom ;
306+
198307 }
199308 });
200309 return result [0 ];
@@ -204,6 +313,7 @@ public void setZoom(final double lat, final double lon, final float zoom) {
204313 AndroidNativeUtil .getActivity ().runOnUiThread (new Runnable () {
205314 public void run () {
206315 mapInstance .moveCamera (CameraUpdateFactory .newLatLngZoom (new LatLng (lat , lon ), zoom ));
316+ PeerImage .submitUpdate (view , view .getWidth (), view .getHeight ());
207317 }
208318 });
209319 }
@@ -218,6 +328,8 @@ public void run() {
218328 mapInstance .clear ();
219329 markerLookup .clear ();
220330 listeners .clear ();
331+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
332+
221333 }
222334 });
223335 }
@@ -248,6 +360,7 @@ public void run() {
248360 p .remove ();
249361 paths .remove (param );
250362 }
363+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
251364 }
252365 });
253366 }
@@ -284,6 +397,7 @@ public void run() {
284397 return ;
285398 }
286399 mapInstance .setMapType (GoogleMap .MAP_TYPE_NORMAL );
400+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
287401 }
288402 });
289403 }
@@ -304,6 +418,7 @@ public void setShowMyLocation(boolean show) {
304418 @ Override
305419 public void run () {
306420 mapInstance .setMyLocationEnabled (showMyLocation );
421+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
307422 }
308423 });
309424 }
@@ -337,6 +452,7 @@ public boolean onMarkerClick(Marker marker) {
337452 mapInstance .setOnCameraChangeListener (new GoogleMap .OnCameraChangeListener () {
338453 public void onCameraChange (CameraPosition position ) {
339454 MapContainer .fireMapChangeEvent (InternalNativeMapsImpl .this .mapId , (int ) position .zoom , position .target .latitude , position .target .longitude );
455+ PeerImage .submitUpdate (view , view .getWidth (), view .getHeight ());
340456 }
341457 });
342458 mapInstance .setOnMapClickListener (new GoogleMap .OnMapClickListener () {
@@ -382,6 +498,7 @@ public void run() {
382498 view = null ;
383499 return ;
384500 }
501+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
385502 }
386503 });
387504 return view ;
@@ -415,6 +532,7 @@ public void setRotateGestureEnabled(boolean e) {
415532 @ Override
416533 public void run () {
417534 mapInstance .getUiSettings ().setRotateGesturesEnabled (rotateGestureEnabled );
535+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
418536 }
419537 });
420538 }
@@ -427,6 +545,7 @@ public long finishPath(long param) {
427545 @ Override
428546 public void run () {
429547 paths .put (key , mapInstance .addPolyline (currentPath ));
548+ //PeerImage.submitUpdate(view, view.getWidth(), view.getHeight());
430549 }
431550 });
432551 return key ;
@@ -499,6 +618,7 @@ public void onPause() {
499618 try {
500619 if (view != null ) {
501620 view .onPause ();
621+
502622 }
503623 } catch (Exception ex ) {
504624 ex .printStackTrace ();
@@ -533,6 +653,24 @@ public void onLowMemory() {
533653 try {
534654 if (view != null ) {
535655 view .onLowMemory ();
656+ synchronized (pendingUpdates ) {
657+ PendingUpdate toRemove = null ;
658+ for (PendingUpdate u : pendingUpdates ) {
659+ if (u .view == view ) {
660+ if (u .timer != null ) {
661+ u .timer .cancel ();
662+ u .timer = null ;
663+ }
664+ toRemove = u ;
665+ }
666+ }
667+ if (toRemove != null ) {
668+ pendingUpdates .remove (toRemove );
669+ }
670+
671+
672+ }
673+ peerImages .clear ();
536674 }
537675 } catch (Exception e ) {
538676 e .printStackTrace ();
@@ -541,6 +679,23 @@ public void onLowMemory() {
541679
542680 public void deinitialize () {
543681 AndroidNativeUtil .removeLifecycleListener (this );
682+ synchronized (pendingUpdates ) {
683+ PendingUpdate toRemove = null ;
684+ for (PendingUpdate u : pendingUpdates ) {
685+ if (u .view == view ) {
686+ if (u .timer != null ) {
687+ u .timer .cancel ();
688+ u .timer = null ;
689+ }
690+ toRemove = u ;
691+ }
692+ }
693+ if (toRemove != null ) {
694+ pendingUpdates .remove (toRemove );
695+ }
696+
697+ }
698+ PeerImage .clearOldest ();
544699 }
545700
546701 public void initialize () {
0 commit comments