Black view when starting new thread - java

In my android application I want an automatically refresh every 60 seconds. So I tried it like this:
public void refresh_check() {
Thread myThread = new Thread()
{
int counter = 0;
#Override
public void run() {
MyActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
while (counter < 60) {
try {
Thread.sleep(1000);
counter += 1;
System.out.println("Counter: " + counter);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
refresh();
}});
super.run();
}
};
myThread.start();
}
This works in the way that it prints the counter into logcat but in my Application I get a black view. refresh() is just a function with a http request, and this works alone, so the mistake has to be in the thread at any place :/ Can someone help?

You are not utilizing the Thread correctly. Running long tasks on the UI thread is just like not using a Thread at all. To accomplish what you need you should do it like this:
public void refresh_check() {
Thread myThread = new Thread()
{
int counter = 0;
#Override
public void run() {
while (counter < 60) {
try {
Thread.sleep(1000);
counter += 1;
System.out.println("Counter: " + counter); //I think this may cause exception, if it does try removing it
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
refresh(); // In refresh(), use TextView.post(runnable) to post update the TextView from outside the UI thread or use handlers
}});
super.run();
};
myThread.start();
}
Also, take a look at AsyncTask class, it enables you to run long tasks outside UI thread (doInBackground()) as well as update UI with the result from (onPostExecute())

Related

Using Syncroniation wait/notify complete stops program from working Android

I am trying to stop the for loop and wait until the method has finished and continue once it has called onFinish. I was suggested to use either CyclicBarrier or syncronized wait/notify, but neither of them work.
When I run the method without the "stoppers", it always reaches to the onFinish, calling all 3 System.out.prints, but when I add either CyclicBarrier or syncronized it just does not start ticking. Meaning it only prints the first line countDownTimer first call and then stops and does nothing.
Just to make it shorter I have added both stoppers here to show how I did either of them, but I did use them seperately.
What can I do to make it "tick" ?
cyclicBarrier = new CyclicBarrier(2);
object = new Object();
for (int i = 0; i < sentenceList.size() - 1; i++) {
String currentLyricLine = sentenceList.get(i).content;
long diff = sentenceList.get(i+1).fromTime - sentenceList.get(i).fromTime;
int interval = (int) (diff / sentenceList.get(i).wordCount);
if(isFirstLine) {
startLyricCountDownTimer(diff, interval, currentLyricLine, coloredLyricsTextViewFirstLine);
isFirstLine = false;
} else {
startLyricCountDownTimer(diff, interval, currentLyricLine, coloredLyricsTextViewSecondLine);
isFirstLine = true;
}
//First tried with this
synchronized (object) {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Then tried with this
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
private void startLyricCountDownTimer(final long millisInFuture, final int countDownInterval, String lyrics, final ColoredLyricsTextView coloredLyricsText){
System.out.println("countDownTimer first call" );
coloredLyricsText.setText(lyrics);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
new CountDownTimer(millisInFuture,10) {
#Override
public void onTick(long millisUntilFinished) {
System.out.println("countDownTimer second call + " + millisUntilFinished);
//Do some stuff (irrelevant since it never gets here)
}
#Override
public void onFinish() {
System.out.println("countDownTimer last call" );
//First tried with this
synchronized (object) {
object.notify();
}
//Then tried with this
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}.start();
}
});
}
If i understand correctly then it was also mentioned that I run my loop on UI thread which is why everything stops. And well I do not wish to stop the UI thread, just to wait for one countDownTimer to finish, then start a new loop.

delay inside while loop not working

i'm trying to make a delay inside while loop using Thread.sleep() method . here is my code :
new Thread(new Runnable() {
#Override
public void run() {
z=0;
while (z<45){
z++;
handler.post(new Runnable() {
#Override
public void run() {
time.setText(Integer.toString(45-z));
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
this code was working and suddenly a problem occurred . it started to make a delay less than one minute , sumtimes 500 ms and sumtimes less than that
Instead if using a different thread, Thread.sleep(), Handler and while loop you can try only with Handler like this,
private int timerCount = 0;
private static Handler myHandler = new Handler();
private void runVVRunnable() {
myHandler.postDelayed(runnable, 1000);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
timerCount++;
if ((time == null)) {
return;
}
if (timerCount <= 45) {
time.setText(Integer.toString(timerCount));
runVVRunnable();
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacks(runnable);
}
you can just call runVVRunnable() it will do the same process which you are doing while loop
Just a guess but when sleeping/waiting on Java thread you need to try-catch InterruptedException.
This exception is thrown when "someone" calls interrupt() on your thread.
This will cause the thread to wake up from sleep early than expected.
Check if you catch InterruptedException before your thread terminated.

How to update SWT GUI in asyncExec() call

In my SWT GUI, I would like to have a button that kicks off a job and while running that job, update a textbox that will show a log of the events of that job. However, my textbox does not update until the end of my asyncExec() call. In the example below, I would like for my textbox to be updated every second, but instead it gets all of the updates at once after 10 full seconds when it finishes executing.
Is there a way to achieve this?
private void UpdateUI()
{
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run()
{
StringBuilder sb = new StringBuilder();
for(int i=1; i<=10; i++)
{
sb.append("Running iteration " + i + "\n");
txtLogBox.setText(sb.toString());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}});
}
You're sleeping in the UI thread. You need to do your long-running work in a different thread and only post updates to the UI thread using asyncExec. For example:
new Thread(new Runnable() {
public void run()
{
StringBuilder sb = new StringBuilder();
for(int i=1; i<=10; i++)
{
sb.append("Running iteration " + i + "\n");
final String result = sb.toString();
Display.getDisplay().asyncExec(new Runnable() {
public void run()
{
txtLogBox.setText(result);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();

I need to stop thread when progress bar reaches 0 in android

I need stop thread and handler when my progress bar reaches 0 from 100 when thread runs the progress bar reaches but the progressStatus value going in negative please help me to stop thread after progress bar reaches 0
new Thread(runn =new Runnable() {
public void run() {
while (progressStatus <= 100) {
progressStatus += doWork();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
handler.post(runn1=new Runnable() {
public void run() {
bar.setProgress(progressStatus);
i=-1;
if(bar.getProgress()==0)
{
handler.removeCallbacks(runn);
handler.removeCallbacks(runn1);
System.out.println("Reached");
congrats.setVisibility(View.VISIBLE);
restart.setVisibility(View.VISIBLE);
rightbutton.setVisibility(View.GONE);
wrongbutton.setVisibility(View.GONE);
}
}
});
}
}
private int doWork() {
return i;
}
}).start();
your program is not thread safe, you actually reading and writing a variable (progressStatus) from two different threads, you must avoid doing that or if you want to do that you must use synchronized block. In order to solve your problem you can do this way:
Thread t;
progressStatus = 100;
t = new Thread(runn =new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
// Update the progress bar
handler.post(runn1=new Runnable() {
public void run() {
bar.setProgress(progressStatus);
progressStatus=progressStatus-1;
if(bar.getProgress()==0)
{
handler.removeCallbacks(runn);
handler.removeCallbacks(runn1);
System.out.println("Reached");
congrats.setVisibility(View.VISIBLE);
restart.setVisibility(View.VISIBLE);
rightbutton.setVisibility(View.GONE);
wrongbutton.setVisibility(View.GONE);
t.interrupt();
}
}
});
another way that i recommend you is using ScheduledThreadPoolExecutor with the function scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit). something like:
final ScheduledThreadPoolExecutor myTimer = new ScheduledThreadPoolExecutor(1);
myTimer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
getActivity().runOnUiThread(new Runnable(){
#Override
public void run(){
}
});
}
}
}, 0,10, TimeUnit.MILLISECONDS);
and in order to close it use myTimer.shutdownNow();

Updating Thread progress on the Command Line

I'm trying to use threads to show a progress bar on the CLI in java while doing a long operation (generating md5sums for a batch of large files).
I've written a bit of code, and it works, but I'd like to know if I'm using threads correctly as I'm pretty new to this.
I have two class files, ProgressThreadTest.java and CountToABillion.java
CountToABillion.java:
public class CountToABillion implements Runnable {
double count = 0;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
echoCount();
}
}
}
ProgressThreadTest.java:
public class ProgressThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread doCount=new Thread(new CountToABillion());
doCount.start();
}
}
It works as expected and counts upwards on the command line.
Anyone have any comments on whether or not this is a good way to do threads?
Also, because I am updating the progress in the counting loop, it will update every 10ms. How would I change the code to only output the count once every second?
Using javax.swing.Timer is probably the easier solution:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class CountToABillion implements Runnable {
double count = 0;
Timer progressTimer;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
progressTimer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
echoCount();
}
});
progressTimer.setRepeats(true);
progressTimer.start();
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
progressTimer.stop();
}
}
Using java.util.concurrent.ScheduledThreadPoolExecutor is the better and more scalable solution:
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CountToABillion implements Runnable {
double count = 0;
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
Runnable task = new Runnable() {
public void run() {
echoCount();
}
};
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
exec.shutdownNow();
}
}
Option 1:
int sleep = 10; //ms
int echo = 1000; //ms
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((x*sleep % echo) == 0) {
echoCount();
}
}
Option 2:
Create a new Class to manage your counter, it should be able to add, reset and so on. You will have to make sure it's thread safe (writing new values in case you want to update from various threads).
Make one thread that increases the counter in given intervals
Make another thread that polls the current count in other given intervals and print.
long last=0;
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
doWork();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((System.currentTimeMillis()-last)>=1000) //post every second
{
last=System.currentTimeMillis();
echoCount();
}
}
}
This will print the count once every second assuming "work" does not take more than a second.
#Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = i;
if(i % 100 == 0) {
echoCount();
}
}
}
By using i % 100 == 0 you're checking if i is divisible by 100 without rest value. If that's the case, it means that you have ran 100 times 10ms which is 1000ms which is 1s. So you will output your echoCountt() every second.
This is an okay way to use threads. But your thread will keep running until it has counted to 10000000 seconds.
On a sidenote, you should use 'i' instead of 'x' in for loops. It's more widely used like this and will be easier to read for experienced java developers

Categories