I can't stop this thread when I exit my activity or application.
public class MyThread extends Thread {
public Handler handler;
#Override
public void try{
Looper.prepare();
handler = new Handler();
Looper.loop();
}
}
...
myThread = new MyThread();
myThread.start();
final Runnable runnable = new Runnable() {
#Override
public void run(){
doSomething();
myThread.handler.postDelayed(this,30*1000);
}
};
myThread.handler.post(runnable);
#Override
public void onStop(){
myThread.handler.removeCallbacksAndMessages(null);
myThread.handler.getLooper().quit();
myThread = null;
}
I can confirm that all the onStop() code is run, but the logcat still shows the thread running after I exit the application.
I think even if I remove the battery and smash the device with a sledgehammer it will still keep running, I've tried everything. :~) I must be missing something about handlers, loopers, and threads. Please help.
add a boolean flag in the Activity, say "shouldThreadRun", set to true in onResume(), set to false in onPause()
In run() of the Thread, check whether the Activity is still running
if(shouldThreadRun){
doSomething();
myThread.handler.postDelayed(this,30*1000);
}
Related
I have been trying to stop a handler in my onPause(). Despite of calling removeCallbacks(timeRunnable) or removeCallbacksAndMessages(timeRunnable), the handler is not stopped. I have seen many answers here. But nothing worked. I might be missing something here.
Code:
public Runnable timeRunnable = new Runnable() {
#Override
public void run() {
Log.d("Here is my task");
timeHandler.postDelayed(timeRunnable, 5000);
}
};
public void startTimeHandler() {
timeHandler.post(timeRunnable);
}
public void stopTimeHandler() {
timeHandler.removeCallbacks(timeRunnable);
}
#Override
protected void onPause() {
super.onPause();
stopTimeHandler();
}
I am using below code snippet to run a thread every 10 seconds and update UI based on the values received from Server, stop thread on onPause.
Declare below variables in your class:
public class ActivityPortfolio extends AppCompatActivity {
Handler handler = new Handler();
Runnable runnable;
int delay = 10*1000;
//---------
In your onResume:
#Override
protected void onResume() {
handler.postDelayed(new Runnable(){
public void run(){
doSomething();
handler.postDelayed(this, delay);
}
}, delay);
super.onResume();
}
onPause():
#Override
protected void onPause() {
super.onPause();
handler.removeCallbacks(runnable); // this alone didnt work as we are calling postDelayed() in background as well.
handler.removeCallbacksAndMessages(null);//after adding this it stops thread
}
Am having a handler method which is running in a interval of 5ms. I want to stop this execution after certain period? Any suggestion please
You can manage a handler(runnable) by creating an instance member for the handler and runnable, then managing the handler in the Activity Lifecycle methods.
private Handler myHandler;
private Runnable myRunnable = new Runnable() {
#Override
public void run() {
//Do Something
}
};
Start the runnable with handler.post.
protected void onStart() {
super.onStart();
myHandler = new Handler();
myHandler.post(myRunnable);
}
If the runnable hasn't executed by the time onStop is called, we don't want to run it. Remove the callback in the onStop method:
protected void onStop() {
super.onStop();
mHandler.removeCallbacks(myRunnable);
}
I've got an activity with the following code:
Handler dataLoaderHandler = new Handler();
int mInterval = 3000;
public MyActivity myself;
Thread dataLoader = new Thread( new Runnable() {
#Override
public void run() {
Log.e("MyActivity","ReloadData");
new DataLoader(new JSONData(myself)).execute(Configuration.dataURL);
dataLoaderHandler.postDelayed(dataLoader, mInterval);
}
});
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myself = this;
... some other stuff...
dataLoader.start();
}
... other code ...
#Override
protected void onDestroy() {
super.onDestroy();
Log.e("MyActivity","onDestroy ending thread");
try { dataLoader.join(); } catch(Exception e) { e.printStackTrace(); }
Log.e("MyActivity","onDestroy called");
}
When I hit the back button my activity gets destroyed but the thread still continues to run every 3 seconds. Why is the thread not stopped or better said deleted?
Because you haven't stopped it. Since calling stop() on a thread is already deprecated, you should stop the thread within the thread itself. This can be easily done by calling return on it.
However, don't expect your Thread to finish immediately you hit your back button. The Thread will probably run up until Android OS determines it has to (basically, it may take a while to stop even you call it).
You may want to check that question I made a time ago, it's well answered.
try:
boolean finished=false;
Handler dataLoaderHandler = new Handler();
int mInterval = 3000;
public MyActivity myself;
Thread dataLoader = new Thread( new Runnable() {
#Override
public void run() {
if(!finished){
Log.e("MyActivity","ReloadData");
new DataLoader(new JSONData(myself)).execute(Configuration.dataURL);
dataLoaderHandler.postDelayed(dataLoader, mInterval);}
}
});
#Override
protected void onStop() {
super.onStop();
finished=true;
}
I created a Looper thread class:
public class MyLooperThread extends Thread{
private Handler mHandler;
public void init(){
start(); //start the thread
synchronized (this) {
wait(5000); //wait for run()
}
Log.d("DEBUG","Init Done!");
//EXCEPTION: Can't create handler inside thread that has not called Looper.prepare()
MyObject obj = new MyObject(mHandler);
}
#Override
public void run() {
Looper.prepare();
mHandler = new Handler(){
#Override
public void handleMessage(Message msg){
//Check installed app package names, NOTHING RELATED WITH UI ...
}
};
synchronized (this) {
notify();
}
Looper.loop();
}//end of run()
}
In my Activity, I call above MyLooperThread 's init() method in onCreate(). Besides, I have a ToggleButton element, when ToggleButton is checked, I call MyLooperThread's init() method too.
public class MyActivity extends Activity implements OnCheckedChangeListener{
…
#Override
protected void onCreate(Bundle savedInstanceState){
…
myToggleButton.setOnCheckedChangeListener(this);
myToggleButton.setChecked(true);//checked by default
MyLooperThread myLooper = new MyLooperThread();
myLooper.init();
}
#Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
if(isChecked){
MyLooperThread myLooper = new MyLooperThread();
myLooper.init();
}else{
...
}
}
}
When launch my app, it is fine. My toggle button is shown as checked by default. When I uncheck it & check it again, I got exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
which is pointed to the init() method's last line of code MyObject obj = new MyObject(mHandler);
Why I got this exception? I don't understand, my mHandler is created after I called Looper.prepare() in run().
Pretty sure the error is saying you're trying to do something UI related when not on the UI thread.
As you haven't posted anything that you're doing inside the handleMessage, I'm gonna assume that you're trying to change one of the UI elements. Always use the UI thread to update the UI. It should go something like this:
handleMessage(Message msg) {
...
getActivity().runOnUiThread(new Runnable {
...
// update UI here
...
});
...
}
just use a HandlerThread():
ht = new HandlerThread();
ht.start();
h = new Handler(ht.getLooper());
I am writing a game in which after a specified amount of time a thread must be stopped.The user has failed to complete a particular level.I am using a thread.How do i stop this thread after a specified amount of time and display another view.How do i do this.The following code delays the launching of the thread by timelimit.
Thread t = ... t.join(timelimit);
if (t.isAlive)
t.interrupt();
How do i run the thread and close it after a period of time.
Your working thread
public class Worker extends Thread {
private boolean isRunning = true;
public void run() {
while (isRunning) {
/* do your stuff here*/
}
}
public void stopWorker() {
isRunning = false;
}
}
Your stopping thread
public class Stopper extends Thread {
private Worker worker;
public void Stopper(Worker w) {
worker = w;
}
public void run() {
// wait until your timeout expires
worker.stopWorker();
}
}
you should declare your thread with something like this
public class GameLoopThread extends Thread{
private boolean running = false;
public void setRunning(boolean run){
running = run;
}
#Override
public void run(){
while(running){
}
}
}
This is the safer way, In order to stop you should set the running variable to false. Otherwise If you stop the thead you will get an android exception .
I prefer interrupting the Thread from outside and checking interrupted state in short intervals:
try {
while (!Thread.currentThread.interrupted()) {
doSth();
}
} catch (InterruptedException e) {
// finished
}
you can use below code is run after given specified time.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// after this is rung
}
}, 5000);