There's thread order method like thread.join()
But how to wait thread start point until not thread method done
I made button click listener. In there takePicture function need to start and finish before start Thread.
But when I debug, takePicture and Thread start almost simultaneously.
How can I prevent this?
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
takePicture();
new Thread(new Runnable() {
#Override
public void run() {
send();
}
}).start();
}
});
++++++
make takePicture to thread and do join() before starting below thread not working
this also below thread done first...
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
try {
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
takePicture();
}
});
thread1.start();
thread1.join();
new Thread(new Runnable() {
#Override
public void run() {
Log.d("point", "3");
send(image_byte);
}
}).start();
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
Related
I have an activity with 3 buttons: create, start and cancel. Button create creates a new thread, button start runs it and button cancel stops this thread. And my problem is that thread isn't interrupted after calling interrupt method (this action is performed after clicking on cancel button). I know, that in my thread I should check if thread is interrupted or no. I added it, but interrupting still doesn't work. Here's my code:
private View.OnClickListener listener = new View.OnClickListener() {
#SuppressLint("HandlerLeak")
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.create_button:
thread = new Thread(new Runnable() {
#Override
public void run() {
int i;
for (i = 0; i<10;i++){
final int finalI = i;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
textCounter.post(new Runnable() {
#Override
public void run() {
textCounter.setText(String.valueOf(finalI));
}
});
}
}, 500*i);
if (thread.isInterrupted()){
Log.i(getClass().getSimpleName(), "Thread is interrupted");
return;
}
}
new Handler().postDelayed(new Runnable() {
#SuppressLint("SetTextI18n")
#Override
public void run() {
textCounter.setText("Done!");
}
},(i+1)*500);
}
});
break;
case R.id.start_button:
thread.run();
break;
case R.id.cancel_button:
thread.interrupt();
Log.i(getClass().getSimpleName(), "Cancel Button clicked");
break;
}
}
};
So, why thread isn't interrupted and how can I solve this problem?
Your thread is quickly adding 11 tasks (10 + the last one) to this handler you're creating and then dying. These tasks have a delay, and then the message queue will take care of running the 10 + 1 runnables. To do what you're trying to do you should make the thread to wait 500ms between each loop.
Something similar to this:
thread = new Thread(new Runnable() {
#Override
public void run() {
int i;
for (i = 0; i<10;i++){
final int finalI = i;
textCounter.post(new Runnable() {
#Override
public void run() {
textCounter.setText(String.valueOf(finalI));
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ignored) {
Log.i(getClass().getSimpleName(), "Thread is interrupted");
return;
}
if (thread.isInterrupted()){
Log.i(getClass().getSimpleName(), "Thread is interrupted");
return;
}
}
textCounter.post(new Runnable() {
#Override
public void run() {
textCounter.setText("Done!");
}
});
}
});
There are many problems with your code
Problem 1: When users click on Create button, you create a new thread, it is not expected behavior as you want, so just create a new thread if it is not created yet or terminated.
Problem 2: When users click on Start button
thread.run();
This line does not start the thread, it just executes the code in run method on calling thread, in this case main/UI thread. To start a thread you must use start method. Make sure you start the thread if it is has been created.
Problem 3: When users click on Cancel button
thread.interrupt();
Because there is no thread started so this line will do nothing.
Problem 4: From your description, you want to use a thread to increase counter on a TextView from 0 to 9 each 0.5 second, then display "Done". Your code is incorrect and contains many redundant.
Solution: You can following this code.
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.create_button:
// Only create a new thread if it is not created or it is terminated.
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
final int finalI = i;
// This will post a message to main/UI thread.
textCounter.post(new Runnable() {
#Override
public void run() {
textCounter.setText(String.valueOf(finalI));
}
});
// Sleep current thread in 0.5 second before running next step.
Thread.sleep(500);
}
// Display Done after finishing counter.
textCounter.post(new Runnable() {
#SuppressLint("SetTextI18n")
#Override
public void run() {
textCounter.setText("Done!");
}
});
} catch (InterruptedException e) {
// Display Cancelled if the current thread is cancelled.
textCounter.post(new Runnable() {
#SuppressLint("SetTextI18n")
#Override
public void run() {
textCounter.setText("Cancelled!");
}
});
}
}
});
} else {
Toast.makeText(MainActivity.this,
"Thread is already created. No need to create anymore.",
Toast.LENGTH_SHORT)
.show();
}
break;
case R.id.start_button:
// Start thread if it is created.
if (thread != null && thread.getState() == Thread.State.NEW) {
thread.start();
} else {
Toast.makeText(MainActivity.this,
"Thread is not created yet or it is running.",
Toast.LENGTH_SHORT)
.show();
}
break;
case R.id.cancel_button:
// Cancel the thread if it is running.
if (thread != null && thread.isAlive()) {
thread.interrupt();
} else {
Toast.makeText(MainActivity.this,
"Thread is not running yet.",
Toast.LENGTH_SHORT)
.show();
}
break;
}
}
};
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);
I have a button listener witch include a thread sleep and another button listener.
Second button listener must interrupt this thread and I don t know how to do this:
My code:
button1.setOnClickListener (new View.OnClickListener() {
#Override
public void onClick(View v) {
..........
button1.setEnabled(false);
button1.setVisibility(View.GONE);
button2.setVisibility(View.VISIBLE);
button2.setEnabled(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2800);
} catch (InterruptedException e) {
// ???????
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
button1.setEnabled(true);
button1.setVisibility(View.VISIBLE);
button2.setEnabled(false);
button2.setVisibility(View.GONE);
}
});
}
}).start();
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
..............
// Thread.interrupted(); -> does not work
}
});
} });
How can I make button2 listener to interrupt the thread?
class TestInterruptingThread1 extends Thread{
public void run(){
try{
Thread.sleep(1000);
System.out.println("task");
}catch(InterruptedException e){
throw new RuntimeException("Thread interrupted..."+e);
}
}
b2 //
{
try{
t1.interrupt(); // t1 is the thread to be interrupted
}catch(Exception e){System.out.println("Exception handled "+e);}
}
}
Instead of an anonymous implementation of the thread, make the thread a class variable. Suppose the name of the thread is btnOneThread
private Thread btnOneThread;
Initialize the thread where needed and start it.
btnOneThread = new Thread( ){...}
btnOneThread.start();
When the button2 is clicked call
if (btnOneThread != null) {
btnOneThread.interrupt();
}
By calling the thread.interrupt() method. You also need to save your Thread instance in a field of your class.
Thread t = new Thread() {...}
t.start();
and in the listener:
t.interrupt();
As to
// Thread.interrupted(); -> does not work
it will work from within a class derived from Thread and will be the same as this.interrupted(); t.interrupted() will work outside of the class definition.
Also note that the method isInterrupted() does not clear the interruption flag, while interrupted() has the side-effect of clearing the flag.
I want to update the UI during an intensive task. I've got a separate thread where the intensive method runs but I can't update the UI...
This is the structure of my code:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
Thread t = new Thread(){
#Override
public void run(){
runIntensiveMethod();
}
}
t.start();
}
});
If I comment runIntensiveMethod(); the animation runs perfectly fine. However, it seems as though the UI queue is delayed until the method is run.
How can I post an animation and run the method while the animation runs?
Everything I've tried halts the UI until the method has been executed.
You should set a priority for that thread:
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
Also check here
Just call runOnUiThread when you want to refresh from your runIntensiveMethod()
runOnUiThread(new Runnable()
{
#Override
public void run()
{
updateUI();
}
});
Change your code to this, this should work.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Thread t = new Thread(){
#Override
public void run(){
runIntensiveMethod();
runOnUiThread(new Runnable() {
public void run() {
updateUI();
}
}
}
t.start();
}
});
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