How to properly interrupt a thread in android - java

In my application I have a button and when it gets clicked I start a new thread and change the text of button. If I press the button again it will start changing its text faster.
I would like to interrupt the thread when the button is pressed in the second time. What's the correct way to do it?
public class TestActivity extends Activity {
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}

In this case, just keep a reference to your thread and use Thread.interrupt():
private Thread runThread() {
return new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Then:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (myThread != null) myThread.interrupt();
myThread = runThread();
myThread.start();
}
});
Read this post for more info and options:
How to properly stop the Thread in Java?

In my opinion, the best way would be using a variable to control this.
Something like:
while(i++ < 1000 && keepRunning)
I see that as a good solution because it cant cause unexpected behavior, as you are sure the exactly moment your thread would exit.
extra--
As a suggestion, I also would recommend you to set your thread non-Damon (setDaemon(false)) because it makes layout changes
Also it is a good practice to give thread a name (setName()) to make it easy on debugging.

Right now you start a new Thread each time you press the button.
Something like this should work.
public class TestActivity extends Activity {
Button btn;
int i = 0;
Thread countThread = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
countThread = new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread() {
if(countThread != null) {
if(countThread.isAlive()) {
countThread.stop();
} else {
countThread.start();
}
}
}
I only had a text editor so I can't guarantee if this solves your problem.

You can use thread.interrupt() to interrupt the thread.

Try this, Just take another variable j and it will handle your code:-
public class TestActivity extends Activity {
Button btn;
int i = 0,j=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
j=1;
runThread();
}
});
}
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(j==1){
btn.setText("#" + i);
j=0;
}
else
Thread.interrupted();
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}

You can use normal Thread in Android (and call interrupt() for your use case) but frameworks provides other better options by providing helper classes around Threads. You can refer to official documentation page for other options.
HandlerThread is preferred option. You can call quitSafely() or quit() for your use case if you go for HandlerThread
Related post:
Why use HandlerThread in Android

Related

how to disable button for some for example 2 minutes in android studio

I want complete code to disable a Button for some time for example 2 minutes in Android Studio. Thank you for help.
protected void onclick(View v){
bwasta = (Button) findViewById(R.id.btDes);
new CountDownTimer(10000, 10) { //Set Timer for 10 seconds
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
bwasta.setEnabled(true);
bwasta.setEnabled(false);
}
}.start();
This might help you out.
Button bwasta = (Button) findViewById(R.id.btDes);
bwasta.setEnabled(false);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2*
60*
1000);//min secs millisecs
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
YourActivityName.this.runOnUiThread(new Runnable() {
#Override
public void run() {
bwasta.setEnabled(true);
}
});
}
}).start();
DO NOT RELY ON Thread.sleep()
Actually, there is already a Question and an Answer on SO regarding the inaccuracy of Thread.sleep()(as per the OP's experience) here.
The answer then favors the accuracy of a ScheduledThreadPoolExecutor using the schedule() method.
Do the following:
Button bwasta = (Button) findViewById(R.id.btDes);
bwasta.setEnabled(false);
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.schedule(new new Runnable() {
#Override
public void run() {
YourActivityName.this.runOnUiThread(new Runnable() {
#Override
public void run() {
bwasta.setEnabled(true);
}
});
}
}, 2, TimeUnit.MINUTES);
You can use mHandler.postDelayed(mRunnable, mTime) function to achieve this
Button bwasta = (Button) findViewById(R.id.btDes);
bwasta.setEnabled(false);
bwasta.postDelayed(new Runnable() {
public void run() {
bwasta.setEnabled(true);
}
}, 2*60*1000);

How to use delay functions in Android Studio?

I want to send a character with Bluetooth. The code works perfectly when there is only a single character.But I want to use a delay function between the two codes.
I want to enter any number with EditText and the app will take that number and do EditText/44. That is what I want to wait between 2 codes
Finally work.. Thanks guys. :)
I moved a,b,c inside setOnClick.. ;
kileri = (Button) findViewById(R.id.kileri);
final EditText value1 = (EditText) findViewById(R.id.textkont);
assert value1 != null;
value1.setText("0");
btAdapter = BluetoothAdapter.getDefaultAdapter();
checkBTState();
kileri.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int a = Integer.parseInt(value1.getText().toString());
int b = a / 44;
int c = b * 1000;
sendData("F");
try {
Thread.sleep(c);
} catch (Exception e) {
e.printStackTrace();
}
You can use handler
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//do something
}
}, 2000 );//time in milisecond
try {
//set time in mili
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
edited as your code
kileri.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("F");
try {
//set time in mili
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
sendData("S");
}
});
Use handler like this:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// do something after 2s = 2000 miliseconds
}
}, 2000); //Time in milisecond
You can do like this
kileri = (Button) findViewById(R.id.kileri);
final EditText value1 = (EditText) findViewById(R.id.textkont);
assert value1 != null;
value1.setText("0");
final int a = Integer.parseInt(value1.getText().toString());
final int b = a/22;
final int c = b/2; // It will take a int from Edittext and do this operation on that.
btAdapter = BluetoothAdapter.getDefaultAdapter();
checkBTState();
kileri.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendData("F");
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
sendData("S");
}
}, c);
}
});
just use runOnUiThread on button click and post Handler after time delay..
Button button = new Button(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendData("F"); // send
delay(2000);
}
});
UPDATE
delay()..
public void delay(final int c){
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(c);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
sendData("S"); //send
}
}, c);
}
It's not recommended to use Thread.Sleep because it stops execution of main thread if it is called in main thread execution.So,if we want to set delay we can use CountDownTimer.
In below snippet,we gave 2 seconds delay.So,after 2s onFinish() callback comes and we can have our operation there.
new CountDownTimer(2000, 1000) {
public void onFinish() {
}
public void onTick(long millisUntilFinished) {
}.start();
}

