Milestone 4: Scheduled threads, EventBus, Singletons, and Activities (60/200 points)
In this milestone, your app will show the simulation as it animates. To start the animation, someone will need to issue a POST request to the server (at the same address you have been using up until now). Subsequent requests to the server should still be GET requests.
[8 pts] Using ScheduledThreadPoolExecutor. Create a class called Poller that is responsible for sending a query to the server to GET a new grid every 500 milliseconds. The Poller class must use a ScheduledThreadPoolExecutor to cause requests to be sent to the server at a fixed rate of once every half-second. See https://codelatte.wordpress.com/2013/11/13/49/ (Links to an external site.) for a great tutorial on how to do use a ScheduledThreadPoolExecutor in this way.
[8 pts] Using EventBus (akin to the Observer pattern). Use a greenrobot EventBus to make your Poller post events and to make something (or things) in your Grid subsystem subscribe to them (in a communication pattern similar to the Observer pattern). Note that whenever the Poller gets new data from the server, it should update both the grid and the textual description of the currently selected cell.
See http://www.andreas-schrade.de/2015/11/28/android-how-to-use-the-greenrobot-eventbus/ (Links to an external site.) and
https://github.com/greenrobot/EventBus (Links to an external site.) to get started (the first is a great intro, but is a bit outdated, while the second is completely up-to-date). It may help to refer to the following page again to remind you about life-cycle concerns:
https://developer.android.com/reference/android/app/Activity.html (Links to an external site.)
[8 pts] Making the Poller a Singleton. Put in a log message that says "Response Received" at the place you get a server response using log.d. You should see that every time you rotate your app, the number of server responses per second increases. This is because you are creating a new Poller instance each time, and the old Poller instances aren't getting garbage collected. Deal with this problem by making the Poller into a singleton using the Singleton pattern discussed in class. We must be able to see the "Response Received" messages behaving appropriately during screen rotations for you to get full credit for this part.
[10 pts] Showing location history for Gardener items. Maintain a history (linked list?) inside each GardenerItem of when it moved to a new location (including the very first location), using java.sql.Timestamp with System.currentTimeMillis() to record the time. This list should output to Log.d() whenever the left-hand button is clicked on the main Activity (instead of showing a Toast). This is not as easy as it may at first sound, because currently the GardenerItems change every time the Poller polls. In order for this to work, you will have to make sure to get the same GardenerItem (based on its ID) each time. This means...
1) The GridCellFactory must maintain a collection (HashMap?) of GardenerItems and return an existing instance rather than create a new one, if an instance already exists. It is not necessary to parse the ID out completely, but you do need to mask away the XXX digits somehow.
2)If a GardenerItem instance already exists, there must be some way for the GridCellFactory to tell it what the GardenerItem's new location is.
3) The GridCellFactory must be made into a Singleton so that this new collection doesn't get destroyed and recreated whenever the device is rotated.
4)There needs to be some new method added to the SimGridFacade that allows the button to invoke the log-writing behavior (perhaps something like, showDetailsForSelected).
5)It is advisable to just have the GardenerItem's getCellInfo include the history list at the end of its input (see the image below for an example).
[6 pts] Unit Tests for history of GardenerItems. Create a set of JUnit tests to ensure that the history of GardenerItems is being properly updated. Your tests should generate movement of GardenerItems by creating appropriate messages and deliver them as if they came over the EventBus (you may send them over the EventBus, or through another method that interprets the object that gets sent over the EventBus). You should not be involving the server in any way for your tests, but your tests should instead simulate data that might have come from the server. The data should be deterministic, so that your tests will be consistent.
[2 pts] Pause/resume update of GridView. Cause the right-hand button to pause and resume updating of the GridView. Note that the Poller should continue requesting data, and the history of GardenerItems should continue to accrue in the background. When updates to the GridView are resumed, it should show the most recent grid (it doesn't need to play everything that happened since it was paused).
[8 pts] Display history in a new Activity. Design and build the layout for another Activity that displays all details of the currently selected grid cell (including location history for GardernItems). This Activity should be shown whenever the user clicks the left-hand button on the main Activity (instead of putting it to the log). It should be possible to see all history regardless of the amount of history that has been accumulated, meaning it will likely need some way of scrolling. It should be possible to return from this Activity back to the mainActivity (using the built-in back-button would be fine). It is not necessary for the display of the history to continue to update as long as it is completely up-to-date each time the activity is displayed.
Milestone3_snapshot.jpg (4-1.png is attched below)
[10 pts] The app has all working functionality (from Milestone 3) without crashing or freezing during the run.
[+3 pts] You can get additional points for causing the history display to continue updating without leaving and coming back to it. For full credit, the display must update without changing the viewing location. If the viewing location is already at the end, it is good for it to always show the most-recent line (causing the rest to scroll off the top), but it would also be fine for the list to stay put in this case as well.