I am trying to update a textview after 3 seconds, and i want to do that in a loop for which i am using thread .....what should i do in order to start background thread so that exactly after 3 seconds background1 thread starts ... and it should be done in a loop ?
package com.edu.math;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class EduMath extends Activity {
TextView txt;
TextView tv;
TextView num;
String x;
int time = 3000;
float z ;
int random;
int random1;
int random_operator =1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt=(TextView)findViewById(R.id.txt);
tv = (TextView)findViewById(R.id.randomNumber);
background.start();
}
// our handler
Handler handler = new Handler() {
public void handleMessage(Message msg) {//display each item in a single line
random = (int)Math.ceil(Math.random()*10);
random1 = (int)Math.ceil(Math.random()*10);
if(random1>random)
{
txt.setText(/*txt.getText()+*/""+random1+" "+>+" "+random+" "+
System.getProperty("line.separator"));
}
else
{
txt.setText(/*txt.getText()+*/""+random+" "+>+" "+random1+
System.getProperty("line.separator"));
}
}
};
Handler handler1 = new Handler() {
#Override
public void handleMessage(Message msg) {//display each item in a single line
txt.setText(/*txt.getText()+*/""+random1+" "+x+" "+random+System.getProperty("line.separator"));
}
};
Thread background1 =new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<10;i++)
{
try {
Thread.sleep(time);
// send message to the handler with the current message handler
handler1.sendMessage(handler1.obtainMessage());
background.stop();
Log.d("EduMath-enclosing_method", "thread started");
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
Thread background=new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<10;i++)
{
try {
Thread.sleep(time);
// send message to the handler with the current message handler
handler.sendMessage(handler.obtainMessage());
background1.start();
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
}
You must use AsyncTask for changing any views in layout, but at now I have very little experience with AsyncTask.
Try to use a java.util.Timer ( http://download.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html )
public class HandlerDemo extends Activity {
ProgressBar bar;
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
//add your text
}
};
AtomicBoolean isRunning=new AtomicBoolean(false);
public void onStart() {
super.onStart();
Thread background=new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
handler.sendMessage(handler.obtainMessage());
}
catch (Throwable t) {
// just end the background thread
}
}
});
isRunning.set(true);
background.start();
}
public void onStop() {
super.onStop();
isRunning.set(false);
}
}
Try the solution on this post...seems to be what you looking for http://androidgenuine.com/?p=707
Related
I can't find a none blocking way to invoke my callback method from the main thread as my second thread exits.
I tried to use the loading.isAlive() in a while loop but it freeze the screen.
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.load_opening_screen);
Thread loading = new LoadingBarThread();
loading.start();
}
private class LoadingBarThread extends Thread {
#Override
public void run() {
for (int i=0;i<=100;i++) {
progressBar.setProgress(i);
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void callback(){
// start a new activity for example
}
}
I would like to start a new activity as the ProgressBar reaches 100.
Use a Handler object and at the end of your run() function, post a Runnable to that Handler. Have the Runnable call the callback method. Handler will execute it on the thread its attached to (whatever thread it was created on).
So your new class looks like:
private class LoadingBarThread extends Thread {
Handler handler = new Handler();
#Override
public void run() {
for (int i=0;i<=100;i++) {
progressBar.setProgress(i);
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
handler.post(new Runnable() {
public void run() {
callback();
}
});
}
}
I am updating progress bar with the help of handler of MainActivity
but it gives the error :Can't create handler inside thread that has not called Looper.prepare()
Error
public class MainActivity extends AppCompatActivity {
ProgressBar progressBar;
Handler handler;
Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
thread = new Thread(new MyThread());
thread.start();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
progressBar.setProgress(msg.arg1);
}
};
}
class MyThread implements Runnable {
#Override
public void run() {
Message message = Message.obtain();
for (int i = 0; i < 100; i++) {
message.arg1 = i;
handler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The error is because you are updating your UI from a different thread. So what you should be doing is like call the update method on main ui thread
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do something on UiThread
// update progress
}
});
};
You should run progress bar only on Main Looper.
Add
handler = new Handler(context.getMainLooper()) {
.....
}
Should work.
Can anyone explain when I put the thread to sleep for 30 milliseconds it updates the UI from the background thread. but when I put the sleep for 300 milliseconds it crashes saying that you cannot touch view from another thread. I expect it to crash in both cases but somehow it is working in 30 milliseconds. Needs some clarification on this issue.
public class HandlerDemo extends Activity implements Handler.Callback{
private static final String TAG = "FFFF";
private Handler mHandler = null;
private Handler mUIHandler = null;
private HandlerThread backgroundThread = null;
public static final int BACKGROUND_OPERATION = 10;
public static final int MAIN_THREAD_OPERATION = 20;
private TextView asd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HandlerThread backgroundThread = new HandlerThread("BACKGROUND_THREAD");
backgroundThread.start();
mHandler = new Handler(backgroundThread.getLooper(), this);
mHandler.sendEmptyMessage(BACKGROUND_OPERATION);
// mUIHandler = new Handler(Looper.getMainLooper(), this);
// mUIHandler.sendEmptyMessage(MAIN_THREAD_OPERATION);
}
#Override
protected void onDestroy() {
super.onDestroy();
mHandler.getLooper().quit();
}
#Override
public boolean handleMessage(Message message) {
Log.d(TAG, Thread.currentThread() + "");
switch (message.what) {
case MAIN_THREAD_OPERATION:
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
((TextView) findViewById(R.id.textview)).setText("Updating from UI Handler");
findViewById(R.id.textview).invalidate();
break;
case BACKGROUND_OPERATION:
try {
**Thread.sleep(300);**
} catch (InterruptedException e) {
e.printStackTrace();
}
((TextView) findViewById(R.id.textview)).setText("Updating from background Handler");
findViewById(R.id.textview).invalidate();
break;
default:
break;
}
// message.recycle();
return true;
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
// do what you want
}
});
I am trying to build a short memory game and I want a list of words to be shown.
At the start of the activity, the first word, then every second the next word and after the last word is shown the activity changes without user proc. I have tried some things but the closest I've been is just the last word being shown. Any thoughts?
Java file:
package com.example.pc.myapplication;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.Random;
public class Game1Round1 extends Activity {
String[] round1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game1round1);
round1 = getResources().getStringArray(R.array.round1);
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
updateTextView();
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
Proceed();
}
private void updateTextView() {
int i= 0;
while ( i <13) {
TextView textView = (TextView) findViewById(R.id.randomTextView);
textView.setText(round1[i]);
i = i + 1;
}
}
public void Proceed() {
Intent intent1 = new Intent(this, Game1Start.class);
startActivity(intent1);
}
}
And my strings.xml:
<resources>
<string name="app_name">My Application</string>
<string-array name="round1">
<item>Cinnamon</item>
<item>Apple</item>
<item>Milk</item>
<item>Detergent</item>
<item>Cheese</item>
<item>Shampoo</item>
<item>Butter</item>
<item>Tangerine</item>
<item>Coffee</item>
<item>Marmalade</item>
<item>Cabbage</item>
<item>Meat</item>
<item>Sugar</item>
</string-array>
delete the updateTextView() method and change your Thread like this
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted() && i < 12) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView)findViewById(R.id.randomTextView)).setText(round1[i]);
i++;
}
});
}
Proceed();
} catch (InterruptedException e) {
}
}
};
t.start();
In your run() method after try, catch use finally and put proceed() method in that like below
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
updateTextView();
}
});
}
} catch (InterruptedException e) {
}
finally{ Proceed(); }
}
};
then you should start the thread
t.start();
Hope this solves your issue
You can use this:
textView.postDelayed(new Runnable() {
#Override
public void run() {
lastCommentText.setText(...);
}
}, 1000);
I would like to write a real time counter. I tried to use thread, but android warned me that only activity thread may touch the view. I found a solution with runOnUiThread, but it does not work too
public class CounterInRealTimeExampleActivity extends Activity {
private TextView textView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
textView = new TextView(this);
textView.setTag(new Integer(0));
layout.addView(textView);
setContentView(layout);
runOnUiThread(new Runnable() {
#Override
public void run() {
//while(true)
{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
increment();
}
}
});
}
public void increment() {
textView.setTag(new Integer((Integer)textView.getTag())+1);
textView.setText(Integer.toString((Integer)textView.getTag()));
}
}
i am pasting code here. may this help you..
class UpdateTimeTask extends TimerTask {
public void run() {
String time = DateUtils.now("hh:mm:ss'T'a");
String[]arrValues = time.split("T");
if(arrValues.length>0) {
String strValue= arrValues[0];
String []arrTimeValues = strValue.split(":");
String strValue1= arrTimeValues[2];
setTimertext(strValue1);
}
}
public void setTimertext(String strValue) {
runOnUiThread(new Runnable() {
public void run() {
FinalTime=timer_time--;
btnTimer.setText(String.valueOf(FinalTime));
}
});
}
}
Thread.sleep(3000);
is definitely a problem. You aren't allowed to block the UI-thread, which is exactly what sleep does. You have to execute the code to update the UI from within runOnUiThread solely.
working one, found solution after Hasmukh tip
package com.android.examples;
import java.util.Calendar;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CounterInRealTimeExampleActivity extends Activity {
private TextView textView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
textView = new TextView(this);
layout.addView(textView);
setContentView(layout);
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
updateTime();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
private void updateTime() {
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(Integer.toString((int) (Calendar.getInstance()
.getTimeInMillis() / 1000) % 60));
}
});
}
}