How can I know that a task I started onResume is running? - java

If I run an async call onResume is there a good way to detect that if the async call is running to not call it again?
Because I am doing a network call using an AsynTask in onResume of a Fragment and it seems to be called too often
Update
THe problem is that when onResume is called there are no variables available. So I don't have a valid reference of an async task anymore to check the status.
The code is like:
public void onResume() {
AsynTask<Void, Void, String> theTask = new AsyncTask<>() {
//code to run
};
theTask.execute();
//code
}
So how am I suppose to do this since I don't have a reference? I mean where should I keep theTask in order to be able to cancel it onResume?

You can getStatus to get the status of the AsyncTask. To check if its running you can compare it to AsyncTask.Status.RUNNING.

Related

How to set up a Handler/Looper to call requestLocationUpdates in a Service callback

I've got a service that instantiates a web server using com.koushikdutta.async.AsyncHttpServer. Inside a callback, I need to instantiate a class which is calling requestLocationUpdates on LocationManager. But this is causing an exception:
Can't create handler inside thread that has not called Looper.prepare()
I'm trying to setup a looper/handler to get rid of this error, but I'm not exactly sure how to proceed. This example shows how to create a thread class which creates a handler, but not how to use it. In this answer which mistakenly claims you can't use a Handler but then provides a link to showing how to do that is some code which I have adapted to look like this:
Handler handler = new Handler();
final GPSListener gps;
handler.post(new Runnable() {
#Override
public void run() {
gps = new GPSListener(ctx,ews);
}
})
This code is in the callback in response to an HTTP request. But there is an immediate problem. I can't use the gps variable in the Runnable unless it is declared final. But if I declare it final outside the Runnable, then it tells me that I can't initialize it since it's final. But I can't initialize it outside the Runnable, because the whole point of putting it in the Runnable is to avoid the exception caused by trying to the constructor trying to call requestLocationUpdates instead a thread which has not called Looper.prepare(). Additionally, this gps variable also needs to be outside the Runnable because another callback (on connection close) needs to call another function on it to shut things down. Further, the variable has to be local to the callback, because it needs to separately instantiate a new object each time the callback is called.
I'm not sure the way I'm trying to set up the handler is even correct, and assuming it is, how can I get past the above issues?
As I understood, you run Service from another thread, don't you?
In order, to make it work you should call Looper.prepare() before your class instantiation.
AndroidSync is single-threaded, so setting up a looper on the thread that you instantiate it isn't going to work anyway. In the callback, create a new thread, prepare a looper, and then after you start the GPS engine, run the loop:
final Thread t = new Thread() {
#Override
public void run() {
Looper.prepare();
gps.start((long)mint,(float)mind,sat!=0);
Looper.loop();
}
};

Can I send a custom event, or call another method, in another class but not wait for the result?

I would like to send a custom event (or call another method) to another class and not wait for the response?
The best way I can explain it is to use the Windows SDK method. It gave you the ability to "post a message to another window" (WM_POSTMESSAGE). The thing about that feature, which is the part I want, is that the message went into the OS's msg queue. So you did not have to wait for the response, your app could continue on.
So is I have a method in class A that is doing something, and at some point it wants to emulate an OnClick event in class B, but not wait for the result as the method still has more to do.
Is this possible?
Sorry for the long winded question.
You can use the LocalBroadcastManager, which I believe resembles the most what you are seeking.
Contrary to what advised in the comments, I do not feel starting a Thread to call a method is a good pattern here.
Have your sender send a signal via the aforementioned component:
final Intent intent = new Intent();
intent.setAction(FILTER_VALUE);
// put your data in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
where
public static final String FILTER_VALUE= "com.you.yourapp.MY_SIGNAL";
public static final IntentFilter SIGNAL_FILTER = new IntentFilter(FILTER_VALUE);
Whoever is meant to receive the signal shall implement a BroadcastReceiver
this.localBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do what you have to do here... call you method
}
}
If you are using Android's framework classes (Activity, Fragment, Service, ...) you should follow the standard life-cycle pattern for registering and un-register the receiver:
#Override
protected void onResume() {
// Listen if someone sends data
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
#Override
protected void onPause() {
// I'm going to the background / or being destroyed: no need to listen to anything anymore...
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
otherwise registering it when the object is initialized should be the way to go.
I believe this is the messaging system you are looking for.
If you want to run some code that will run in parallel while your current code is running, the easiest way to do this would be using a Thread. A thread once started will run in parallel and will not block your application, thus allowing the code that started the thread to continue executing even while the code in the thread is also executing.
To create and use a thread, use the following code:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
//put the code that you want to run in parallel here
}
});
thread.start();
You should be warned though that using parallel programming without carefull planning may result in very weird results especially if two different threads are accessing and changing the same variables or data. You should therefore plan your code very carefully if you plan on using multi threading.

