In my Android app I am trying to execute a task every 5 seconds.
I tried doing something like this:
#Override
public void onCreate() {
//standard initialization code
letsChange(); //method name
try{
wait(1000);
} catch(Exception e) {
e.printstackstrace();
}
}
But I get the following error message:
java.lang.IllegalMonitorStateException: object not locked by thread before wait()
What do I do to stop this?
When you call wait() inside a class, you are actually calling wait() on the current instance of that class. To do that, it requires a lock on that instance. If another thread has the lock, you will not be able to wait.
Adding synchronized to onCreate() will acquire the lock (the current instance of the Activity) and let you call wait() inside, but this is definitely not want you want to do as it will block the main/UI thread and cause your app to be non-responsive.
What you probably want instead is the following inside your activity:
private boolean isTerminationConditionMet = false;
#Override
public void onCreate() {
//standard Android onCreate code
final Handler handler = new Handler();
final Runnable task = new Runnable() {
#Override
public void run() {
//code you want to run every second
if (!isTerminationConditionMet()) {
handler.postDelayed(task, 1000);
}
}
}
handler.postDelayed(task, 1000);
}
This will cause the code inside run() to be run after the desired delay (1000ms) and then every 1000 ms until your termination condition is met.
Related
I want perform a network call in every 30sec to push some metrics to Server. Currently I am doing it using thread.sleep(). I found some articles saying thread.sleep() has some drawbacks. I need to know am I doing it right? or Replacing the thread with Handler will improve my code?
public static void startSending(final Context con) {
if (running) return;
running = true;
threadToSendUXMetrics = new Thread(new Runnable() {
#Override
public void run() {
do {
try {
Thread.sleep(AugmedixConstants.glassLogsPushInterval);
} catch (InterruptedException e) {
mLogger.error(interrupt_exception + e.getMessage());
}
// to do to send each time, should have some sleep code
if (AugmedixConstants.WEBAPP_URL.equals(AugmedixConstants.EMPTY_STRING)||!StatsNetworkChecker.checkIsConnected(con)) {
Utility.populateNetworkStat();
mLogger.error(may_be_provider_not_login_yet);
} else
sendUXMetrics();
} while (running);
if (!uxMetricsQueue.isEmpty()) sendUXMetrics();
}
});
threadToSendUXMetrics.start();
}
If You are using only one thread in the network, then usage of the thread.sleep() is fine. If there are multiple threads in synchronization, then the thread.sleep() command will block all the other threads that are currently running.
As per the details you've provided, there is only one thread present which isn't blocking any other active threads which are running in synchronization, so using thread.sleep() shouldn't be a problem.
Use Handler.postDelayed to schedule tasks if you are working in UI Thread and Thread.sleep if you are working in background thread.
Apparently you are sending some data using network, you must do it in the background thread, hence Thread.sleep is recommended.
Simple is:
Thread.sleep(millisSeconds): With this method, you only can call in background tasks, for example in AsyncTask::doInBackground(), you can call to delay actions after that. RECOMMENDED CALL THIS METHOD IN BACKGROUND THREAD.
Handler().postDelayed({METHOD}, millisSeconds): With this instance, METHOD will trigged after millisSeconds declared.
But, to easy handle life cycle of Handler(), you need to declare a Handler() instance, with a Runnable instance. For example, when your Activity has paused or you just no need call that method again, you can remove callback from Handler(). Below is example:
public class MainActivity extends Activity {
private Handler mHandler = Handler();
public void onStart(...) {
super.onStart(...)
this.mHandler.postDelayed(this.foo, 1000)
}
public void onPaused(...) {
this.mHandler.removeCallback(this.foo)
super.onPaused(...)
}
private Runnable foo = new Runnable() {
#Override
public void run() {
// your code will call after 1 second when activity start
// end remove callback when activity paused
// continue call...
mHandler.postDelayed(foo, 1000)
}
}
}
The code above just for reference, I type by hand because don't have IDE to write then copy paste.
I have an asynctask named myAsync that performs some network operations (fetching data from server, and parsing the json).
I also have a handler created once the activity runs.
I also have a runnable in which i run the asynctask. The reason I am using runnable is because I will be using it inside a Handler's postdelayed method as I want this to be repeated every 1 minute.
Runnable runnable = new Runnable()
{
public void run()
{
new myAsync ().execute();
}
};
Then I am using the above runnable inside my onResume;
#Override
protected void onResume()
{
super.onResume();
handler.postDelayed(runnable, 60000);
}
Whenever I leave the activity, I want the check to stop, so I am calling,
handler.removeCallbacks(runnable);
However, the asynctask keeps on running non stop.
What shall I do ?
The whole point of asynctask is to run a thread on the main thread.
So it does not make sense to run it in Runnable()
What you can do is skip the Runnable and Handler...definitely not needed here. Assuming the AsyncTask is an inner class of your Activity, you can set a member boolean variable and check that in your doInBackground()
public Void doInBackground(Void...params)
{
// this is a boolean variable, declared as an
//Activity member variable, that you set to true when starting the task
while (flag)
{
// run your code
Thread.sleep(60000);
}
return null; // here you can return control to onPostExecute()
// if you need to do anything there
}
This will make the AsyncTask sleep for a minute before running the code again. Then in onPause() or wherever you want you set the flag to false. If you need to update the UI then call publishProgress() inside your loop and put the UI code in onProgressUpdate()
You can remove the AsyncTask and just do the proccess with Runnable in this way you can make the repetitions that you need. If this does not work you can set a flag to stop the proccess like said codeMagic.
runable = new Runnable() {
public void run() {
try {
//Proccess
while (flag)
{
//Proccess
handler.postDelayed(this, 3000);
}
}catch(Exception e)
{
Log.i("Log","Error: "+e);
}
};
handler.postDelayed(runable, 3000);
#Override
public void onPause() {
super.onPause();
flag=false;
handler.removeCallbacks(runnable);
}
#Override
public void onResume() {
super.onResume();
flag=true;
handler.postDelayed(runable, 3000);
}
I hope this help.
I just need to stop a thread which was created in previous run time of the same application. This is the scenario. I'm retrieving data from database for the notification using thread in background, But when I start that application again, number of threads are increasing. I need to stop this. I think its better to stop the background running thread in onCreate() method of the application's main class. But noway to do it. Please help me on this thing as soon as possible.
Thanks and Best Regards,
Shehan.
Keep a static reference to the running Thread in your activity class. Inside your thread you need to have a boolean variable you can set or a method you can call that will cause your thread to complete. In onCreate() you can check if you have a running thread, and if so, tell it to stop. Here's a code example:
In your activity:
private static Thread myThread;
In your activity, when you create the thread:
if (myThread != null) {
if (myThread.isAlive()) {
myThread.running = false; // Tell the thread to stop running now
}
}
myThread = new Thread(...);
myThread.start();
In your thread:
public boolean running = true; // Initator of this thread should set this to false to make the thread complete
public void run() {
while (running) {
// do whatever your thread does in a loop
}
}
You can stop the ruuning threads onDestroy() of activity.
please find the below eg:
static boolean stopThread=false;
public myThread implements Ruunable{
public void run(){
while(true){
//your logic
if(stopThread)
break;
}
}
#Override
protected void onDestroy()
{
stopThread=true;
}
I'm not sure if this is the correct way to go about but I will try and explain what I want to do.
I have an Activity which creates a fragment called TemporaryFragment with a label. What I want to do is create and start a service with a Timer in it and that Timer then updates the time in that TextView.
The way I am thinking of going is somehow, when the Service is started, passing the TextView from the Activity to the Service and then the Service keeping a reference to it.
Another possible way is to make the Activity become a listener of the Service and then calling a method in the Service to update the TextView.
Any thoughts would be great and maybe some options.
Thanks in advance.
ADDITION
I'm sorry, I should also specify that I need this timer to run in the background. So when the application is sent to the background, I need the timer to carry on and only stop when I tell it to.
Service is not ideal for such minor task like this, moreover, Service can be run independently of activity. Also spawning new thread or using timer which introduces new thread into the application is not ideal for this relatively minor reason if you are thinking in the terms of mobile applications.
Instead use Handler in your fragment.
create handler in your fragment
private Handler mHandler = new Handler();
to execute your defined task call
mHandler.postDelayed(mUpdateTask, 1000);
or
mHandler.post(mUpdateTask);
and define your task in the fragment
private Runnable mUpdateTask = new Runnable() {
public void run() {
Toast.makeText(getActivity(), "hello world", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(this, 1000);
}
};
If you are showing time-like information instead of countdown-like one, use
mHandler.removeCallbacks(mUpdateTimeTask);
in onPause() method to stop executing your task if the activity is not visible as updating UI isn't relevant and it saves battery (you start task again in onResume() method)
Basically, the idea behind the timer is eventually I am going to add some tracking into my application and therefore need it to continue running even if the application isn't in the foreground – Disco S2
Based on this comment I suggest you to use a local service which resides in the background, doing it's stuff (start a thread from Service#onStart), until it gets stopped by stopService(..).
Activities on the other hand may bind and unbind to that service (see: bindService(..)) to get notified about updates or to communicate with the service in any way.
I would use a more simple approach by using a Thread:
public class MainActivity extends Activity implements Callback {
private static final int MSG_UPDATE = 1;
private static final long INTERVAL = 1000; // in ms
private final Handler handler = new Handler(this);
private Thread worker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE:
updateView();
return true;
}
return false;
}
private void updateView() {
// TODO tbd
}
#Override
protected void onStart() {
super.onStart();
// start background thread
worker = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
break;
}
// send message to activity thread
handler.sendEmptyMessage(MSG_UPDATE);
}
}
});
worker.start();
}
#Override
protected void onStop() {
super.onStop();
// stop background thread
worker.interrupt();
try {
worker.join();
} catch (InterruptedException e) {
}
worker = null;
}
}
You can use the TimerTask Class for this. Override the TimerTask.run() method and then add that TimerTask to Timer class.
Also check this question: controlling a task with timer and timertask
I have one function which queries a network server with a few "ping pongs" back and forth, and have written a custom handler to handle the message communication between my main UI thread and the communication thread (I was using AsyncTask for this, but as the program got more complex, I have decided to remove the communication code to its own class outside of the main activity).
Triggering a single instance of this thread communication from onCreate works perfectly, no problem.
I want this query to run on a regular timed basis -- in the background -- for the entire time the app is in use, so I've set up another thread called pollTimer, which I'm trying to use to call the OTHER thread at a regularly scheduled basis.
Obviously, it's crashing, or I wouldn't be posting this.
Is there a way to get a thread within a thread? Or put differently, trigger a thread from another thread?
Timer pollTimer = new Timer();
private void startPollTimer(){
pollTimer.scheduleAtFixedRate(new TimerTask(){
public void run(){
Log.d(TAG,"timer dinged");
//if the following is commented out, this "dings" every 6 seconds.
//if its not commented out, it crashes
threadedPoll();
}
}, 3120, 6000);
}
private void threadedPoll() {
testThread(asciiQueries,WorkerThreadRunnable.typeLogin);
}
edit: it would probably help to include the "testThread" function, which works by itself when called from onCreate, but does not make it when called from the Timer.
"WorkerThreadRunnable" is the massive chunk of code in its own class that has replaced the mess of having AsyncTask handle it inside the main activity.
private Handler runStatHandler = null;
Thread workerThread = null;
private void testThread(String[] threadCommands, int commandType){
if(runStatHandler == null){
runStatHandler = new ReportStatusHandler(this);
if(commandType == WorkerThreadRunnable.typeLogin){
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler,threadCommands, WorkerThreadRunnable.typeLogin));
}
workerThread.start();
return;
}
//thread is already there
if(workerThread.getState() != Thread.State.TERMINATED){
Log.d(TAG,"thread is new or alive, but not terminated");
}else{
Log.d(TAG, "thread is likely deaad, starting now");
//there's no way to resurrect a dead thread
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler));
workerThread.start();
}
}
You seem to be well on the way already - the nice thing about handlers, though, is that they aren't limited to the UI thread - so if you have a Handler declared by one thread, you can set it up to take asynchronous instructions from another thread
mWorkerThread = new WorkerThread()
private class WorkerThread extends Thread {
private Handler mHandler;
#Override
public void run() {
mHandler = new Handler(); // we do this here to ensure that
// the handler runs on this thread
}
public void doStuff() {
mHandler.post(new Runnable() {
#Override
public void run() {
// do stuff asynchronously
}
}
}
}
Hopefully that helps... if I'm totally off base on your problem let me know
Wots wrong with a sleep() loop? Why do you have pagefuls of complex, dodgy code when you could just loop in one thread?