I'm trying to do something like this after clicking a button:
case R.id.bcheckConnection:
if (IPok()) {
PlcState.ErrPlc = false;
Constant.adressIpPlc = adresIp.getText().toString();
final ProgressDialog dialog = ProgressDialog.show(Main.this, "", "Trying to connect...");
new Thread(new Runnable() {
public void run() {
timeout = network.testConnection(Constant.adressIpPlc, 102, 20000);
dialog.dismiss();
}
}).start();
if (timeout > -1) {
PlcState.ErrPlc = false;
stanPolaczenia.setText("Connection established. Timeout = ");
stanTimeout.setText(Long.toString(timeout));
currentIp.setText(Constant.adressIpPlc);
} else {
PlcState.ErrPlc = true;
stanPolaczenia.setText("Error");
stanTimeout.setText("");
currentIp.setText(Constant.adressIpPlc);
}
} else {
Toast.makeText(Main.this, "Wrong IP", Toast.LENGTH_LONG).show();
}
break;
So is it possible to change text AFTER thread stops running?
You can use Thread.join() to block the current thread until the given thread is finished:
Thread myThread = new Thread(new Runnable() {
public void run() {
// Do something
}
});
myThread.start();
// Do some things
// and block current thread until myThread is finished
myThread.join();
// Continue execution after myThread got finished
Edit: As #Eric already mentions in the question comments: for your (example) situation it seems to make more sense to use AsyncTask. It has two events (that are called on the UI thread), so you can update your UI with progress updates and when the task finished. For an AsyncTask example see: AsyncTask Android example
Related
I have this problem. I'm trying to update my TextView from another thread and it's not letting me.
I have tried a bunch of different solutions and none of those didn't seem to help. In my while loop code is printing that "Started new loop" all the time but it's not continuing from that runOnUiThread.
Can anyone help me figure out how to update TextView from another thread?
//second thread
protected void startKakkosThread() {
Thread t2 = new Thread() {
public void run() {
while (true) {
System.out.println("Started new loop");
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
if(rullaavaNumero >= 0) {
rullaavaNumero--;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
sleep(1000);
}else{
rullaavaNumero = 9;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
sleep(1000);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
}
}
};
t2.start();
}
Here is a quick fix, you have an infinite loop that runs faster than a thread can have a chance (time) to start. So even thus you have a sleep in side your thread with if statement, if the thread never starts then sleep have no effect.
And your sleep inside a Thread won't work like this. You want to delay your infinite while loop, therefore you need to move sleep on out of the thread in your while loop.
It is still possible to delay your thread by adding extra sleep in it, but all that depends on what you want to achieve.
Your final code would look like this:
protected void startKakkosThread() {
Thread t2 = new Thread() {
public void run() {
while (true) {
System.out.println("Started new loop");
runOnUiThread(new Runnable() {
#Override
public void run() {
if (rullaavaNumero >= 0) {
rullaavaNumero--;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
// no need for sleep here
// sleep(1000);
} else {
rullaavaNumero = 9;
System.out.println(rullaavaNumero);
pelaajanPisteetTeksi.setText("" + rullaavaNumero);
// no need for sleep here
// sleep(1000);
}
}
});
// add this part
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t2.start();
}
I have test it and it works, you could also go what #cricket has suggest.
My eye saw another issue, which is not a part of your question, but good to mention. I assume you want to count from 9 to 0, if that is the case, you need to correct following line by removing = otherwise you get counts till -1, so your code line would look like this:
if(rullaavaNumero > 0) {...
I'm very new to Android programming so pls excuse my ignorance...
I'm trying to do simple Android app:
User presses a button, starts postDelayed job and then waits on conditional var
after timeout the postDelayer job should signal
private final static long TIMEOUT = 10000;
private Handler mHandler;
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mHandler = new Handler();
...
}
private void timeOutSignal() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d(">> ", "---> timeout notify");
lock.lock();
try {
condition.signal(); // releases lock and waits until doSomethingElse is called
} finally {
lock.unlock();
}
}
}, TIMEOUT);
}
public void buttonClick(View view) {
timeOutSignal();
Log.i("???", "... WAIT");
lock.lock();
try {
condition.await();
} catch (InterruptedException e) {
// todo
} finally {
lock.unlock();
}
Log.i("???", "... WAIT DONE !");
}
What happens is that buttonClick() is stuck waiting and I'm not even seeing the "---> timeout notify" message after timeout...
What I'm doing wrong ?
EDIT: Tried to fix messed up example...
You can't do what you're trying to do. Handlers run on Looper threads. Handlers that are created with the default constructor will use Looper thread that it is currently running in. In this case, it is the main Looper thread (or UI thread). So, you're locking on the UI Thread and the Handler unlocks on the UI Thread, but it will never reach that point because you're blocking the UI Thread.
Also, at no point do I see you actually calling the method that posts to the Handler.
Consider this example:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
// Show toast message
}
});
Now I will start this thread on button click in MainActivity and right after that I would exit the activity on back button press, but in overided method onBackPressed following code is implemented:
If(thread != null)
thread.interupt();
finish();
After few seconds toast message is shown, why is that?
interrupt, clears the interrupt status of your thread and will cause the InterruptedException to be thrown. So if your thread is sleepin, and while it is asleep, you call interrupt, it will be woken up, and the execution flow will continue from the instruction that follows the catch block. Assuming you have something really simple like:
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
or
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
}
both will shown the Toast even though you called interrupt()
While blackbelt has already explained the reason why this happens, here is how you can get around the problem.
The best way to interupt a thread is to use a if-boolean-break method.
So if i were to re-write you code it would be along the following lines
onBackPressed:
isBackPressed = true;
inside the thread's run method:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
if(!isBackPressed){
// Show toast message
}
}
});
I have a thread containing a runnable.
I need this to loop infinitely unless cancelled by the user.
I have no idea how to go about this. All help is greatly appreciated.
Cheers.
I need this to loop infinitely unless cancelled by the user.
Obviously you can easily add a loop inside of your run() method:
new Thread(new Runnable() {
public void run() {
while (true) {
// do something in the loop
}
}
}).start();
It's always a good idea to check for thread interruption:
new Thread(new Runnable() {
public void run() {
// loop until the thread is interrupted
while (!Thread.currentThread().isInterrupted()) {
// do something in the loop
}
}
}).start();
If you are asking about how you can cancel a thread operation from another thread (such as a UI thread) then you can do something like this:
private final volatile running = true;
...
new Thread(new Runnable() {
public void run() {
while (running) {
// do something in the loop
}
}
}).start();
...
// later, in another thread, you can shut it down by setting running to false
running = false;
We need to use a volatile boolean so that changes to the field in one thread are seen in the other thread.
i have two threads one for downloading and other for displaying data there is a cancel button in layout i want when i click cancel button the downloading thread stops how can i do this
final Thread parseThread=new Thread(new Runnable() {
public void run()
{
count=1;
searchResult.clear();
Log.v("url","++"+"http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
Log.v("searchText","searchText "+ v.getText());
downloader("http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
//if(msearchCancel)
}
});
parseThread.start();
Thread displayThread = new Thread(new Runnable() {
public void run() {
try {
if(msearchCancel)
parseThread.interrupt();
else
parseThread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
mHandler.post(new Runnable() {
public void run()
{
list_ed=new EfficientAdapter(getApplicationContext());
searchList.setAdapter(list_ed);
progress_waiting1.setVisibility(ProgressBar.GONE);
}
});
}
});
displayThread.start();
First, use AsyncTask for tasks in own threads, it's much easier and handles some low level stuff for you.
Then, in your thread (or background task in AsyncTask), you need periodically to check that main thread requests cancel. In AsyncTask it is isCancelled method.
If you detect cancel request, you exit thread's function ASAP, so that thread may be closed. Otherwise, in case of AsyncTask.cancel, canceling is blocked until background task (thread) gracefully ends.