Can I use a thread for increment a counter and shows it in a frame of Android activity.
Public class MainActivity extendsActivity {
TextView counter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
counter = (TextView) findViewById(R.id.TV_counter);
Thread t = new Thread() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
counter.setText("" + i);
System.out.println("Value of i= " + i);
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
};
t.start();
}
}
I wrote this code, but it run properly in console, but the text view displays i=4 in the terminal, I modified the time to sleep(3000) and the problem persists.
First you don't ever want to put sleep in UI Thread that can lead to unresponsive user interface and that is never good. You should use it just to update your graphics. Try replacing your code with this
Thread t = new Thread() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
final int a = i;
runOnUiThread(new Runnable() {
public void run() {
counter.setText("" + a);
}
});
System.out.println("Value of i= " + i);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
You are going to notice that sleep and for loop is outside UIThread and in your first thread, so basically all of your math is done outside and you just display the results.
This is just a correction of your code and suggestion for further thinking
EDIT: And for you to better understand why your code is not working, you set some value on your TextView, and immediately after you set UIThread to sleep, UIThread blocks instead of giving it time to finish updating graphics, after he finish sleep you set new value, and he never got to update previous one so in the end you see just the last one.
Hope this helps and enjoy your work.
you can use a CountDownTimer, and update your UI in the onTick() method ( this method is executed on the UI Thread):
int i=0;
CountDownTimer timer = new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
// this method will be executed every second ( 1000 ms : the second parameter in the CountDownTimer constructor)
i++;
txt.setText(i);
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
};
timer.start();
Related
i am trying to display a Toast on the screen and when Toast fades off then move to the next question. I have tried with Thread but cannot seem to manage.
My code:
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getUserSelection()){
position = position + 3;
if (position < questionsArray.size()) {
curName = questionsArray.get(position).getName();
curArray = questionsArray.get(position).getAnswers();
curIscorrect = questionsArray.get(position).getIscorrect();
setupQuestionView(curName, curArray, curIscorrect);
} else {
StringGenerator.showToast(QuestionsActivity.this, "Your score : " + score + "/" + (questionsArray.size() / 3));
}
}else {
StringGenerator.showToast(QuestionsActivity.this, getString(R.string.noanswerselected));
}
}
});
and the getUserSelectionMethod:
private boolean getUserSelection() {
correct = (RadioButton)findViewById(group.getCheckedRadioButtonId());
if (correct == null){
return false;
}else {
correctAnswerText = correct.getText().toString();
if (map.get(correctAnswerText).equals(Constants.CORRECTANSWER)) {
score++;
setCorrectMessage();
return true;
} else {
setWrongMessage();
return true;
}
}
}
private void setCorrectMessage() {
correctToast = new Toast(QuestionsActivity.this);
correctToastView = getLayoutInflater().inflate(R.layout.correct, (ViewGroup) findViewById(R.id.correctRootLayout));
correctText = (TextView)correctToastView.findViewById(R.id.correctTextView);
correctText.setText(getString(R.string.correctAnswer));
correctToast.setDuration(Toast.LENGTH_SHORT);
correctToast.setView(correctToastView);
correctToast.show();
correctThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
correctToast.cancel();
}
});
correctThread.start();
}
private void setWrongMessage() {
wrongToast = new Toast(QuestionsActivity.this);
wrongToastView = getLayoutInflater().inflate(R.layout.wrong, (ViewGroup) findViewById(R.id.wrongRootLayout));
wrongText = (TextView)wrongToastView.findViewById(R.id.wrongTextView);
wrongText.setText(getString(R.string.wrongAnswer));
wrongToast.setDuration(Toast.LENGTH_SHORT);
wrongToast.setView(wrongToastView);
wrongToast.show();
wrongThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
wrongToast.cancel();
}
});
wrongThread.start();
}
Any suggestion on how to do this?
You can determine the toast visibility:
toast.getView().getWindowToken()
If the result is null, than your toast isn't visible anymore, and than you can run any code you want.
as stated in this answer you can start a thread that waits the duration of the Toast:
Thread thread = new Thread(){
#Override
public void run() {
try {
Thread.sleep(3500); // 3.5seconds!
// Do the stuff you want to be done after the Toast disappeared
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Toast.LENGTH_SHORT and Toast.LENGTH_LONG are only flags so you have to either hard code the duration or keep them in a constant. The durations are 3.5s (long) and 2s (short).
If you want to manipulate some of your views, you cannot do this in another thread than the "main" UI thread. So you have to implement a kind of callback/polling mechanism to get notified when the SleepThread has finished.
Check this answer to read about a couple of ways to do this. Probably the easiest of them to understand and implement is this:
After you started your Thread you can check if it is still alive and running by calling thread.isAlive(). In this way you can do a while loop that runs while the thread is running:
// start your thread
while(thread.isAlive()){}
// continue the work. The other thread has finished.
Please note that this is NOT the most elegant way to do this! Check the other possibilities in the answer I've mentioned above for more elegant solutions (especially the last one with the listeners is very interesting and worth reading!)
That's because the Thread class is purely executed in the background and you need to manipulate the view in the Main thread. To solve your issue just replace the Thread with AsynTask.
AsyncTask<Void,Void,Void> a = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
correctToast.cancel();
}
};
a.execute();
If you look at my code you can see my onPostExecute, this method is called in the Main Thread.
My Error was because i was trying to acess UI Elements through another Thread so modifying the code like this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
QuestionsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
moveToNextQuestion();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
did the trick. I hope my answer helps someone!!!
Suppose that I have 10 text views in my layout. I want to change their background one by one with a small delay between each operation. Here's a sample code:
public void test(){
for (int i=0 ; i < 10 ; i++){
myTextViews[i].setBackgroundResource(R.color.red);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
The problem is that during the time of running this function main thread blocks and backgrounds don't change. They change all together when the program finishes running the function. What should I do if I want the user to see each background is changed at the correct time and then next one...?
When you call Thread.sleep(), the thread you are actually blocking is the UI thread, which is why you're seeing a hang-up. What you need to do is start up another Thread to handle the sleeps, or delays, that you want, and then utilize the runOnUiThread method
Try this:
public void test() {
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//anything related to the UI must be done
//on the UI thread, not this thread we just created
runOnUiThread(new Runnable() {
public void run() {
myTextViews[i].setBackgroundResource(R.color.red);
}
});
}
}
}).start();
}
i want to start Asynchoronous task after some sleep time. For that i am using thread and i start my asynchronous task in that thread finally block. But it gives cant create a handler inside a thread exception.
i am using the following logic.
thread= new Thread()
{
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
Load ld=new Load();
ld.execute();
}
}
};
thread.start();
Well, first of all, if the final goal is to run AsyncTask after some delay, I would use Handler.postDelayed instead of creating separate Thread and sleeping there:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
new Load().execute();
}
}, 300); //300ms timeout
But, if you really wanna make fun of Android, you can create HandlerThread - special thread which has looper in it, so your AsyncTask will not be complaining anymore:
thread= new HandlerThread("my_thread")
{
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
Load ld=new Load();
ld.execute();
}
}
};
thread.start();
Please note that you are responsible for calling quit() on this thread. Also I'm not sure what happens if you quit this thread before AsyncTask is done. I don't remember where AsyncTask posts its results - to the main thread, or to the thread it was called from...
In any case, second option is just a mess, so don't do it:) Use the first one
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Do whatever you want.
}
}, SPLASH_TIME_OUT);
}
You can use like above. there SPLASH_TIME_OUT is the millisecond value that u want to make a delay.
Use Handler class, and define Runnable YourAsyncTask that will contain code executed after sleepTime
mHandler.postDelayed(YourAsyncTask, sleepTime);
You must run AsyncTask in UI thread, so you can use something like this:
class YourThread extends Thread{
private Activity _activity;
public YourThread(Activity _activity){
this activity = _activity;}
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Load ld=new Load();
ld.execute();
}
});
}
}
}
and in your activity call thread like this:
YourThread thread = new YourThread(this);
thread.start();
also note: use soft reference to activity or do not forget kill thred when activity will be destroyed.
just do your like below code:
define a thread globally.
public static Thread thread;
thread= new Thread() {
public void run() {
sleep(time);
Message msg = setTextHandler.obtainMessage(2);
setTextHandler.sendMessage(msg);
}
};
thread.start();
and your handler look like
private final Handler setTextHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (thread!= null) {
thread.interrupt();
thread= null;
}
switch (msg.what) {
case 2: //do your work here
Load ld=new Load();
ld.execute();
break;
}
}
};
I am trying to make view of random text 3 times with time pausing between.
I just can't! It all run all together. I admit I don't know thread subject at all, I just need simple solution.
public void loading3() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result.setText(temp + "%");
}
This is the code. I want to use it let's say 3-4 times in a row. How can i do it? I try inside loop or writing same methods in a row but it won't work because it doesn't wait for the first method to end before start the new one.
You should not sleep on the main thread. This can easily be done with a Handler or Timer. Here is an example with a Handler:
private int mCount = 0;
private Handler mHandler = new Handler();
private Runnable mUpdater = new Runnable() {
public void run() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
result.setText(temp + "%");
mCount++;
if (mCount < 3)
mHandler.postDelayed(mUpdater, 1000);
}
}
public void loading3() {
mHandler.postDelayed(mUpdater, 1000);
}
I want to have my runnable undate my UI every .75 second, I don't want to use AnsyTask. But the TextView is only set at the end of the for loop, any idea why?
...
robotWords = "........Hey hello user!!!";
wordSize = robotWords.length();
mHandler.postDelayed(r, 750);
}
private Runnable r = new Runnable()
{
public void run()
{
for(int i=0; i<wordSize; i++)
{
robotTextView.setText("why this words only display on the textView at last operation on this for loop?");
Log.i(TAG, robotWords.substring(0, i));
try
{
Thread.sleep(750);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
The TextView is only set at the end of the for loop because of this line Thread.sleep(750);
Your thread will sleep before the text is really set to your textview. I think you should call Handler.postDelayed every 750ms instead of using Thread.sleep(750); or use a CountDownTimer
new CountDownTimer(750 * wordSize, 750) {
public void onTick(long millisUntilFinished) {
robotTextView.setText("why this words only display on the textView at last operation on this for loop?");
Log.i(TAG, robotWords.substring(0, i));
}
public void onFinish() {
}
}.start();
You shouldn't be making calls to the UI thread from another thread.
use CountDownTimer
new CountDownTimer(wordSize*750, 750) {
public void onTick(long millisUntilFinished) {
robotTextView.setText("...");
}
public void onFinish() {
}
}.start();
Try this, call "doStuff()" when you want the operation to take place
public void doStuff() {
new Thread(new Runnable() {
public void run() {
for(int i=0; i<wordSize; i++) {
robotTextView.setText("why this words only display on the textView at last operation on this for loop?");
Log.i(TAG, robotWords.substring(0, i));
robotTextView.post(new Runnable() {
public void run() {
robotTextView.setText("why this words only display on the textView at last operation on this for loop?");
}
});
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
Hope this helps!