I want to schedule some code to be executed in future. What I want to be done in future is that the future process should call a webservice and do something, after that it should call the local database that I have (SQLite) and do some update on it.
I was going to use Handler for this purpose. Wherein I'll pass the Runnable object to it, and inside runnable I'll call AsyncTask to call the webservice, and on the onPostExecute I'll call my local db and do the update.
But the problem is that when I call the db, it is going to require a context to open itself. Now I looked up if I can pass null to it, but then it says that it will create an inmemory database, instead of giving my database that I've created already.
Now, I can pass the context info from the place where I am creating the runnable instance, but what exactly happens if I keep my 'context' object alive. That context is not going to be used anywhere but in the database.
What will be the best way to work this through?
Thanks
Use an IntentService, perform a blocking request so that the service is not killed and then the write to the database both in onHandleIntent.
I think this should work If you use the handler method that you are speaking of. I don't think you will have any issues (other than stopping your garbage collector from collecting the context) if you retain a reference to the context. To be safe though, I would use the application context to create and retrieve the db, as that context doesn't get garbage collected until the android OS kills your app process, which occurs sometime after a user closes the app.
Related
I have old Android/java code, that contains two derives from IntentService,
and these services not run in separate processes.
The question is about the way to return result from these IntentService.
One service return result by using Handler + Runnable, to run code in main loop:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
MyApplication.get().setFoo(someThing);
}
});
the other one is uses LocalBroadcastManager.getInstance(this).sendBroadcast(in); to send message to Activity, and Activity subscribe via BroadcastReceiver on message in onResume, and unsubscribe in onPause.
Am I right, and in both case it is possible to use LiveData to simplify things?
IntentService should create LiveData and who want result should observe it,
and when new data arrives IntentService should call postValue,
or may be there are some reefs to prevent usage of LiveData here?
I think that LiveData will not help you in sending any data from Service to other components.
The problem with communication from any Service to other components is that you don't usually obtain a direct reference to the Service, therefore you can't directly "subscribe" to notifications.
Theoretically, if the Service runs in the same process, you can bind it, obtain a reference to Service object and then directly perform subscription. However, this is often an overkill and I don't see this pattern being used widely.
In your examples, there are two communication mechanisms:
Service reaches statically to Application object and sets some data. This is a communication through global state, and is generally considered an anti-pattern.
Communication through LocalBroadcastManager
From the above two mechanisms, I would use only #2 and avoid #1 at all costs.
Back to LiveData.
In order to be able to get LiveData object from the Service you will need to have a reference to that Service. This is usually impossible unless you bind Service in the same process, or use some ugly hack that involves global state.
Therefore, usefulness of LiveData in this context is very limited.
By the way, while LocalBroadcastManager is alright, I find this mechanism too complicated and restricting. Therefore, if the Service runs in the same process, I prefer to use EventBus in order to communicate from Service to other components (or vice-versa).
An example of such a communication you can see in SQLite benchmarking application that I wrote several days ago. In this app, TestService posts status changes and test results to EventBus as sticky events, and TestActivity subscribes to those events.
Both methods work with using LiveData since the purpose of LiveData is to have it on another thread and still notify users when something has changed. Seems like it would definitely replace LocalBroadcastManager.getInstance(this).sendBroadcast(in); and your IntentService would postValue. Just have your activity or anything that needs to be aware of the changes become an observer.
I have read the two reasons/issue mentioned on:(Please read two reason on below link)
Android AsyncTask for Long Running Operations
1. "If you start an AsyncTask inside an Activity and you rotate the device, the Activity will be destroyed and a new instance will be created. But the AsyncTask will not die":
Lets suppose i have set the orientation of my activity to Portrait. Will this issue still be there?
2. Memory leak issue:
inner class will hold an invisible reference on its outer class instance : the Activity.
What if i am not using Inner AsyncTask instead created separate class. Also if i use weak reference.
The issues you mention arise only when life-cycle of AsyncTask is not handled properly, mainly from lack of understanding of how they work.
AsyncTask is a wrapper for running code on a separate thread. It is similar to plain Java's Runnable submitted to ExecutorService, with additional features of "pre" and "post" hooks to be run on main thread. So, its basically an enhanced version of Thread, Runnable and Handler setup.
By default AsycTask's share a single thread and hence not advised for long running tasks. Because when a single background thread is shared by many tasks, a long running task may block others. However, AsycTask can also run on a custom Executor, removing such restrictions of a shared worker thread.
All that means that AsyncTask's own design doesn't restrict its usage for long running tasks.
You can have a background Service run some continuous processing using AsyncTasks on a separate ThreadPoolExecutor.
You can have a Fragment load latest news using an AsyncTask and when Fragment's onDestroy() is called, you cancel the task, since its no longer meaningful.
Hence the answer to "how long and AsyncTask should run", entirely depends upon the usage context.
Additional problem of AsyncTask: losing your results.
Yes, you said:
Lets suppose i have set the orientation of my activity to Portrait.
Will this issue still be there?
But, Activity could be recreated not only 'cause rotation. For example, if there is no enough resources in system, operation system can destroy your Activity.
So, for long running operations there is high risk that AsyncTask will have an invalid reference to its Activity in onPostExecute() after Activity recreation.
Another problem: parallelism.
new AsyncTask1().execute();
new AsyncTask2().execute();
Will these two tasks run at the same time or will AsyncTask2 start when AsyncTask1 is finished?
Well... It depends on the API level.
And aboud API level...
Before API 1.6 (Donut): the tasks were executed serially. This means a task won't start before a previous task is finished.
API 1.6 to API 2.3 (Gingerbread): the Android developers team changed AsyncTasks to make possibility to start them in parallel on a separate worker thread.
API 3.0 (Honeycomb): the AsyncTasks where executed serially again. Of course the Android team provided the possibility to let them run parallel. This is done by the method executeOnExecutor(Executor). Check out the API documentation for more information on this.
Setting the orientation will work because locking to portrait means no orientation change, meaning no lifecycle re-creation because of this. However if an activity is paused for a long time it can still be destroyed so this is not a good way to make sure this works 100%. You could instead try a service or a headless fragment.
According to this post, having a weak reference will solve the memory issue
AsyncTask have following drawback.
1. Memory leak :- In inner class as well in seprate class you provide reference of your activity to AsyncTask for callback in both case AsyncTask will not release the reference of activity for GC which cause memory leak.
2. GC :- If a AsyncTask is running although the calling activity is destroyed it will restrict the GC to not run till it will not finish its process.
3. On Orintation change activity recreate as Asynchtask will running in background and when it finish its operation it will try to update UI which cause IllegalStateException as activity is not attached to window.
So its better if you use Service for long running background process instead of AsyncTask.
There are so many superstitions around this topic, it's hard to know where to start. AsyncTask is just a small piece of sugar around a standard task queue, using it or not using it does not make much difference in comparison to other things.
For example the problem of orientation change is NOT real. You can start an AsyncTask when the activity starts for the first time and simply not start it the next time around. (and remember that other changes in configuration can also restart your activity).
The weak references are a total overkill and will probably get you nowhere. You either need a reference to the current activity (and then the weak reference won't work) or not (and then, simply don't hold any reference).
The most important, and missing from your question, is what are you actually trying to accomplish?
Think about someone answering their phone while your application is running, and going back to it after some time. And then try to answer questions like:
- are the results from 15 minutes ago relevant? Or will the task be restarted?
- how about 6 hours ago?
- will something bad happen if the background task is interrupted?
- does user expect the task to be finished? (did he press "OK" and just waited for a confirmation to appear?).
And then you can ask a more precise question. AsyncTask can be used in any scenario, but usually it's simpler not to use it than to use it correctly.
The scenario of my problem is:
In my servlet I get a large amount of data from somewhere (not relevant). I have to iterate over all this data and put it in an array, convert it to a JSON object and send it to the client side for viewing. If I do this in a single response it takes a very long time to display the results. Hence, I need to do multithreading.
The created thread needs to keep on adding data to the list while the main thread whenever it gets a request (requests for data keep on coming periodically) sends the present available list.
For instance on first request the response sent is : 1 2 3
Second request : 4 5 6 and so on.
Now I come to actual problem : I don't know how to do multithreading in a servlet. I have looked through numerous resources and examples but it only has confused me further. Some examples have created threads right in doGet which I think is very wrong, some have created them in the init() method but I dont know how can I pass parameters and get results from the thread if it is declared in the init method (It cannot be a global variable). Then there are examples of servletContextListener but I havent found anything useful or that makes sense.
Can anyone please guide to me a reliable source or just give me some sort of pseudo code to get a solution to my problem. It would be extremely helpful if the answers are in context with the aforementioned scenario.
Thanks
The created thread needs to keep on adding data to the list while the
main thread whenever it gets a request (requests for data keep on
coming periodically) sends the present available list.
If I got you correct, you like to get some data as background service and make them ready for clients once they request them(sounds like harvesting data).
Well, creating thread in web-apps, or generally stuffs come with managed environment is different, creating a thread implicitly would cause of memory leak.
One good solution would having a ThreadPool(either by container context/ndi or create it manually).
AND it MUST be created in a manageable manner, where you would control it by environment related events.
ContextListener is your friend, having a context listener class, like this.
public class dear_daemon implements ServletContextListener,Runnable{
ExecutorService the_pool;
Thread the_evil;
/*following get invoked once the context is called*/
public void contextInitialized(ServletContextEvent sce){
/*initialize the thread-pool, and run evil thread*/}
/*following get invoked once the context is destroying*/
public void contextDestroyed(ServletContextEvent sce){eviling=false;
/*stop evil(this) thread(first), then destroy thread pool*/
}
volatile boolean eviling=true;
public void run(){
while(eviling){
/*run Runnable instance which do data fetching using thread-pool*/
}
}
}
And register the listener in web.xml
<listener>
<listener-class>dudes.dear_daemon</listener-class>
</listener>
Having a class(runnable) which do the data fetching, and invoke it by evil thread, each instance using one thread.
The ContextLisstener helps you correctly shutdown and manage init and hult events by container, using the same thing with servlet init is possible, but make sure you do the same thing about hulting with destroy method of servlet.
If you like to do thread-thing about it, make sure you are doing things thread-safe since you have one thing to store data(a list).
If any synchronization is needed(for example ordering the fetched data), make sure you are doing it right, or you will face with deadlocks, or low-performance code.
If any(probably) IO action is needed for getting data, note java IO is blocking, so set appreciated read and connection timeouts, or switch to NIO if you can handle complex NIO stuffs.
If applying these changes make the environment complex, and you like to do alternative solutions, you may simply extract the data fetching from web-profile and run it as a external daemon-service or applciation, where the applciation will pass the fetched data to the server context using calling one of your CGI/Servlet.
I have a simple Tomcat 7 Server where I want to implement a Java Web Service which offers some data I can get via my mobile phone.
The point is I want the data on the server being updated every once in a while. So I need a "background process" which updates the data.
I first tried to start a new thread in the constructor of my binding implementation class (which implements only my own Service - not a HttpServlet or so) like
public NewBindingImpl(){
Thread informationFetcher = new InformationFetcher();
informationFetcher.start();
}
But I didn't think about the fact that this class gets created every time someone is using the service. Further more this would update the data only the moment I ask for them. But how could I update them lets say every two hours or so?
Hopefully someone here has an idea. Is that even possible for a "simple" web service?
Thank you very much,
Tobias
EDIT: ----
Maybe it helps to know that I tried this very basic tutorial here:
http://www.elearning.witnut.com/230/java-web-service-creation-using-top-development-approach/
Why not initialise the thread when the servlet's init() method is called ? You can shut it down when the corresponding destroy() method is called. The thread will be bound to the lifecycle of the servlet and since init() is only called once, you won't have to worry about multiple instances.
Here's a brief tutorial on the init() method usage.
Since you want something running every two hours, check out the Timer class. For more complex scenarios Quartz is a serious contender.
I'm implementing a service that does REST calls for multiple applications. The results of certain REST calls should be stored in a content provider.
I'm currently trying to use multiple threads that would do the HTTP request, parse the result, and store the data in a content provider. In order to do this, I must pass around the Context to each of the threads. I'm not sure if this is a good idea because I do not know if the Context is ok to be passed to multiple threads because of its size, thread safety, etc. I'm thinking that I'm only passing a reference to the Context object for each thread, so maybe its not heavy to pass it around?
Yes, this is fine. I don't believe that explicit synchronization is required, but many of the interesting things you can do with a Context must happen on the UI thread.
Because of this reason it is usually wise to do your http request inside an AsyncTask, which will arrange to have your implementation of onPreExecute and onPostExecute run on the UI thread, as well as provide a nice interface for cancellation.
Pretty much everything in Java is passed by reference, so it's not "heavyweight".
However, you'll need to be careful that your access to members of Context is synchronized appropriately or else you will have thread safety issues.