A thread start on a button click and ending the thread with another button click

Sir Please help me to add a thread that starts on a button click and ends the thread with another button click. In between I have a sound playing till the thread stops.
You can try this simple code:
final volatile boolean toExit = false;
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(!toExit){
// Your code
Thread.sleep(100);
}
}
});
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
t.start();
}
});
findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
toExit = true;
}
});
The thread will stop after button2 clicked and run to while(!toExit).
Threads stop method is deprecated.
The best solution will be having a boolean variable in the run method.
Your Thread:
public class MyThread implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;
public void terminate() {
running = false;
}
#Override
public void run() {
while (running) {
try {
//Your code that needs to be run multiple times
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
}
}
In your Activity:
MyThread t=new Thread();
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
t.start();
}
});
findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
t.terminate();
}
});
Use Below Code
public class SomeBackgroundProcess implements Runnable {
Thread backgroundThread;
public void start() {
if( backgroundThread == null ) {
backgroundThread = new Thread( this );
backgroundThread.start();
}
}
public void stop() {
if( backgroundThread != null ) {
backgroundThread.interrupt();
}
}
public void run() {
try {
Log.i("Thread starting.");
while( !backgroundThread.interrupted() ) {
doSomething();
}
Log.i("Thread stopping.");
} catch( InterruptedException ex ) {
// important you respond to the InterruptedException and stop processing
// when its thrown! Notice this is outside the while loop.
Log.i("Thread shutting down as it was requested to stop.");
} finally {
backgroundThread = null;
}
}
Hope this will help you

I can't update more than one on my infinite thread in button click

At the below code i try to take the user's current location each second as x and y axises.At the first time of loop,the code works.But second and so on it doesnt work.What is the missing thing on this code.What should i do.Thanks..
new Thread(new Runnable(){
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
public void run() {
textViewXAltitude.setText(String.valueOf(gps.getLatitude()));
textViewYAltitude.setText(String.valueOf(gps.getLongitude()));
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
you should do this by Handler;for example:
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
textViewX.setText(String.valueOf(i++));
textViewY.setText(String.valueOf(j++));
}
}
};
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Timer().schedule(new TimerTask() {
#Override
public void run() {
handler.sendEmptyMessage(0x123);
}
}, 0, 1000);
}
});

How to call run method inside a thread from another method in android?

I want to make an quiz application in which the questions will be displayed every ten seconds. But when the user answers the question, I need to display the next question. For this I use threads. I have accomplished displaying questions in regular intervals, but when the user answers the question, it wait for the thread to complete. I want to stop the thread and start a fresh one on a button click. My code is given below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
while (i++ < 10) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
//Display questions here
}
});
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
public void buttonOnClick(View view)
{
//I want to display new question here
}
How can I call the run method inside the thread. Any help is appreciated. Thank you.
You can use t.interrupt() to stop the thread. Here is the code.
Thread t ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
generateQuestions()
}
public void generateQuestions()
{
t = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
try {
while (i++ < 10 & !Thread.currentThread().isInterrupted()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//Display questions here
}
});
Thread.sleep(6000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
public void buttonOnClick(View view)
{
//I want to display new question here
t.interrupt();
generateQuestions();
}

Categories