Android: how to store an Object in consecutive Service calls? - android

I call a Service several times, the Service performs its job and then stop himself.
What I need is to store an abject between consecutive calls of the same Service,
So that:
every time the Service is called it retrieves the object uses
and it saves it again before stopping for using it in the next call.
The object in question is a RemoteViews object.

use can use Singleton Pattern:
public class SingletonClass{
private YourObject objectToStoreBetweenSession;
private SigletonClass instance;
private SingletonClass(){
objectToStoreBetweenSession = new YourObject();
}
private static SingletonClass getInstance(){
if(instance==null)
instance = new SingletonClass();
return instance;
}
public void setObject(YourObject obj){
objectToStoreBetweenSession = obj;
}
public YourObject getObject(){
return objectToStoreBetweenSession;
}
}
Into your Service:
YourObject objectToStoreBetweenSession = SingletonClass.getInstance().getObject();
if(objectToStoreBetweenSession.value==0){
//First time that Service is called.
}else{
//Do whatever you want
SingoletonClass.getInstance().setObject(new YourObject("value"));
}

Related

remove static varialble android service

There is android application which stored data into the sqlite. I keep a list of routes in databases table.I display the data on the active route on the screen/To release the processor, I use static List inside service.To release the processor, I use static List inside service. I change the list when receiving data from the server.
public class NetworkService extends Service{
private static NetworkService instance = null;
private static List<RouteTask> routeTaskList;
private static LoadRoutesTask loadRoutesTask;
private static RouteChangedListener rtListener ;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
if (instance == null) {
instance = this;
NetworkManager.updateNetworkInfo(this);
NetworkManager.setNetworkListener(this);
}
}
public static Context getCurrentContext() {
return instance;
}
public static boolean hasInstance() {
return instance != null;
}
public static void setRouteTaskList(List<RouteTask> rtList)
{
routeTaskList = rtList ;
}
public static List<RouteTask> getRouteTask(){
return routeTaskList;
}
}
In application i can set value
NetworkService.setRouteTaskList(list);
or get value :
List<RouteTask> = NetworkService.getRouteTaskList();
My application usually use routeTaskList instead of sql query for data table.
The task now is change the service, for the android development standards. I removed static field and Now, I run a service through intents (startService(intent)). How Can I remove static settter and getter for routeTaskList object ?
You can provide the Service with the list of tasks as extras in the Intent you use in the startService() call. This replaces your static setter.
To get the list of tasks is more complicated. Options:
You could use AIDL and bind to the Service and then call a method to get the list of tasks
You could call startService() with an Intent that asks the Service to broadcast the list of tasks. In the Service.onStartCommand() you could then send a broadcast Intent which contains the list of tasks as extras.
You could have the Service send a sticky broadcast Intent which contains the list of tasks every time the list changes. Your app would then use registerReceiver() call to read the most recently sent sticky broadcast.

RxJava use dynamic variable with interval

On my RxJava code, I create an Observable with an interval. The code look like this :
public class GetProducts implements RxRequest<Observable<ProductsResult>> {
private LatLng markerLocationToReport;
private static int TIMER = 5;
private static GetProducts INSTANCE = new GetProducts();
public static GetProducts getInstance() {
return INSTANCE;
}
private Observable obs;
private GetProducts() {
}
#Override
public Observable<ProductsResult> getObservable() {
if (obs == null) {
obs = Observable.interval(0, TIMER, TimeUnit.SECONDS, Schedulers.io())
.flatMap((tick) -> Observable.just(GetProductsRequest.getProducts(markerLocationToReport)))
.retry()
.observeOn(AndroidSchedulers.mainThread()).publish();
((ConnectableObservable) obs).connect();
}
return obs;
}
public void setMarkerLocationToReport(LatLng markerLocationToReport) {
this.markerLocationToReport = markerLocationToReport;
}
}
My question is, how can I use the current value of markerLocationToReport in my flatMap function ?
Because in the current code when the request is made by GetProductsRequest.getProducts(markerLocationToReport) always use the initial value of markerLocationToReport when the Observable have been created and I need to update it during my app lifecycle.
Thank's
First of all, I see a couple of races: 1) markerLocationToReport should be volatile so the function of flatMap can observe it properly; 2) unless you call getObservable from a single thread, it may create multiple instances of the timed action.
In addition, you can use convenience .publish().autoConnect(0) which will connect immediately and you don't have to cast to ConnectableObservable.

Using synchronized section in onCreate() in Service

What for do we need to synchronize creating syncadapter in onCreate() in service? As far as I know, there is only one instance of service in system at time. So, there is no change of parallel calls onCreate().
Code from android developers sample:
public class SyncService extends Service {
// Storage for an instance of the sync adapter
private static SyncAdapter sSyncAdapter = null;
// Object to use as a thread-safe lock
private static final Object sSyncAdapterLock = new Object();
public void onCreate() {
/*
* Create the sync adapter as a singleton.
* Set the sync adapter as syncable
* Disallow parallel syncs
*/
synchronized (sSyncAdapterLock) {
if (sSyncAdapter == null) {
sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
}
}
}
...
}

