Rechercher dans ce blog

mercredi 2 mai 2012

15. Loading the data

In this post, I will describe how to populate the map with marker.

For this purpose, we need to know:

  • the localization: add a grey marker on the map.
  • the content of the plugged yoctopuce device: add a green marker on the map (localization prerequisite)
  • the content of the database: red marker on the map (the plugged yoctodevice is a prerequisite)
As everything is loaded asynchronously with callbacks, we could do the following:

  1. get the localization
  2. In the callback of the location, get the content of the plugged device
  3. In the callback of the plugged device, get the content of the database
However, that would mean the database access is performed relatively late in the startup sequence and would cause a very slow UI. 

The other approach is to load all the elements at the same time, however, depending on the responsiveness of the GPS localization, we may get the result of the yocto device before the localization. As we must know the localization when we get the yoctopuce device, we may end up with complex code that needs to check what has been already found before putting the marker on the map.

In order to simplify the flow, we will use a callback queue that will manage the callbacks priorities. The behavior will be the following:
  1. When a callback is called
  2. Check if the callback is the one with highest priority, if it is not, mark the callback as completed and do not call it
  3. If it is the one with the highest priority: call it
  4. Check the next callback (in term of priority), if is marked as finished, loop on step 3.
This behavior allows us to have the good reordering of callbacks and make sure that we will have the functions called at the beginning but with the callbacks properly ordered.

SequentialCallback

Here is the class which performs the queuing of callback. The order is specified by the sequence of the createCallback function call. For simplicity's sake, the subclasses of GenericManagedCallback are not provided here.
 
33    
34   public class SequentialCallback { 
35    
36       private Logger logger = Logger.getLogger(this.getClass().getName()); 
37       private List<GenericManagedCallback> callbacks; 
38    
39    
40       public SequentialCallback() { 
41           callbacks = new ArrayList<GenericManagedCallback>(); 
42       } 
43    
44       public AsyncCallback createCallback(AsyncCallback entry) { 
45           ManagedCallback callback = new ManagedCallback(entry); 
46    
47           callbacks.add(callback); 
48           return callback; 
49       } 
50    
51       public YoctoCallback createCallback(YoctoCallback yoctoCallback) { 
52           YoctoManagedCallback callback = new YoctoManagedCallback(yoctoCallback); 
53           callbacks.add(callback); 
54           return callback; 
55       } 
56    
57       private synchronized void checkTrigger() { 
58           GenericManagedCallback last = null; 
59           for (GenericManagedCallback callback : callbacks) { 
60               if (callback.isFinished()) { 
61                   callback.trigger(); 
62               } else { 
63                   last = callback; 
64                   break; 
65               } 
66           } 
67    
68           if (last != null) 
69               while (!last.equals(callbacks.get(0))) 
70                   callbacks.remove(0); 
71    
72       } 
73    
74       public Runnable createCallback(Runnable runnable) { 
75           RunnableCallback callback = new RunnableCallback(runnable); 
76           callbacks.add(callback); 
77           return callback; 
78       } 
79    
80    
81       private abstract class GenericManagedCallback { 
82           private Throwable t; 
83           private Object o; 
84           private boolean throwableCaught; 
85           private boolean objectFound; 
86    
87           public GenericManagedCallback() { 
88               throwableCaught = false; 
89               objectFound = false; 
90           } 
91    
92           public void trigger() { 
93               logger.info("Triggering current callback: " + this); 
94    
95               if (objectFound) success(o); 
96               if (throwableCaught) failure(t); 
97           } 
98    
99           protected abstract void success(Object o); 
100   
101          protected abstract void failure(Throwable t); 
102   
103          public boolean isFinished() { 
104              return objectFound || throwableCaught; 
105          } 
106   
107          public void onFailure(Throwable caught) { 
108              throwableCaught = true; 
109              t = caught; 
110              checkTrigger(); 
111          } 
112   
113          public void onSuccess(Object result) { 
114              objectFound = true; 
115              o = result; 
116              checkTrigger(); 
117          } 
118      } 
119   
...
205  } 
206  

Calling the callback

To create the callbacks, it becomes now relatively easy, here is how we get the data in the yoctopuce devices:

 
117          SequentialCallback callback = new SequentialCallback(); 
118   
119   
...
135          //noinspection unchecked 
136          currentHub.refresh(callback.createCallback(new YoctoCallback<Hub>() { 
137              public void onSuccess(Hub hub) { 
138                  logger.info("Hub with serial number: " + hub.getYocto().getSerialNumber() + " has been found"); 
139                  if (latLng != null) { 
140   
141                      hub.getDto().setLatitude(latLng.getLatitude()); 
142                      hub.getDto().setLongitude(latLng.getLongitude()); 
143                      map.removeOverlay(currentMarker); 
144                      currentMarker = MarkerFactory.getInstance().getYoctoMarker(map, hub); 
145                      map.addOverlay(currentMarker); 
146   
147   
148                      //Now let's save the hub in DB 
149                      worldMapService.addHub(hub.getDto(), new AsyncCallback<Void>() { 
150                          public void onFailure(Throwable caught) { 
151                              logger.severe("Impossible to save hub: " + caught); 
152                          } 
153   
154                          public void onSuccess(Void result) { 
155                              logger.fine("Hub successfully saved"); 
156                          } 
157                      }); 
158   
159                      refreshHub(hub); 
160                  } 
161              }


  • at line 135: //noinspection unchecked: is an indication for Intellij Idea to avoid complaining about possible class cast exceptions. 
  • at line 139: we check if the localization has succeeded or not: we know that it has returned but we do not know if it was successful or not.
  • at line 145: we add the marker on the map
  • at line 149, we update the database

This concludes the introduction of the GWT & yoctopuce introduction. The next post will describe how to use Google App Engine to store the data and how to put the project in production.

Aucun commentaire:

Enregistrer un commentaire