Im using the Parse SDK, and at times, after running a few queries one after the other, all calls to Parse just get blocked and I need to restart my app. ( Log: http://pastebin.com/qk6jvtBb )
Usually a single operations involves these FOUR things: Save Object; Make Query; Save Installation; Send Push (im gonna keep the code really specific)
...
pObject.saveEventually();
...
pQuery.getFirstInBackground(new GetCallback<ParseObject>()
...
pInstall.saveEventually(new SaveCallback()
...
pPush.sendInBackground(new SendCallback()
What I want to know is. Should I use sendInBackground for all or saveEventually for all or should I run each in a separate Runnable with its own Handler?
I would recommend if all of the operations are specific to one task, then put it all in an IntentService, do nothing in the background.
so your code would look like this
public class MyClass extends IntentService
{
...
#Override
protected void onHandleIntent(Intent mIntent)
{
try
{
pObject.save();
pQuery.getFirst();
pInstall.save()
pPush.send();
}
catch(ParseException e)
{
//handle errors here DEBUG
}
}
}
The benefit to doing this is that your parse operations are executed one at a time, sequentially, and on a background worker thread. You won't have to worry about four/five different parse sdk calls running at the same time.
Remember, put the IntentService in the manifest. Start the IntentService with an Intent. No need to call stopSelf() when you are finished with your parse sdk operations. You will have to bind the service to your activity, or send a broadcast to let the activity or fragment know that the operation is complete.
Related
I have some fragments loaded in a ViewPager, where each "page" is loaded from a row in a cursor. Each fragment shows an image (JPEG) on the device. When the user dismisses the fragment (i.e swipe/page change, hits back/up, or just closes the app entirely) I want to invoke a method which opens the JPEG file for writing and does an update of its metadata. The actual work is eventually handled by the Apache Commons Imaging library.
I've implemented this by invoking my saveToFile() method from each fragment's life cycle onStop() handler. Does this mean the entire file operation ends up running on the UI thread? Should I definitely set up an AsyncTask for this?
Say the file write for some reason suddenly (for some jpeg) should take a long time, eg 2 minutes. What would then happen? Would the UI just wait (freeze) at this page/fragment before resuming? Or would the process (write to file) carry on "in the background" somehow? Or would the process just be killed, stopped short mid-process?
The way I have this wired up currently (onStop invoking saveToFile(), which calls up the imaging library and then updates the file) seems to work as it should. Even if I end the app, I still see my Toast text popping up, saying "Writing to file..." Seemingly, the process is never disturbed, and I can't say I'm experiencing any UI lag.
onStop() handler. Does this mean the entire file operation ends up
running on the UI thread? Should I definitely set up an AsyncTask for
this?
YES
An AsyncTask has several parts: a doInBackground method that does, in fact, run on a separate thread and the onPostExecute method that runs on the UI thread.
You can also use some sort of observer pattern such as EventBus to run async and post results to the UI.
Say the file write for some reason suddenly (for some jpeg) should
take a long time, eg 2 minutes. What would then happen? Would the UI
just wait (freeze)
The application will crash because Android will forcefully close it due to ANR (Application Not Responding).
Refer to the official documentation for details on this: https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by
default the "UI thread" or "main thread"). This means anything your
application is doing in the UI thread that takes a long time to
complete can trigger the ANR dialog because your application is not
giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little
work as possible on that thread. In particular, activities should do
as little as possible to set up in key life-cycle methods such as
onCreate() and onResume(). Potentially long running operations such as
network or database operations, or computationally expensive
calculations such as resizing bitmaps should be done in a worker
thread (or in the case of databases operations, via an asynchronous
request).
The most effective way to create a worker thread for longer operations
is with the AsyncTask class.
Here is what I recommend though. Use the above mentioned, EventBus and create a BaseActivity which will automatically save the data for you onClose() by firing an event that runs Async. You then extend that base activity in all the places where you need autosave capabilities.
Here's what I mean with an example that uses EventBus.
public abstract class BaseActivity extends Activity{
#Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
#Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
#Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}
I know how to save states and restore them, but I just get confused when I have to do work with the Web services and to update UI. For times I was using the AsyncTask but then I came to point where I loose my activity/fragment context for example when I rotate the device. So in this way, I am thinking how other apps are handling such situations.
If I use the IntentService and call my web service from there, then I came to think that for each web service I have to make IntentService differently, and update the UI of each activity and fragment I have to make the BroadcastReceiver for each activity and fragments.
So what is a good practice for calling web service from the activity and the fragments?
How can I Update UI when the service return arrives (or call next service based on first services results)?
If you want your data to be instantly available through configuration changes (which you do), then you probably want to use Loaders.
It gives the developer a mechanism of loading data asynchronously for an activity or fragment. Since loaders are specifically designed to solve the issue of async loading, one does not have to spend too much time designing async tasks to handle all different scenarios efficiently.
Good article about Loaders https://medium.com/google-developers/making-loading-data-on-android-lifecycle-aware-897e12760832
Try using retrofit. It's a great networking libraries for Android apps and it's easy to use.
The entire network call + JSON/XML parsing is completely handled by it (with help from Gson for JSON parsing). Documentation is great and the community is huge.
check out this sample.
I noticed a comment you made:
...and my webservices are soap and I cant change them
The way I'm currently calling my web service, which is also SOAP, is via an Intent. I do this by passing in the data that I'm submitting to the Web service with putExtra then receiving it on my WebService, as you probably do right now. I then get the result from that web call and process it inside an AsyncTask, the async task will then utilize EventBus to post to Results as needed which are received on my MainThread via ThreadMode.Main.
So with that said, I highly recommend the use of a library called EventBus from Greenrobot.
You greatly simplify communication between Activities and Fragments, You can get started immediately using a default EventBus instance available from anywhere in your code. For example, you can do the following.
EventBus.getDefault().post(new ModelForOtherActivityToSee(data));
In the model, you can include anything you want, and react accordingly when received.
The best part is that when received, EventBus handles how the data will be executed by either running ASYNC, MAIN, BACKGROUND
ASYNC - Event handler methods are called in a separate thread. This is always independent from the posting thread and the main thread. Posting events never wait for event handler methods using this mode. Event handler methods should use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number of long-running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
Background - Subscribers will be called in a background thread. If posting thread is not the main thread, event handler methods will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single background thread that will deliver all its events sequentially. Event handlers using this mode should try to return quickly to avoid blocking the background thread.
MAIN -Subscribers will be called in Android’s main thread (sometimes referred to as UI thread). If the posting thread is the main thread, event handler methods will be called directly (synchronously like described for ThreadMode.POSTING). Event handlers using this mode must return quickly to avoid blocking the main thread.
An example of receiving an event broadcasted from EventBus:
//ThreadMode can be ASYNC, MAIN, BACKGROUND
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(ModelForOtherActivityToSee eventModel) {
/* Do something with eventModel received, this runs on UI thread */
};
Full example on how to use EventBus:
1 - Open your build.gradle for the app and set your dependency for EventBus:
dependencies { compile 'org.greenrobot:eventbus:3.0.0'}
2 - Create your first model to use in publishing an EventBus, I will use a very simplistic example of a model:
package com.myapp.models.eventbusmodels;
public final class EventBusMyModel {
private final String dataRaw
public EventBusMyModel(final String rawData) {
this.dataRaw = rawData;
}
public String getRawData() {
return this.dataRaw;
}
}
3 - Now all that's left is pushing out a broadcast by using from anywhere.
EventBus.post(new EventBusModel("My Data here"));
4 - To enable Activities/Fragments to receive events from EventBus you must attach and detach, this is what I mean. From inside an Activity on the onResume() and onStop() overrides:
public class SomeActivity {
#Override
protected void onResume() {
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
}
#Override
protected void onStop() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onStop();
}
}
5 - The final thing to do is receive that broadcast, you can receive it in Any Fragment, Activity, or in all your fragments/activities. Here's an example from inside the SomeActivity:
#Subscribe(threadMode = ThreadMode.MAIN)
public void eventThisNameDoesNotMatter(final EventBusMyModel resultModel) {
String receivedData = resultModel.getRawData();
//Do whatever with receivedData. Since we are on ThreadMode.MAIN, this is on the UI thread.
}
I have a Service running in my app..
This Service has an object for sending message to the server and a function to get that object and use it.
The object is initialized from the Service and yet when the UI gets this objects and use it - it looks like it uses it on the UI Thread..
Is this correct ? Is there a way i can make my object always run from the Service Thread ?
public class ServerMessagesManager extends Service {
private ServerMessagesReceiver serverMessageReceiver;
#Override
public void onCreate() {
super.onCreate();
this.serverMessageReceiver = new ServerMessagesReceiver(app);
}
public ServerMessagesReceiver getServerMessagesReceiver()
{
return serverMessageReceiver;
}
}
Use IntentService instead of Service. If you do network calls in a Service, the UI will stuck. Therefore, use an IntentService since it uses a separate Thread.
And you do not know when a server message will retrieve the data. A NullPointerException could be thrown if objects are accessed as long as network calls are still in progress. Use BroadcastReceivers to fire an Intent whenever a server responds.
As far I know, Android service run on UI thread. If you want to make an asynchronous job, you should use Intent Service
See:
What is the difference between an IntentService and a Service?
Here is an Intent service example you can try.
I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running
You have already some answers to your question, but I think it worths a summary ...
What you need
When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.
You can achieve that in 2 ways:
Using Thread:
This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.
Using AsyncTask:
Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.
What you don't need
Service
This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.
IntentService
This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.
Regards.
an Android Service is not in a background thread.
Therefore you should have a Service running that will start an ASyncTask each time you want to poll.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.
Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.
As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.
Here you got with AsyncTask fundamentals and some tutorials
And here you got with IntentService fundamentals and tutorials
Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.
EDIT
There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed
If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.
Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.
The thread will run only when the app is running
Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.
Example:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
#Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}
I am writing an android app and I need to be able to do certain things periodically/continuously. I am coming from a C/C++ embedded firmware background and this new-fangled way of doing things is going to take some getting used to. It seems that there is no such thing as a "main loop" in Android, that everything is event-driven... I also understand that by default all code you write operates on the GUI thread, and I should probably make a new thread to execute the equivalent of a "main loop"...
So far what I have is an implementation of the AsyncTask class who's "doInBackground" method contains an infinite loop (my main loop), I create an instance of this class and run it immediately when my app starts. The problem I am having is in the interaction between this thread and the user interface... when something occurs in my main loop thread and I want to update the GUI understand that I must call "publishProgress", which is executed on the GUI thread. There are a few problems with this, primarily that many things I have tried to do in this "onProgressUpdate" method do not work, or do not occur in a predictable amount of time.
My question, is there a better way to accomplish what I am trying to do? In general, what do most people do when they have code that they want to run periodically and/or continuously while their application is running, code that must interact with the user interface in a timely manner (by timely I mean with zero delay).
Thank you.
public class MainLoopThread extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
while(true)
{
//Do stuff
//Update GUI
publishProgress();
}
}
protected void onProgressUpdate(Void...voids)
{
//Update GUI
}
}
It is unclear what you are trying to do, however just let me say using AsyncTask in this way may have negative consequences.
AsyncTask internally uses a thread pool pattern for running the stuff from doInBackground(). On Android OS before 1.6 and starting from 3.0 the pool size is just 1, meaning no parallel computations for a bunch of AsyncTasks. More details on this here.
So, this may result that only this current AsyncTask is running, while others even if started will have to wait untill the current one is done.
Depending on your needs for things to be done periodically Android exposes:
AlarmManager
Handler - it allows to post a runnable on UI thread with a delay or periodically
Timer + Activity.runOnUiThread(Runnable action) inside of TimerTask
UPDATE: basing on your comments it looks like you need a Service, that starts a thread that periodically sends broadcasts with the data for UI. Then your UI (Activity) registers broadcast receivers to catch those broadcasts, extract the data and use for UI updates.
So your saying that onProgessUpdate() isn't working? That seems weird because it should.
Another option that you have is just to make a Thread that loops.
The trick is that if you want to update the UI thread you will have to make a call to view.post() and give it a runnable that will actually perform the update. The idea here is that you must schedule an update on the UI thread, you can't just take it and say NOW!