How to stop a running thread when Activity on destroy at Android? - android

I used some thread objects in my Android activity. But these threads do not stop itself when Activity on destroy. My code for thread-stopping as following:
#Override
public void onDestroy() {
super.onDestroy();
thread.interrupt();
}
Above code is not only working for thread object stopping but also throws an InterruptedException. What's the correct way to stop a running thread without exceptions?
is it not an error when thread object throws InterruptedException?

try this way:
volatile boolean stop = false;
public void run() {
while ( !stop ) {
log.v("Thread", "Thread running..." );
try {
Thread.sleep( 1000 );
} catch ( InterruptedException e ) {
log.v("Thread","Thread interrupted..." );
}
}
}
#Override
public void onDestroy() {
stop = true;
super.onDestroy();
}
and
#Override
public void onDestroy() {
thread.interrupt();
super.onDestroy();
}

trying to stop the thread from outside is not reliable.
I suggest to use global param using SharePreferences or Application Context, ( e.g. IS_APP_ACTIVE ) across your app
and let thread kill itself.
let me try to explain a bit...
in your Activity
protected void onResume() {
super.onResume();
// isAppActive
CommonUtils.setAppActive(mContext, true);
}
protected void onPause() {
super.onPause();
// isAppActive
CommonUtils.setAppActive(mContext, true);
}
in your thread
if ( !CommonUtils.isAppActive(mContext) )
just get out of the thread loop.

I perform this way.
In your activity
#Override
public void onDestroy() {
super.onDestroy();
thread.interrupt();
}
in your Thread
#Override
public void run() {
// stop your thread
if (interrupted()) {
return;
}
// do your work
}

Adding finish(); should end the Activity when onDestroy() or anything else (eg. a button is pressed) is called. When you use onDestroy(), make sure super.onDestroy(); is put after everything else is called.

Related

Is it safe to start thread execution in onDestroy of a Activity/IME?

I am creating a keyboard. I need to do some database intensive operation at onDestroy of my IME. SO I made a Runnable and am calling it in the onDestory as shown, but I'm not sure wether it is safe to do so. Is it?
#Override
public void onDestroy()
{
super.onDestroy();
convexthesavedlists();
Runnable rn=new Runnable() {
#Override
public void run() {
edata.addthislist(MyInputMethodService.this,englist1);
}
};
Thread th=new Thread(rn);
th.start();
}

Android: Restart the interrupted thread on onResume

i'm trying to restart the interrupted thread in onResume (i'm interpreting the thread in onPause). For this i saw lot of examples in online but nothing was helpful (May it's my fault). So,please tell me how to restart interrupted thread in onResume
My code:
private void runThread(){
threadService = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Thread", "thread");
if (freshMSgId != null) {
getPrevChatVolleyInThread();
}
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadService.start();
}
#Override
protected void onPause() {
super.onPause();
if (threadService != null) {
threadService.interrupt();
}
}
#npace Thank you, i got the idea from your comment. I restarted the interrupted thread in onResume like
#Override
protected void onResume() {
super.onResume();
runThread();
}

Finishing Activity doesn't stop thread Android

I have splash activity and 1 thread. Thread starts timer and after some time main activity will start.
Unlike on other apps I don't want to disable backPressed button in Splash Activity. I want when backpressed is pressed to cancel thread and finish activity. But I can't get it to work.
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.starter);
Thread Logo = new Thread() {
public void run() {
try {
sleep(1 * 1500);
Intent i = new Intent(getBaseContext(),
MainActivity.class);
startActivity(i);
finish();
} catch (Exception exception) {
}
}
};
Logo.start();
}
...
#Override
public void onBackPressed() {
Thread.currentThread().interrupt();
super.onBackPressed();
this.finish();
}
}
But this doesn't stop thread, it only finish activity and thread keeps running in background(and ofc starts activity)
Make Thread Logo Object Globally and do Logo.interrupt();
You should stop the thread that you already Started before. and also as #TmKVU answer's Thread.currentThread(); return main UI/Main Thread but you have to Stop your Logo Thread.
Try this If you wish to stop the thread if Back button is pressed by the user:
#Override
public void onBackPressed()
{
// First check if the thread isAlive(). To avoid NullPointerException
if(Logo.isAlive())
{
Logo.interrupt();
}
super.onBackPressed();
}
Do like this:
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
// your logic
SplashActivity.this.finish();
} catch (InterruptedException e) {
finish();
}
}
});
thread.start();
}
#Override
public void onBackPressed() {
thread.interrupt();
super.onBackPressed();
}
It will work as it works in my all apps. Because when you inturrept thread then InterruptedException will be called. At that time finish your activity.
Thread.currentThread() will refer to you Main thread, since it is the currently active Thread.
You should make a field from your thread, so you can access it in your onBackPressed()method. You can then call logo.interrupt()
Use a Handler and Runnable. Instead of the inner new Runnable, create it outside as an object then pass it as a parameter to the handler. When you press back, call this method handler.removeCallbacks(runnable); to cancel the execution. Make sure to keep the variables in a global scope so you can access them anywhere.
handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
startActivity(new Intent(SplashScreenActivity.this, MainActivity.class));
finish();
}
}, SPLASH_SCREEN_TIMEOUT);
Try this code, it may help you.
private Thread Logo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.starter);
logo = new Thread() {
public void run() {
try {
if(!isInterrupted()){
sleep(1 * 1500);
Intent i = new Intent(getBaseContext(),
MainActivity.class);
startActivity(i);
finish();
}
} catch (Exception exception) {
}
}
};
Logo.start();
}
#Override
protected void onStop() {
super.onStop();
System.out.println("On Stop");
logo.interrupt();
}
...
#Override
public void onBackPressed() {
logo.interrupt();
super.onBackPressed();
}
}