How to hold an Object as long as a service live?

I have an Object that i use in all my activities which holds a lot of complex data in it, it would be quite an hassle to use Android framework of saving the object state and passing it around from activity to activity, so i thought it would be possible to make a Singleton that manages this object and makes it live as long as the application lives.
Tried to use regular Java Singleton scheme, with normal class and normal static instance, but the instance becomes null after a while (which is very confusing, why would an Object that is still referenced be turned to null and garbage collected?). so i decided to flow with Android designers and created a Service to manage this Object, the Service looks something like that :
public class DataService extends Service {
private Data data;
private static DataService instance;
#Override
public void onCreate() {
instance = this;
data= new Data(...);
instance.data.addProgressListener(listener);
(new Thread() {
#Override
public void run() {
data.doInitProgress();
listener = null;
};
}).start();
}
public static void listenToInitDataProcess(final ProgressBar progressBar,final Runnable onDone) {
listener = new ProgressListener() {
private int progress;
private int max;
#Override
public void onUpdateProgress(final long i) {
progressBar.setProgress(progress+=i);
}
#Override
public void onProgressEndComputed(final long n) {
progressBar.setMax(max=(int) n);
}
#Override
public void onDone() {
progressBar.setProgress(max);
onDone.run();
}
};
if (instance!=null) instance.data.addProgressListener(listener);
}
public static Data getData() {
return instance.data;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
now the problem with that is that after a while that the app is on i get NPE caused by instance is null... notice that i was listenning to the data object creation and i was trying to get it only after it was once inited, so no way that instance was suppose to be null...
how to do this right then?
If you want an Object that lives as long as your application lives (i.e. as long as its process is not killed by OS) you can extend android.app.Application, put your 'global' data there and use that subclass as your app context (needs to be declared in manifest)
However many argue that singletons provide essentially the same result as custom context e.g.
Singletons vs. Application Context in Android?
but the instance becomes null after a while
First, understand Effective Java's singleton recommendations, and how something wouldn't become null:
// Singleton with public final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
But a Service is different, since there is no public constructor there. So, first check if the Service is running (as referenced in this post: Check if Service is running from a Broadcast Receiver):
private boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (DataService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Then define some methods in your Service to return your needed state variables.

Using Gson to deserialise Json into a singleton

I'm using Gson to deserialise Json into a model ApplicationModel. I want this Model to be a singleton so I can access it elsewhere in my application.
Now as Gson creates an instance of this class, I'm creating the singleton instance in a rather unconventional way. See below:
public class ApplicationModel {
private static ApplicationModel instance;
private GeneralVO general;
protected ApplicationModel() {
instance = this;
}
public static ApplicationModel getInstance() {
return instance;
}
public String getVersionDate() {
return general.getVersionDate();
}
}
This is the way I create it and then reuse it later in the application:
InputStreamReader reader = new InputStreamReader(is);
ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);
Log.i("MYTAG", "InputStream1 = "+model1.toString());
Log.i("MYTAG", "Date: "+model1.getVersionDate());
ApplicationModel model2 = ApplicationModel.getInstance();
Log.i("MYTAG", "InputStream1 = "+model2.toString());
Log.i("MYTAG", "Date: "+model2.getVersionDate());
This works as the getInstance() returns the same model but somehow this just doesn't seem right.
My question is 'is this a good way of going about it or is there a better solution???'
EDIT
A much better way of doing singletons is to use an enum with one INSTANCE element.
See this post for an explanation
I suggest to instantiate your singleton instance on your Model, rather than instantiating it using constructor.
public class ApplicationModel {
private static ApplicationModel instance; //= new ApplicationModel();
//instantiating here is called an "Eagerly Instantiated"
private GeneralVO general;
private ApplicationModel() {
}
public static ApplicationModel getInstance() {
//instantiating here is called "Lazily Instantiated", using :
//if (instance==null) { --> Check whether 'instance' is instantiated, or null
// instance = new ApplicationModel(); --> Instantiate if null
//}
return instance; //return the single static instance
}
public String getVersionDate() {
return general.getVersionDate();
}
}
By setting the constructor to private, you prevent the object from being re-instantiated by another class, to use the object, you will have to call the object with ApplicationModel.getInstance().
So if you want to set values, call ApplicationModel.getInstance().setterMethod(value), Why this is useful? if you want to track the change, you will only need to track the setter method. If you used constructors, you will have to track the constructors too.
Example :
// To SET the value:
// instead of ApplicationModel model1 = new Gson().fromJson(reader,ApplicationModel.class);
ApplicationModel.getInstance.setValue(new Gson().fromJson(reader,ApplicationModel.class);
// To GET the value :
ApplicationModel.getInstance.getValue();
The "Eager Instantiation" vs "Lazy Instantiation" :
Eager Instantiation is useful if you want an easy way to deal with
Threads
Lazy Instantiation has better memory footprints
There's more than that, you can google it for more info, but I think this should be enough for you right now.
Hope this helps, and good luck ^^
Regards,
Reid

Categories

Resources