Thread in Android ---> Unfortunately ThreadApp has Stopped - android

I have one textview, which i can use to show countdown timer. I wanted to use Thread class which takes Runnable interface.
I wrote the following code for the same but it is gives run time error Unfortunately ThreadApp has Stopped
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity implements Runnable
{
TextView tvTimer;
Thread timerThread;
int time=30;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTimer =(TextView)findViewById(R.id.textView1);
timerThread= new Thread(this);
timerThread.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void run()
{
try
{
Thread.sleep(1000);
tvTimer.setText((String.valueOf(time)).toString());
time--;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
At the same time when i removed tvTimer.setText((String.valueOf(time)).toString()); it works fine. Can anyone provide me the solution. I am new in android.

You can use updating UI using RunOnUiThread like this
#Override
public void run()
{
try
{
Thread.sleep(1000);
runOnUiThread(new Runnable() {
public void run() {
tvTimer.setText((String.valueOf(time)).toString());
}
});
time--;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

when i removed tvTimer.setText((String.valueOf(time)).toString()); it
works fine
because you are trying to change TextView text from non-ui Thread so use runOnUiThread or Handler for updating TextView from other Thread

new Thread(new Runnable() {
#Override
public void run() {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
public void run() {
tvTimer.setText((String.valueOf(time)).toString());
time--;
}
});
}

You are trying to update ui in timer task. Timer task runs on a different thread. update ui on the ui thread. Use a handler or runonuithread
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
tvTimer.setText((String.valueOf(time)).toString());
timer--;
// do something
m_handler.postDelayed(m_handlerTask, 1000); // instad of 1000 mention the delay in milliseconds
}
};
m_handlerTask.run();
Or use
#Override
public void run()
{
try
{
Thread.sleep(1000);
// should not call thread.sleep() bad design
// check the edit below
runOnUiThread(new Runnable(){
#Override
public void run(){
//update ui here
tvTimer.setText((String.valueOf(time)).toString());
}
});
time--;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Edit: Using Thread.sleep() inside a thread is a bad design.
http://developer.android.com/training/articles/perf-anr.html
Quoting from the docs.
If you implement Thread or HandlerThread, be sure that your UI thread does not block while waiting for the worker thread to complete—do not call Thread.wait() or Thread.sleep(). Instead of blocking while waiting for a worker thread to complete, your main thread should provide a Handler for the other threads to post back to upon completion. Designing your application in this way will allow your app's UI thread to remain responsive to input and thus avoid ANR dialogs caused by the 5 second input event timeout.
To stops use this m_handler.removeCallbacks(m_handlerTask);

You are trying to update the UI element i.e., a TextView in your thread. You can't do this in a thread. Instead use a handler to post changes to your UI element as follows -
Handler handler = new Handler();
#Override
public void run()
{
try
{
Thread.sleep(1000);
handler.post(new Runnable()
{
public void run()
{
tvTimer.setText((String.valueOf(time)).toString());
}
time--;
});
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Related

Spinner Progressbar in android

I want to implement ProgressBar in Android and when I execute the program, Progressbar should show for up to 2 seconds. I can't get it to work properly but I can't figure out why.
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
while(mRunning)
{
Thread.sleep(10L);//10s wait
YourCurrentActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//DISMISS PROGRESS BAR HERE
mRunning=false;
}
});
}
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
I have tried this but it does not giving me output as i want.
That what handlers are for in Android.
Example:
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
// cancel or dismiss your progressbar
}
}, 2000);

Button does not disappear again when the layout is touched

final Thread timer = new Thread(){
public void run (){
try{
//sleep
sleep (2000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
nav2.setAnimation(alpha2);
nav2.setVisibility(View.INVISIBLE);
}
}
};
timer.start();
nav1.setOnClickListener(new LinearLayout.OnClickListener(){
#Override
public void onClick(View arg0) {
nav2.setVisibility(View.VISIBLE);
nav2.setAnimation(inleft);
timer.start();
}});
I have a code that will make button or linearlayout disappear after 2 secs in the timer the problem is that it crashes once the finally executes. Also the other button (nav1) is the whole linear layout so once it had been touched the nav2 or the buttons will appear and the timer will again reset
Generally, you can't touch your UI widgets from a background thread.
For your use case, consider a Handler on the UI thread and a Runnable posted with postDelayed().
try this instead of thread,
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
nav2.setAnimation(alpha2);
nav2.setVisibility(View.INVISIBLE);
} catch (Throwable e) {
e.printStackTrace();
}
}
}, 2000);

