How do I run a thread only once in an android application? - java

Maybe this is a stupid question, I don't have much experience with android studio. Sorry for that.
In my app I have many activities which represent pages. In MainActivity I create a thread which always listens for something (it stays in loop). But whenever I return to the MainActivity page it creates another thread. If I only want to run it once, what are ways to do it?
I was thinking if maybe using a static variable to count how many times client is running, and stop it from creating another if there already is one.
public class MainActivity extends AppCompatActivity {
private Thread client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
client = new Thread(new CheckForOrders());
client.start();
.
.
}

A thread can only be run once under any circumstances. What's likely happening is that you're creating a new copy of the thread every time your activity is destroyed and recreated on a configuration change (the most common config change being a device rotation.)
If you want to preserve a background thread between activity instances, you have two options:
If you want it to survive between different activities or when no activity is running, put it in a Service.
If you only need it to survive configuration changes, put it in a retained Fragment.

Since you only want one instance of the Thread you can declare it as static something like this:
private static Thread client = new Thread(new checkForOrders());

Related

Save a list of Threads in Android

I have a question concerning the thread:
In my activity I get a list of threads(more exactly a list of Runnable). Inside these threads, I check if the time written in the activity is the same as the current time (basically like an alarm).
When I press back on my android, my activity finishes and I go back to the main screen of my phone...however the thread are still there (which makes sense for me as it is initialized in the heap).
However when I return to my app, I have no way to get access back to these threads...
DO you have an idea how to do it?
Here is a part of my code:
public class SmartAlarm extends AppCompatActivity {
private List<Runnable> listThreadAlarms;
#Override
protected void onCreate(Bundle savedInstanceState)
{
listThreadAlarms = new ArrayList<>();
for(Alarm alarm: alarmList) {
Runnable activateAlarm = new ActivateAlarm(this,(int)alarm.getId()-1,"alarm"+(alarm.getSound()+1),alarm.getTitle());
Thread threadAlarm = new Thread(activateAlarm);
listThreadAlarms.add(activateAlarm);
threadAlarm.start();
}
}
}
i think you should rethink your design. more on this to follow...
I Do NOT Recommend This
if you MUST retain references to these objects, one way to do this is to stash them as instances in a static collection in a long-lived singleton. a custom android.app.Application instance would be an option since it lives for as long as your app does and you can reference it from any standard component such as an Activity, ie:
public class MyApplication extends Application {
public static List<Runnable> runnables;
}
add Runnable instances to the collection as they are created...
...however, i have no idea what the criteria would be for removing them. Runnables are meant to run to completion/error, and then be GC'd. since they don't return a result, we'd need some sort of state within the Runnable instance to know if it has completed its work, which means it can then be removed from the collection so as to be GC'd. by keeping them in this collection, they live beyond their scope of viability, and we've created extra housekeeping for ourselves in pruning the collection.
this sort of approach would technically work, but strikes me very odd and untestable.
I DO Recommend This
let the Runnables communicate the state of their tasks independently through another medium, ie:
shared preferences
a database
an in-memory collection stored in the Application
when your SmartAlarm instance starts, interrogate the state of the associated tasks through that medium.

How to make more than one Android AsyncTask run at the same time?

OK so I have an Android app which has a listview on a fragment being loaded on the mainactivity. The list view contains an imageview which is loaded with an image from the devices external storage via an adapter which in turn calls an AsyncTask object called BackgroundImageLoader.
At this point if I run my app everything work great and the images show nearly instantaneously.
To give more detail about that process....
On the listview's adapter's bindView method I call a method which invokes the following:
BackgroundImageLoader loader = new BackgroundImageLoader(photoID, imageView);
loader.execute();
Now after I got the above code working perfectly I wrote some logic to "purge old photos". This logic was put in an AsyncTask object named AutoPurgePhotos_Task. Basically I want to run the task once on startup of the app but I just want it to run in the background so as not to interfere with the UI. I have tried launching it from the tail-end of the Applications onCreate() method and I have tried launching it from the MainActivity's onCreate() method. The results are such that the purging logic runs and works perfectly. And while it is running in the background my UI seems to be working as well with EVERYTHING EXCEPT the BackgroundImageLoader AsyncTask. None of the photos will begin to show until the AutoPurge task completes. Even to prove it has nothing to do with what I am doing in the task, I commented out all of my business logic and just have the task sleeping.
public class AutoPurgePhotos_Task extends AsyncTask<Void, Void, Void> {
public AutoPurgePhotos_Task() {
super();
}
#Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
return null ;
}
}
As a side note I have other asynctask in my app that will not run either until this initial asynctask finishes. Its as if only one asynctask will run at a time. Again all other code that is in my UI thread appears to be running and working just fine while the asynctask is running. It just seems that only one asynctask will run at a time.
Here is how I launch the autopurge task...
AutoPurgePhotos_Task task = new AutoPurgePhotos_Task();
task.execute();
again I have tried launching it from several different areas and no matter where/how I launch it the other asynctask will wait till that one is done before they will run.
Thanks for any help you can give me.
Use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of execute(). Quoting the AsyncTask documentation:
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.

