I am new to android, don't have much experience to manage threads. I am working on an activity where I want to display progress bar for say 5 seconds and then repeat. During those 5 seconds, I will display some text for the user to work on the text. I want to repeat this for say N times.
Currently, I have the following code that works for 1 such progress. I tried looping it but it didn't help, as threads executed at same time. How can I repeat this for N number of times? Am I on the correct path in order to solve my the problem?
public class test extends Activity {
private ProgressBar progressBar;
private int progressStatus = 0;
private TextView textView;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loop);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
textView = (TextView) findViewById(R.id.textView1);
progressBar.setScaleY(3f);
// Start long running operation in a background thread
for(int i=0; i<5; i++)
Progress();
}
public void Progress(){
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
I am not sure I would recommend using the pattern you are following but here is the way to get the threads to run one after another rather than all at the same time:
public void progress(final int numberOfRuns) {
if (numberOfRuns <= 0 ) {
return;
}
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus + "/" + progressBar.getMax());
// For the UI Changes. Eg update the loop number
myTextView.setText(Integer.toString(totalLoop));
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progressStatus = 0;
totalLoop = totalLoop+1;
progress(numberOfRuns - 1);
}
}).start();
}
then just call progress(numberOfRuns), no need for any loops.
Related
In one activity of my app, there are an imagview and a textview that are changing every 3 seconds.
I first set this up with a handler and thread runnable. It works fine, but when I use removeCallbacks with the pause button, it will not pause in the middle of the Thread. It completes the Thread runnable before pausing. I need it to pause when the button is clicked no matter where it is in the runnable.
I thought about using an asynctask but I'm not sure how this would work.
I know there has to be a way to do this, as you can pause almost any game you download. Does anyone have any suggestions on the best/easiest way to do this?
Thanks so much!! :)
public class Workout extends AppCompatActivity {
private String[] messages = {"1", "2", "3", "4", "5"};
final Handler handler = new Handler();
private int nextIndex;
String mDrawableName[] = {"bodypart70", "equipment70", "settings70", "time70", "bodypart70"};
private int nextImage;
ImageView image;
private ProgressBar progressBar;
private int progressStatus = 0;
Runnable r = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout);
image = (ImageView) findViewById(R.id.exerciseImage);
final TextView text = (TextView)findViewById(R.id.textView4);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
//changing
r = new Runnable(){
#Override
public void run(){
if (messages.length > nextIndex) {
//change textview
text.setText(messages[nextIndex++]);
//change image
int resID = getResources().getIdentifier(mDrawableName[nextImage++] , "drawable", getPackageName());
image.setImageResource(resID);
//restart progress bar
progressStatus = 0;
progress();
//do it after 3 seconds
handler.postDelayed(this, 3000);
}
}
};
handler.postDelayed(r, 0);
}
public void progress(){
new Thread(new Runnable() {
public void run() {
long timerEnd = System.currentTimeMillis() + 3 * 1000;
while (timerEnd > System.currentTimeMillis()) {
progressStatus = 3 - (int) (timerEnd - System.currentTimeMillis()) / 1000;
// Update the progress bar
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
}
});
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w("App", "Progress thread cannot sleep");
}
}
}
}).start();
}
public void pauseWorkout(View view){
handler.removeCallbacks(r);
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
}
}
It looks like the while-loop in your progress() function is still working after you press your pause button.
Try the following: Create a global boolean that indicates you're in a paused or resuming state. Put it at the top of your code:
boolean resume = true;
Update your while condition in progress()
while (resume && timerEnd > System.currentTimeMillis()) {
Update your workout functions:
public void pauseWorkout(View view){
handler.removeCallbacks(r);
resume = false;
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
resume = true;
}
First, I used animation to hide and show TextView. I saw that using animation costing memory. So I used another way:
SetVisibility(VISIBLE) and SetVisibility(INVISIBLE) with TaskTimer
it works well and it performs better considering the memory.
The main issue is that after a restarting the timer for many times, the TextView disappear.
I need to restart the app to get it back again!
this is the code snippet:
myTimerForAnimation = new Timer();
myTimerForAnimation.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() // run on ui thread
{
public void run() {
counter++;
if (counter < 7) {
if (counter % 2 == 1) {
list_textView[x].setVisibility(View.INVISIBLE);
} else {
list_textView[x].setVisibility(View.VISIBLE);
}
} else {
myTimerForAnimation.cancel();
myTimerForAnimation.purge();
list_textView[x].setVisibility(View.VISIBLE);
}
}
});
}
}, 1000, 600);
Dont use Timer use handler,something like this:
// init the runnables
// the runnable should be members
Handler hanlder = new Handler();//If you arent on the UI thread pass a correct looper
for (int i=1; i<7 ; i++){
long delay = i * 1000;
if (i%2==0)
{
handler.postDelayed(mVisibleRunnable,delay);
}else{
handler.postDelayed(mInVisibleRunnable,delay);
}
}
Whereas the get runnablebs should be memebers because if u choose to cancel the callbacks then call
handler.removeCallbacks(runnable);
Play with it. It should fix your issue.
thanks to #EE66 for the loop idea, I used this code to solve my problem:
private void animateView(final View view){
for (int counter = 0; counter < 7; counter++) {
long delay = counter * 1000;
if (counter % 2 == 0) {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.VISIBLE);
}
;
}, delay);
} else {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.INVISIBLE);
}
;
}, delay);
}
}
}
I'm a "fresh" Android developer and i tried the horizontal ProgressBar.
I have a little issue with it, progress stops in the middle and does not continue till the end of the bar.
Can you help me please?
this is my code
progress=0;
mProgress = (ProgressBar) findViewById(R.id.progressBar1);
mProgress.setMax(200);
// Start lengthy operation in a background thread
new Thread(new Runnable()
{
public void run()
{
while (mProgressStatus < 100)
{
mProgressStatus = doWork();
// Update the progress bar
mHandler.post(new Runnable()
{
public void run()
{
mProgress.incrementProgressBy(20);
mProgress.setProgress(mProgressStatus);
}
});
}
// Cache la progressBar
mHandler.post(new Runnable()
{
#Override
public void run()
{
mProgress.setVisibility(4);
}
});
}
//---------------------------------Work to do-----------------------
private int doWork()
{
try{
Thread.sleep(50);//5 secondes
}catch(InterruptedException e)
{
e.printStackTrace();
}
return ++progress;
}
//------------------------------------------------------------------
}).start();
}
You set the progress bar maximum value to 200:
mProgress.setMax(200);
and later in code you stop when it raises to 100 (half filled). Either set the maximum to 100 or keep running till 200.
I use this Tutorial to create custom Progressbar and it works .
But I want to start new activity when progress bar go to 100% .
anyone can help to put start new activity code in correct place?
You can check if the progress has reached the maximum possible while you're setting it, like this:
#Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
// the setProgress super will not change the details of the progress bar
// anymore so we need to force an update to redraw the progress bar
invalidate();
if(progress >= getMax()) {
Intent intent....
}
}
You can call the onContinue function timer thread and set the intent to next activity and register the activity name in manifest file.
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
mProgressBar = (ProgressBar)findViewById(R.id.adprogress_progressBar);
final Thread timerThread = new Thread() {
#Override
public void run() {
mbActive = true;
try {
int waited = 0;
while(mbActive && (waited < TIMER_RUNTIME)) {
sleep(200);
if(mbActive) {
waited += 200;
updateProgress(waited);
}
}
} catch(InterruptedException e) {
} finally {
onContinue();
}
}
};
timerThread.start();
}
#Override
public void onDestroy() {
super.onDestroy();
}
public void updateProgress(final int timePassed) {
if(null != mProgressBar) {
final int progress = mProgressBar.getMax() * timePassed / TIMER_RUNTIME;
mProgressBar.setProgress(progress);
}
}
public void onContinue() {
Intent intd=new Intent(this,MainActivity.class);
startActivity(intd);
}
Try this...
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 5;
// Update the progress bar and display the current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText("Loading "+progressStatus+"/"+progressBar.getMax());
}
});
try {
// Sleep for 200 milliseconds. Just to display the progress slowly
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
**Intent intent = new Intent(Main_Activity.this, Send_Email.class);
startActivity(intent);**
}
}).start();
I have a few Buttons that I want to appear randomly and then disappear after a few seconds. I would also like them to be clickable when they are visible if that changes anything.
Here's what I have:
public void fight() throws InterruptedException
{
Random g = new Random();
int move;
for(int i = 0; i <= 3; i++)
{
move = g.nextInt(8);
buttons[move].setVisibility(View.VISIBLE);
buttons[move].setClickable(true);
try{ Thread.sleep(5000); }catch(InterruptedException e){ }
buttons[move].setVisibility(View.GONE);
buttons[move].setClickable(false);
}
}
When I try that though, the whole thing just freezes for 20 seconds (presumably 5 seconds for each time through the loop and nothing happens. Any ideas?
Thanks.
Try this
public void fight() throws InterruptedException
{
Random g = new Random();
int move;
runOnUiThread(new Runnable()
{
public void run() {
while(makeACondition) {
move = g.nextInt(8);
buttons[move].setVisibility(View.VISIBLE);
buttons[move].setClickable(true);
if (System.currentTimeMillis() % 5000 == 0) {
buttons[move].setVisibility(View.GONE);
buttons[move].setClickable(false);
}
}
}
}
}
private Handler mMessageHandler = new Handler();
Random g = new Random();
int move;
private Runnable mUpdaterRunnable = new Runnable() {
public void run() {
// hide current button
buttons[move].setVisibility(View.INVISIBLE);
// set next button
move = g.nextInt(8);
// show next button
buttons[move].setVisibility(View.VISIBLE);
// repeat after 5 seconds
mMessageHandler.postDelayed(mUpdaterRunnable, 5000);
}
};
To start, use move = g.nextInt(8); (to avoid the null) and mMessageHandler.post(mUpdaterRunnable);.
To stop, mMessageHandler.removeCallbacks(mUpdaterRunnable);.
You could also achieve this using Timer with TimerTasks, as xbonez said.
have you tried this way ?
private int move;
public void fight() throws InterruptedException
{
final Random g = new Random();
runOnUiThread(new Runnable()
{
public void run() {
while(makeACondition) {
move = g.nextInt(8);
toggleButtonState(buttons[move]);
}
}
});
}
private void toggleButtonState(final Button button)
{
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(button.isEnabled())
button.setVisibility(View.GONE);
else
button.setVisibility(View.VISIBLE);
}
}, 5000);
}