Is there a way I can put some delay in setcontentView in android?

I have a SetContentView(R.layout.camera);
I want this layout to be start executing after some milliseconds....till then it should be blank. How can I achieve this in android?
For this Write your onCreate() like this..Then it will work..
Thread t = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
t = new Thread(new Runnable() {
#Override
public void run() {
try {
t.sleep(5000);
runOnUiThread(new Runnable() {
public void run() {
setContentView(R.layout.activity_main);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
}
you can use handler for make delay
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//setcontentview
}
};
in oncreate methode
Message m = Message.obtainMessage();
handler.sendMessageDelayed(m, delayMillis);
Your activity will not be visible unless onResume() will get called, Do some operation in main Thread or onCreate() Method it will block your main thread and UI will not be displayed until your operation gets completed.
Create root View with all the components and visibility set to INVISIBLE or GONE and then show it after delay. You can use Handler and postDelayed to execute a code after delay.

Updating UI using a Handler freezes my app

I am trying to make a clock, using a TextView :)
Someone here told me that I couldn't use normal threads to change the UI, but Handler or AsyncTask. I managed to get it working a few days ago, but was not a consistent thread.
Now what I want is a consistent thread that is always changing the text of my Textview. I tried using this, but didn't work, any help?
private void startClock() {
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
while (true) {
final long millis = System.currentTimeMillis() - MainActivity.startedAt;
clock.setText("" + millis);
runOnUiThread (new Runnable() {
#Override
public void run() {
clock.setText("" + millis);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, 2000);
}
you should get rid of:
while(true) {
....
sleep(1000);
...
}
because this get your thread stuck forever. your program should work like this:
private Handler mHandler = new Handler();
#Override
public void onResume() {
super.onResume();
mHandler.removeCallbacks(mUpdateClockTask);
mHandler.postDelayed(mUpdateCLockTask, 100);
}
#Override
public void onPause() {
super.onPause();
mHandler.removeCallbacks(mUpdateClockTask);
}
private Runnable mUpdateClockTask = new Runnable() {
public void run() {
updateClock();
mHandler.postDelayed(mUpdateClockTask, 2000);
}
};
and inside updateClock() you do all your UI updates.
Look here for an example https://stackoverflow.com/a/11140429/808940
Also note that you have a duplicate line in your code:
clock.setText(""+millis);
It appears both in the runOnUiThread and in the main handler, it should only appear in the runOnUiThread runnable

Android thread problem

I just want to continously update text in an android app. However my App crashes every time.
This is my code:
package org.pgvw.main;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class InertialView extends Activity {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
tv.setText("Time: ");
new Thread(new Runnable() {
public void run() {
while(true) {
try {
Thread.currentThread().sleep(100);
tv.setText("Time: " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
setContentView(tv);
}
}
Can anyone spot the mistake?
Greetings and thx!
Consider that you do not need to launch any additional threads to update the UI every x milliseconds. The additional overhead of an added thread is justified IF you have a time intensive task. In the following example the timer is launched on a button click. Note that this code does not create a new thread.
private Handler myHandler= new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
if (!isDoneThinking){
editTextConfusedText.setText("Still Thinking "+new Integer(thinkSeconds).toString());
thinkSeconds++;
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0),1000); // <== Loop on delayed messages every second
}
else {
thinkSeconds= 0; // reset timer
}
break;
default:
super.handleMessage(msg);
break;
}
}
};
We launch the timer in onClick. We simply send an empty message with a what value of "0".
buttonConfuseText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
isDoneThinking= false;
myHandler.sendEmptyMessage(0); <== starts timer with what value of "0"
}
};
The timer is unconstrained and will continue to count until the flag isDoneThinking is set to true.
You cannot update GUI from another thread. You can use runOnUiThread or handler to update the GUI.
for example:
new Thread(new Runnable() {
public void run() {
while(true) {
try {
Thread.currentThread().sleep(100);
runOnUiThread(new Runnable() {
public void run() {
tv.setText("Time: " + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
BTW - The use of Thread.currentThread().sleep(100); can be shorted to Thread.sleep(100) since it's a static method. see Jon Skeet's answer regarding that
Or use AsyncTask. It was designed to do background tasks and properly update the UI. Your design will be more scalable this way.

Categories

Resources