How to wait for an asynchronous task to return

So I have a problem and I am wondering how to solve it if it can be solved at all.
I have an external library class called Messenger that defines the method sendMessage(String msg). I also have the following MessengerManager class
public class MessengerManager{
private Messenger messenger;
public MessengerManager(Context context){
messenger = new Messenger(context);
}
public void message(){
String msg = "12435";
messenger.sendMessage(msg);
// Do more stuff
.....
.....
.....
}
}
So the issue is that sendMessage runs asynchronously and starts a new activity. Probably using startActivity() (lets call this Activity A). Hence, the code after sendMessage ("Do more stuff") gets run immediately. However, I need to wait for the newly created activity (Activity A) to return to carry on with the "Do more stuff".
As sendMessage is a method defined in an external library, I cannot change it in any way nor do I have access to its source code.
So, in short, my problem is that sendMessage creates a new thread (using startActivity() probably) and I need to know when this newly created activity ends. However, I have no way of monitoring it since it is defined in an external library. Anyone know how to solve this?
AsyncTask should be what you are looking for.
Let your message() starts an AsyncTask that calls messenger.sendMessage(msg) in doInBackground(). If you care about the result of the AsyncTask, get it in onPostExecute().
http://developer.android.com/reference/android/os/AsyncTask.html
One admittedly ugly way to get around this is to call
Thread.sleep(int milliseconds)
after sendMessage(), and before you continue with the rest of your code. Of course, this will only be helpful if you can fairly accurately estimate how long it will take to get the callback.
The better alternative is as Kaifei is saying. But you won't want the "do more stuff" where it is now. Instead, put it in a new method, and call that method in onPostExecute(). That way, the code will not continue until the AsyncTask has returned.
Edit: Saw your addition about needing the created activity to finish. If that's the case, you're going to somehow need to communicate with that activity (which I can't speak to without seeing all the code). But if you have that, then before "do more stuff", insert
while(!activity.isFinished()) {}
and in that activity, have it set a finished variable to true when it is done (however you define done). So the main thread will run this loop until the activity on the second thread is done, and then the first thread will continue.
Double Edit: Another idea. Let's say that the other activity the user has to complete is some form. In your main activity, after you call sendMessage(), have some popup where the user selects "finished" when they have completed the new activity. Have the program only continue when "finished" has been selected. A bit annoying for the user, but if it's only a single additional tap, that should work.
As you mentioned, sendMessage() runs asynchronously. If it's written properly, it must also have provided a callback interface, whose method will be called when messaging is finished. Move the code in that callback method.

Do I need to use multiple AsyncTask subclasses?

My app has FTP functionality and now I want to implement a ProgressDialog for the various operations (Connect, download, upload, file list etc.)
I found this snippet here on stack and it seemed like a good starting point.
public class LoadData extends AsyncTask<Void, Void, Void> {
ProgressDialog progressDialog;
//declare other objects as per your need
#Override
protected void onPreExecute()
{
progressDialog= ProgressDialog.show(FTPConnector.this, "Please wait for ","Process Description Text", true);
//do initialization of required objects objects here
};
#Override
protected Void doInBackground(Void... params)
{
//do loading operation here
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
progressDialog.dismiss();
};
}
I've implemented it as a subclass of my FTPConnector class which contains the various methods for connect, download, upload, listfiles,rename, delete. Do I need to create a subclass of ASyncTask for each FTP operation? If not what can I do?
Firs of all, I was under the impression that using AsyncTask as a subclass of activity was disfavored since the task would retain a reference to the activity that started it which could cause problems. I've generally used AsyncTask as its own class and passed in the context of the activity that executed it. You should look into that.
Second you could make different tasks for each server transaction. I guess it depends how many their are or how complicated your application is. Other than that you could use one class with a switch statement in the doInBackground method and pass in a string tag as one of the varargs (assuming your task takes only strings as initial arguments). This just seems cumbersome and ugly.
I'd probably just make one task for each transaction.
Do I need to create a subclass of ASyncTask for each FTP operation?
Not necessarily but that will depend on the logic that you use inside your AsyncTask methods. If you make them to handle the function that operation needs then you will be ok. But depending on the logic for each operation, it may be easier to control if you create a separate class for each.
However, note that you will need to create a new instance each time you need to call execute(), according to the Docs
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Using AsyncTask for multiple transaction will work, but this is not proper solution. As written before: it could cause problems. I suggest you to take a look at this video(it's about REST client, but described patterns will work for you too). Follow these rules:
Perform transaction in a separate thread
Every thread must be started from a Service
To retain state of transaction use database(don't keep states in a memory)
Use SyncAdapter. Not sure that it works for you(it's depends on your needs)

Firing Android Activity methods on separate process at set interval

I am writing my first Android app(allot of fun so far!) and have run into a roadblock. I am using SDK tools 21.1 targeting Android 4.2.
I am trying to set up a system that allows activities to register to invoke a method at set time intervals. I wanted to do this in such a way that the processing of the request would be handled on it's own process to avoid making the UI unresponsive.
I have been doing some reading and have explored a few avenues. First I thought that a service would be a good way to go about this but found a fair bit of information suggesting that was not a good course of action due to the OS being able to kill services indiscriminately.
I'm now looking at using a ScheduledThreadPoolExecutor. I've created this simple class with an overridable method to pass methods around:
public abstract class BaseEvent implements EventListener {
public abstract void onFire(Object... params);
}
I've created this runnable task invoke the method:
public class HeartBeatTask implements Runnable {
private BaseEvent mCallback;
private Object mParams;
public HeartBeatTask(BaseAioEvent callback,Object... params){
mParams = params;
mCallback = callback;
}
#Override
public void run() {
Log.d(LOG_TAG,"Run called");
if(mCallback != null)
{
mCallback.onEvent(mParams);
}
}
}
I'm going to use it like this (inside an Activity)
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);
BaseEvent callback = new BaseEvent() {
public void onFire(Object... params){
if(params[0] !=null)
{
Context context = (Context)params[0];
Toast toast = Toast.makeText(context, "Task ran", Toast.LENGTH_SHORT);
toast.show();
}
}
};
threadPool.scheduleAtFixedRate(new HeartBeatTask(callback,(this)),0, 5, TimeUnit.SECONDS);
This will execute the task every 5 seconds, although the callback method is only being run once.
I'm thinking that this may not be a good way to do things. My feeling is that I'm overcomplicating things. What I really need is the ability to have something that will execute a method, on a process other than the main thread, and at a set interval, that activities can bind multiple actions to. So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Could any tell me if I am on the right track here? Is what I am trying to do a viable way to accomplish my goal? Is there a better approach I could be taking? Any advice or suggestions would be very much appreciated. Thanks!
a few suggestions for an Android beginner.
Don't call it a separate process. Process is a different thing (Google 'Linux process'), you want to call them on a separate thread inside the same process.
ScheduledThreadPoolExecutor IS better than anything else people will suggest you here such as Timers or PostDelayed.
But I think you do have a philosophical error here as to UI updates shouldn't be running on a timed manner but on an event base instead. Once your Db, Disk or Network operation finishes from a background thread you callback to the UI thread to update it immediately.
There`re several tools for that and I'll list a few, point the one I like the best, but let you do some research on each one
Handler: That's basic java way
AsyncTask: Nice framework but doesn't handle screen rotation
Loader: That's my preferred way
I think your approach is a bit complicated. Consider you example
So, for instance, I may want to have a UI component update after a call is made
to a database, and would want that to happen every minute.
I think I will do it this way.
Create a AsyncTask which will update the UI component.
Create a thread which will execute a new AsyncTask and sleep one minute in a while loop.
Start the thread in step 3. at some point.
Interrupt the thread if you don't want the component to be updated.
Example of step 2
while (true) {
try {
new updateTask.execute();
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
Android is a mobile platform and in all honesty each time you want something run, you better consider it separately. You may be killing the battery or using resources for no reason. I begrudge Zedge app everyday for running for no reason in the background at all times. Especially since on CyanogenMod kernel puts WiFi to sleep, while apparently it is currently on.
I am guessing this is more of an exercise and for running tasks at a specified intervals. One-offs, most universal can be done via AlarmManager class. But this may not be the best solution.
For some system wide events there is the BroadcastReceiver class.
While addressing
So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Easier done via an Interface really.

Categories

Resources