Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Long running service in background #21

Open
afwang opened this issue Sep 2, 2015 · 8 comments
Open

Long running service in background #21

afwang opened this issue Sep 2, 2015 · 8 comments

Comments

@afwang
Copy link
Owner

afwang commented Sep 2, 2015

This application does not need a long-running service in the background. This issue is open until the long-running service is no longer long-running so that the app plays nicer with other apps on each device.

@afwang
Copy link
Owner Author

afwang commented Sep 3, 2015

This requires some changes to the current design of the app. I believe my original reasoning for having a service act as the software agent component with Ogame's servers was so that data loading can occur in the background if the user taps the home button on the device. When the user returns to the app, the data will be already be loaded and processed, and the client of the service can immediately begin displaying the data to the user without having to wait for a network load. I did not want the service to be long running because if the Android system needs memory, then I do not want to make the overall Android experience worse by increasing the priority of the app.

Although this seems like a problem more suited for Loaders, I also want the service to run while the app is in the foreground for users that do a lot of switching between various different universes (playing multiple accounts). If they do a network request for one account, they are able to switch to a separate account in the mean time so the network request for the first account continues.

Perhaps it makes more sense to redesign the app in the following fashion:

  1. Use an OgameAgent manager class to maintain references to various OgameAgent objects representing the state of an account (logged in status, which page is being viewed, latest loaded data).
  2. When an action is made for a certain OgameAgent (e.g. load resource page), an Intent will be fired off to an IntentService, which does the network loading and data parsing in the background. When complete, the IntentService will then update the corresponding OgameAgent object.
  3. There needs to be a way to inform activities and fragments of newly updated OgameAgent objects. One way is to have the OgameAgent class allow callbacks to be registered, and the IntentService will use these callbacks to notify the activities and fragments (pros: pretty straightforward. cons: have to carefully manage registration and unregistration to OgameAgent objects for activities and fragments). A less hack-y and shoddy way would be to use the EventBus library to send some OgameAgentUpdated event objects (pros: EventBus seems pretty well-established and easy to use. Registration and unregistration seems a bit easier as well. cons: activities and fragments listening for a particular OgameAgent object's updates might receive updates for other OgameAgent objects).

In any case for item 3, these 3 points solve my requirements for the app. Point 1 will allow OgameAgent objects to remain in memory when the app goes to the background. Point 2 allows the service to run in the background if the app gets dismissed, and it will update the OgameAgent object as needed.

@codlab
Copy link
Contributor

codlab commented Sep 9, 2015

The 3. can be easily achieved with the following pattern :

  • OgameAgent created EventBus' Bus
  • fragment/item can register/unregister to the appropriate OgameAgent's Bus

A workaround can be done easily with the following signature :

  • events store a reference to the OgameAgent sender
  • the receiving item check the sender
    (the first solution is the best I presume ;) )

Warning, using IntentService is not efficient in order to store the Manager information. Those services are only meant to perform actions and can be "cleaned" without any notice (for instance, when the Intent queue is empty, there are meant to be closed soon after the detection). A typical Service can stay in memory quite longer (until the system consider that due to RAM usage, sleep inactivity etc... it must be killed)

The final persistent usage is the startForeground() (with a notification)

@codlab
Copy link
Contributor

codlab commented Sep 9, 2015

An other way to keep the Agents event easy to maintaing :

  • the Manager keep an "active" agent in memory
  • and the list of the "inactive" one
  • when switching, an event is sent to make the UI refresh all the information
  • when an agent is inactive, it is considered valid the fact it will not send any event (prevent it?)
  • an active agent which is currently having a network request pending will not fire the response event when it goes to "inactive" but store (as it would have done) the result -- it will be refreshed in UI when it will be put active

@afwang
Copy link
Owner Author

afwang commented Sep 14, 2015

I have a local branch I have been working on for the past week. I went with using EventBus to inform activities and fragments of updated OgameAgent objects.

I'm using an IntentService to run the action of making network requests and updates, but I'm taking the responsibility of managing the OgameAgent objects out into a separate class (essentially, references to the OgameAgent objects is maintained through a static variable referencing a data structure - in my case, a LongSparseArray). This design means that if the system needs to reclaim system resources by killing the process, then the OgameAgent manager and the OgameAgent objects it managers will be cleared as intended. If the process is not killed when a user returns, then the OgameAgent manager and its objects are already sitting in memory ready to go. This is also intended.

I like the idea of having multiple EventBuses - 1 for each OgameAgent. I will update my work with that suggestion before opening a PR. Thanks!

@codlab
Copy link
Contributor

codlab commented Sep 17, 2015

Instead of using a static reference, you should use the Application instance of the app to store it.

The Application is the first and latest object of the "app". Hence, logically, it is good to store the reference in it (not a static one but a direct field)

@afwang
Copy link
Owner Author

afwang commented Sep 17, 2015

Please explain what you mean by saying the Application object is the latest object of the app.

afwang added a commit that referenced this issue Sep 17, 2015
afwang added a commit that referenced this issue Sep 17, 2015
…g with the new

message-passing design outlined in #21.
This redesign is to remove the long-running service from the background.
@codlab
Copy link
Contributor

codlab commented Sep 18, 2015

I meant in the allocation lifecycle. The Application instance is loaded and then, the different entry points defined in the manifest: activity, receivers etc...

Note that when the app is compltely killed, the onTerminte() function can not be called (but everything is released)

so keeping a non-static OgameAgents reference in the ApplicationController defined in the code make sense

@afwang
Copy link
Owner Author

afwang commented Sep 24, 2015

I still don't see the advantage, nor a disadvantage of having the reference sit within an Application object vs. having the reference be static within the manager's own class. It seems to me to be purely a code aesthetic preference, but I'll define a reference to the manager in the Application class before opening the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants