I was trying to run a small worker thread in the middle of an activity which would get some stuff from a web service and fill a container when it returned.
new Thread() {
#Override
public void run() {
Log.w("thread", "can read from thread");
try {
MyActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.w("internal thread", "running");
}
});
}
catch (Exception e) {
// etc
}
}
}.start();
The "internal thread: running" would never print in the log, and when I ripped out the contents and just pasted it into the main body of the method, it worked. My conclusion is that the doubly nested thread never ran. Why would that happen? Am I misusing runOnUiThread?
Thanks!
Why would that happen? Am I misusing runOnUiThread?
Yeas ! runOnUiThread is other thread than Main thread. i suggest to have a look at Android Handler.
Related
I am trying to review the concept of Handler. So I simply create a Thread to update a ProgressBar and see if it would throw an exception.
Here's my code
#Override
public void onResume() {
super.onResume();
new Thread(){
#Override
public void run() {
super.run();
while (progressBar.getProgress() <100){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.setProgress(pb.getProgress()+10);
}
}
}.start();
}
My question is simple. Why it doesn't throw any CalledFromWrongThreadException?
If it meant to be this way, should we forget about Handler when we deal with progress updating?
https://cs.android.com/android/platform/superproject/+/android-10.0.0_r30:frameworks/base/core/java/android/widget/ProgressBar.java;l=1610
Bad luck--ProgressBar has special support for updating its progress from another thread. That's why it doesn't throw something.
But because it's so specifically this operation that has this extra support, no to the second question. You wouldn't, in general, stop using a handler. For cases where, for example, you need to do one other little UI thing while updating the progress.
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'm calling methode doSomething() continuously with a thread.sleep(100). This happens in on the UIThread, so the UIthread gets unresponsive. What is the correct way in Android to run the method doSomething() or the entire someobject in a seperate thread?
public void loop(){
while(true){
someObject.doSomething();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right now i'm using
new Thread(new Runnable() {
#Override
public void run() {
someObject.doSomething();
}
}).start();
This obviously creates a different thread for each iteration. I don't think this is the correct way. What is the correct way in Android?
new Thread(new Runnable() {
#Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
someObject.doSomething();
}
}
}).start();
Since run never returns, the thread will never end and will loop forever. It will call doSomething roughly every 100 ms (as close as sleep will get, which isn't exact).
You can make your own Thread class, with Looper and Handler, posting your doSomething every 100ms:
public class MyThread extends Thread{
private Handler myHandler;
#Override
public void run(){
Looper.prepare();
myHandler = new Handler();
myHandler.post(doSomethingRunnable);
}
Runnable doSomethingRunnable = new Runnnable{
doSomething(); //or myHandler.postDelayed() first for greater accuracy, but only if doSomething doesnt take too long
myHandler.postDelayed(doSomethingRunnable, 100);
};
doSomething(){
thisStuff(thatStuff());
}
}
You can use AsyncTask. doInBackground() is called on a background thread and will not block UI. This is the preferred way for doing stuff on background threads.
For a long running task. You can use an IntentService and put your background code in onHandleIntent
You can use a basic thread but it may be hard to manage. You can read more about threads in android here
I am getting this error, and my application crashes:
java.lang.IllegalStateException: The current thread must have a looper!
I didn't get much about how to use looper on Google, I am using threads(mainly for sleep function), handler(for downloading the image while Async task is running) and Async task(for getting the JSON data from the URL). I have no idea how to resolve this issue, so any suggestions will be vey helpful.
This is the code for the thread which is executed on click of the button:
View view = flingContainer.getSelectedView();
view.findViewById(R.id.item_swipe_right_indicator).setAlpha((float) 1.0);
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
flingContainer.getTopCardListener().selectLeft();
}
}
};
timer.start();
I am using this libray and log-cat is:
where: at com.enormous.quotesgram.MainActivity$3.run(MainActivity.java:479) in last in log-cat corresponds to the line: flingContainer.getTopCardListener().selectLeft(); in above piece of code.
Try the following (unfortunately I cannot test the code):
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
runOnUiThread(new Runnable() {
#Override
public void run() {
flingContainer.getTopCardListener().selectLeft();
}
});
}
}
};
The idea behind is, that the Timer thread is not a Looper thread (resulting in an exception saying "The current thread must have a looper"). The UI thread however, is a Looper thread (see for instance this site).
As flingContainer.getTopCardListener().selectLeft() is probably designed to run on the UI thread it fails, if it not invoked in side of a pipelined thread.
I wants to create a custome Input Method with word suggestions from a webservice in an asynchronous way. If it is not asysnchronouse , phone get stuck while connecting to internet. If I use Thread it cause an excpetion "ui can be touch only by the tread created ". I don't know runOnUIthread can be used or how. I understood that runOnUiThread activity method. Anybody please help. I used android Example app softkeybord.
I'm not sure I understand,
If the definition of the Thread is inside the Activity,
You can just call:
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();