How can I terminate thread properly in Android System?

I have a question.
Recently I develop simple "Logging system" for Android.
There is one singleton class which name is "Logger".
protected Logger(){
....
_logHandler = new LogHandler(_logQueue);
_logHandler.start();
....
}
public static Logger getInstance(){
...
}
In "Logger", one thread is running just like below.
#Override
public void run() {
try{
while (isAlive){
execute();
synchronized (lock) {
try {
while (isPaused) {
lock.wait();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
}
}catch(InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
public void requestShutDown(){
isAlive = false;
interrupt();
}
What i want is when application is terminated, I would like to call "requestShutDown()" method to stop thread above.
But i can't find proper moment.
So, Do I have to
When onPause() method executed in Activity, call requestShutDown(). And onResume() method executed in Activity, call thread.start() again?
Is there another way?
Or When Application is terminated, all the resources in application(include thread, Logger class in above) are garbage collected properly?
thanks in advance.
you can create thread like :
Thread th;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
th = new Thread(new Runnable() {
#Override
public void run() {
//do your stuff
}
});
th.run() //to start thread
}
public void requestShutDown(){
if(th.isAlive())
{
th.yield(); //to close thread
}
}
#dwnz Thank you!!
Finally, I call "onDestory()" method in MainActivity. In onDestory(), if isFinishing() of Activity is true, it will be terminated(Of course, this is not "necessary and sufficient condition".)

Why isn't the thread stopping?

My service spawns a new thread, and stops it according to the typically recommended java method of interrupt()'ing. When I stop the service, I stop the thread in onDestroy(). The service is stopped, and the interrupt code is reached. However, soon enough the thread restarts from the beginning of the Runnable.
public class DoScan extends Service {
public volatile Thread runner;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
startThread();
}
#Override
public void onDestroy() {
super.onDestroy();
android.util.Log.v("####################", "DoScan.onDestroy");
stopThread();
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("####################", "DoScan.startthread");
runner = new Thread(new ScanningThread());
runner.start();
}
}
/* use a handler in a loop cycling through most of oncreate.
* the scanningthread does the work, then notifies the svc's uithread
*/
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("####################", "DoScan.stopthread");
Thread moribund = runner;
runner = null;
moribund.interrupt();
android.util.Log.v("####################", "interrupted?" + moribund.isInterrupted());
}
}
}
I think the safest way is to have a flag so the thread checks for it inside its main loop.
class ScanningThread extends Thread {
// Must be volatile:
private volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println("alive");
}
if (stop)
System.out.println("Detected stop");
}
public synchronized void requestStop() {
stop = true;
}
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("####################", "DoScan.startthread");
runner = new ScanningThread();
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("####################", "DoScan.stopthread");
runner.requestStop();
runner = null;
}
}
The problem is that your thread needs to cooperate by periodically checking for interruption and exiting if the thread has been interrupted. Unless you place something along the lines of the following in your thread...
// Processing...
if ( Thread.interrupted() ){
return;
}
// More processing...
try{
Thread.sleep(sleeptime);
}catch(InterruptedException interrupt){
return;
}
// Rinse and repeat...
...your thread will just ignore the fact that it has been interrupted. The method proposed by Lucas S. is essentially identical, except that using interruption will generate an exception if the thread is blocked, whereas under Lucas S.'s method, you might have to wait indefinitely for the thread to quit.
Interrupting a thread throws an exception in the thread, it does not necessarily stop it. You should catch that exception and then do the clean up in thread before exiting (provided, you need to exit!).

Categories

Resources