Call finish() or not?

I am trying to fetch some API data to my app and I have two activities. The first one is a Splash Screen (like those used by google while your app gets loaded) and I want to know where to call finish() to end the activity.
public class SplashScreen extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AsyncDataFetch fetch = new AsyncDataFetch();
fetch.setContext(this);
fetch.execute();
}
}
I have moved all my code in my AsyncTask so I don't block the ui thread and now I can't call finish() there, or I don't know how.
Why would I call finish for my app there instead of calling it on my activity you might ask... It is because it generates some sort of glitch if I do this, because my API fetch takes about 1 second and showing and closing this activity takes less.
So, where should I call finish() and how?
You should call finish() in onPostExecute of Async Task after getting result from doInBackground().
If your activity you wanna finish is a splash srceen, you should put finish() at postExecute(), which should be overriden in your asyncsTask.

In android, how can I separate the data loading into its own thread?

So I'm working on my "hello world" application in android/java, and elected to do a sports app (which is strange...I don't like sports...but whatever). So I set up my layout, allow users to 'drill down', so they can see the layout for Baseball, or MLB, or the Indians. Say a user selects 'Indians' from the MLB view. I update the tabs, potentially the color scheme, background, etc, and load the data for the 'news' and 'players' tabs (the latter of which is unique to team layouts). Unfortunately, api calls can sometimes take relatively long to complete, especially when the free API from ESPN is capped at 1 call per second. I do some significant caching already, but there's no way I can guarantee that I won't be loading both 'news' and 'players' for 'Indians' at the same time, so one of the requests will have to wait a full second to return.
So my solution is to have a data loading thread - the UI says 'get me this data', and does the UI work not contingent on the data being there. The question though is - once the data is returned from the data loader (as each piece comes back), how should it update or notify the UI appropriately? My current thought is:
UI thread:
OnSelectIndians()
{
DataLoadThread.GetIndiansPlayers();
DataLoadThread.GetIndiansNews();
// UI stuff
}
OnPlayersLoaded(Array Players)
{
if (layout == INDIANS_LAYOUT) // Make sure we haven't changed layouts
{
foreach player in Players
tab[PLAYERS].textview.text += player
}
}
But this isn't a problem I've had to deal with before. Is this the right way to go about it? Or is there a better/easier design I can use? I don't particularly like requiring the UI thread to have a 'on data returned' method for every type of data I can request. My other loosely-formed idea is to create a lambda function in the UI code, which is passed to the data loader and executed in the data loading thread, so:
DataLoadThread.Queue(
foreach player in GetIndiansPlayers()
myView.tab[PLAYERS].textview.text += player;
);
But I think this is probably the worse route, as now we have 2 threads interacting with the UI. Any advice?
Edit: Okay I got it working using AsyncTask. Out of the box, it still has the problem listed above that I would have to create a new derived class for every type if data I load (so PlayerLoadTask, NewsLoadTask, StandingsLoadTask, etc etc). I also wanted was to have most of the logic visible during the call, so if I'm looking at the event code I know what its doing. Below is the working implementation - would appreciate any feedback on it, but I'll accept the first answer below just the same.
abstract public class LoadDataHelper {
public LoadDataHelper(DataLoader dl, Object param) {
mDataLoader = dl;
mParam = param;
}
abstract public LinkedList<String> LoadData();
protected DataLoader mDataLoader;
protected Object mParam;
}
abstract public class UpdateUIHelper {
public UpdateUIHelper(MyActivity context) {
mContext = context;
}
abstract public void UpdateUI(LinkedList<String> results);
protected MyActivity mContext;
}
private class LoadDataTask extends AsyncTask<Void, Void, LinkedList<String> > {
private LoadDataHelper mLdh;
private UpdateUIHelper mUih;
LoadDataTask(LoadDataHelper ldh, UpdateUIHelper uih) {
mLdh = ldh;
mUih = uih;
}
#Override
protected LinkedList<String> doInBackground(Void... params) {
return mLdh.LoadData();
}
#Override
protected void onPostExecute(LinkedList<String> results) {
mUih.UpdateUI(results);
}
}
//
// .....
//
LoadDataTask task = new LoadDataTask(new LoadDataHelper(mDataLoader, "football") {
public LinkedList<String> LoadData() {
return mDataLoader.LoadLeaguesFromSport((String)mParam);
}
},
new UpdateUIHelper(this) {
public void UpdateUI(LinkedList<String> results) {
TextView tv = (TextView)findViewById(R.id.tv1);
tv.setText("");
for (String res : results) {
tv.append(res + "\n");
}
}
});
task.execute();
Take a look at:
1) AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
The AsyncTask.onPostExecute will be executed in the UI thread.
I think this is the most common technique to do background processing.
2) runOnUIThread: If you are managing your own worker thread, you can use this in a worker thread to make sure code is run on the UI thread.
Its always better to have UI work in UI thread, and Non-UI work in Non-UI thread, But this became a Law from the arrival of HoneyComb in Android.
2 ways to do it in Android.
1. Use Java thread with Handler..
Create a thread to do the process heavy background task, and then display the data using
Handler...
2. Use AsyncTask<>, which is specially designed for Android, to sync the UI work and Non-UI
work. AsyncTask is also known as painless threading.
This is what AsyncTask was designed to do ,
Here is the tutorial that I learned from.
Here is what you do
Create a class that extends AsyncTask
Implement doInBackground and onPostUpdate methods
In the onPostUpdate method update the ui , you can use runOnUiThread to avoid any issues during ui update
The advantage of this using Async tasks is that you can even update the progress and display a visual indicator to the user , You can as easily cancel the task to stop the loading if required
AsyncTask is essentially a helper that simplifies the use of threads
Your best bet is to use the AsyncTask. I created a similar app that made 25+ calls to a server to download images. Using the AsyncTask will cut that time greatly, and still provide a great user experience. Here is a great tutorial on how to use/setup an AsyncTask:
http://www.peachpit.com/articles/article.aspx?p=1823692&seqNum=3
async task is the solution for you
here is a tutorial

How to get Async to run thread in background?

I am pulling around 1500 data plots and adding them to overlays for an map view. I want to run this in another thread while the rest of my program finishes starting up. I would like a progress spinner to spin only on the map portion while its loading the data plot points.
I have searched and found what I need, but Im not sure how to implement it and where in my code to put it.
What would I put in the params
Does this go in another class or in my main oncreate method.
When would I call the methods?
private class UpdateFeedTask extends AsyncTask<MyActivity, Void, Void> {
private ProgressDialog mDialog;
protected void onPreExecute() {
Log.d(TAG, " pre execute async");
mDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Retrieving data ...", true);
}
protected void onProgressUpdate(Void... progress) {
Log.d(TAG, " progress async");
}
#Override
protected Void doInBackground(MyActivity... params) {
// TODO Auto-generated method stub
return null;
}
protected void onPostExecute(Void result) {
Log.d(TAG, " post execute async");
mDialog.dismiss();
}
}
From your question I actually am not a hundred percent sure what you currently understand about AsyncTasks so this may be a little some stuff you already know but bear with me.
"Does this go in another task or in my onCreate method?":
AsyncTask is a class which you are supposed to subclass to do what you need, it is not a piece of code which can inlined in your onCreate. You could make an anonymous AsyncTask class in your onCreate, but usually you want it as either a private internal class or its own class entirely.
As for when you call the methods; you don't they are lifecycle events.
onPreExecute() is called on the UI thread just before starting the background work and is a place to do things such as modify components to show progress, or throw up a dialog.
doInBackground(Params...) is the main method which runs in the background on another thread, do your work here. Do not try to modify UI here
onPostExecute(Result) is when your task has finished and is run on the UI thread again. This is where you should handle your UI update.
You only call execute(Params..), which will start the AsyncTask, passing the objects you put as the params into the doInBackground(Params...) method of the task. So the answer as to what to put as params is whatever you need to have access to in doInBackground(Params...).
That should be a decent overview for your needs but you should really check out the docs.
To start the AsyncTask, you simply go
(new UpdateFeedTask()).execute(activityInstance);
It can go where ever you want it, though where you put it might limit access to the variables and objects you want to interact with. E.g. private internal class will have access to them while an entirely new class might not have as easy of an access.
doInBackground(MyActivity... params)
is where the parameter you passed into the execute() function will go, and you can access it via params[0].
You should not call any methods in the AsyncTask class, besides execute().
1. What would I put in the params
It depends. The First parameter is what the task will take in.
The last generic is what it will return.
2.Does this go in another class or in my main oncreate method. You call the execute method when the you want the task to run. The implementation can be in the Activity class or in a different .java file.
3.When would I call the methods?
You only call the execute method. That will make the task run in the background. Then the task will call onPostExecute when it is done.
Here is an example
private class UpdateFeedTask extends AsyncTask<String, Void, DataReturnType> {
#Override
protected DataReturnType doInBackground(String... params) {
String url = params[0];
//Get data from URL
}
#Override
protected void onPostExecute(ReturnDataType result) {
//Do something with result
}
}
Then call the task using the execute("http://foo.com")
Also add android:configChanges=true to the Activity in the manifest. This will make sure that the activity is not killed when the task is still running in the background. Otherwise the task will finish and report back to a null Activity unless you tell the task to callback the new activity.

Categories

Resources