I have a button in my activity. When I press it, following method "ProcessNumbers()" is called. I need the functionality that "Processing..." text should be displayed in the textview first, then the loop should get processed, and when the loop finishes after 2-3 seconds, the textview should show "Processed" text. But this is not happening. When I click the button, loop runs first and after 2-3 seconds, the textview contains "Processed". Why the first step is missing where textview should contain "Processing..."?
private void ProcessNumbers()
{
TextView textViewProcessNumbers = (TextView) findViewById(R.id.textViewProcessNumbers);
textViewProcessNumbers.setText("Processing...");
int k = 0;
for (long i = 0; i <= 1000000000; i++)
{
k = 1;
}
textViewProcessNumbers.setText("Processed...");
}
Am I missing something here?
private void ProcessNumbers()
{
TextView textViewProcessNumbers = (TextView) findViewById(R.id.textViewProcessNumbers);
textViewProcessNumbers.setText("Processing...");
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 30000ms
textViewProcessNumbers.setText("Processed...");
}
}, 30000);
}
Use handler for delay. Hope it helps
You need to move that process to a background thread e.g. using an AsyncTask since textview won't get updated until you leave the main thread.
Executing long running operations on the UI thread is also not recommended and it might cause an Application Not Responding dialog to appear.
So
1. Set the label to Processing...
2. Start the AsyncTask with your process
2. When AsyncTask finishes update the label in onPostExecute
You can use CountDownTimer, after find text view add this code.
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textViewProcessNumbers.setText("Processing...");
}
public void onFinish() {
textViewProcessNumbers.setText("Processed...");
}
}.start();
CountDownTimer(long millisInFuture, long countDownInterval)
Related
I started execution of a for-loop on click of a button. Now I want that when another button is clicked then execution of the for-loop that i started earlier should stop and I want to retrieve the value of counter when this for-loop stops executing. How can I achieve this?
public void clickStart(View view) {
TextView textView = findViewById(R.id.textView);
int counter = 0;
for (int i=0;i<1500;i++) {
counter = counter + 10;
textView.setText(counter);
}
}
public void clickComplete(View view) {
//Write code to stop executing for loop in clickStart()
}
So this isn't exactly the answer for how to stop a for-loop from outside (for which you already have received answers from other users), but after looking at your question it seems you are trying to show a counter that increments in 10s in your textview with some delay for which you are using the for-loop.
I would like to point out that your for-loop will finish executing within some milliseconds, i.e. as soon as you click the button to start the loop your textview will show the final value of counter which is 15000 in your case.
If my assumption was right about the delay you need you can make use of handler and implement is as shown below:
First declare these as global variables in your activity or fragment where you will be using it.
TextView textView;
final Handler handler = new Handler();
Runnable runnable;
int counter; //for the +10 counter you were originally using
int count; //for number of times to execute
Textview needs to be called from multiple methods hence, the global usage.
Now in the onCreate() method you can write the following code:
textView = findViewById(R.id.textView);
runnable = new Runnable() {
public void run() {
if (count <= 1500) {
textView.setText(String.valueOf(counter));
count++;
counter += 10;
handler.postDelayed(this, 500);
//500 milliseconds for half a second delay change this as you require
} else {
handler.removeCallbacks(this);
}
}
};
Inside the run() method is the code that determines what is to be executed after the mentioned delay.
Now assuming you know how to use onClickListeners on your buttons, your startClick method should look like this:
public void startClick(View v) {
counter = 0;
count = 0;
handler.post(runnable);
}
so every time you click start counter will reset to 0, if you don't want it to reset initialize values outside the start function in onCreate before the runnable. Finally, the clickComplete method should be to simply stop the runnable as below:
public void clickComplete(View v) {
handler.removeCallbacks(runnable);
}
Let me know if this was of any help to you.
You could do it like this
public boolean stopExecution = false;
public int counter = 0;
public void clickStart(View view) {
TextView textView = findViewById(R.id.textView);
counter = 0;
for (int i=0;i<1500;i++) {
counter = counter + 10;
textView.setText(counter);
// also here use String.valueOf(counter) this would throw sn error in my android studio
if(stopExecution){
stopExecution = false;
break;
}
}
}
public void clickComplete(View view) {
stopExecution = true;
// you can access the "global" value counter from here at whatever value it stopped
// in case it is still running it will break the execution and you will have the vslue where it stopped
// but the processor should handle it very fast so maybe you need some delayed loop or ?
)
On way is to add a method in your code:
public boolean isRunning()
{
return this.keepRunning;
}
And in your code do this:
public void clickStart(View view) {
TextView textView = findViewById(R.id.textView);
int counter = 0;
for (int i=0;i<1500;i++) {
counter = counter + 10;
textView.setText(counter);
if(isRunning){
keepRunning=false;
break;
}
}
}
public void clickComplete(View view) {
//Write code to stop executing for loop in clickStart()
this.keepRunning=true;
}
2nd way is to use handler thread:
Instead of using a for loop, you can let the Runnable instance call itself for a specific number of times. These calls will be posted to UI thread queue so, keep that in mind.
The following code should do it:
final Handler handler = new Handler();
int count = 0;
final Runnable runnable = new Runnable() {
public void run() {
// need to do tasks on the UI thread
Log.d(TAG, "Run test count: " + count);
if (yourcondition) {
handler.removeCallbacksAndMessages(null);
}
}
};
// trigger first time
handler.post(runnable);
I have the following code, which I was hoping would count up to 3 million on the screen.
It compiles and runs, displaying 3,000,000 at the end on the emulator. My question is how do I force a redraw / display of the textbox during the loop please?
/** Called when the activity has become visible. */
#Override
protected void onResume() {
super.onResume();
Log.d(msg, "The onResume() event");
TextView textbox1=(TextView)findViewById(R.id.TextView1);
for(double l=0; l<=3000000; l++){
textbox1.setText("" + l);
}
}
The view is only disabled after onResume has finished running.
You may want to set the text in the textview, update some state in the activity (like an int field), and register some code to run after a while and increment. Look at using Handler, AsyncTask, or other options to defer code.
Here's a quick-and-dirty example with Handler.
final long DELAY_MILLIS = 50;
final Handler handler = new Handler();
int num = 0;
final Runnable runnable = new Runnable() {
public void run() {
if (num >= 3000000) return;
textbox1.setText("" + num);
num++;
// re-register ourself to run in DELAY_MILLIS;
handler.postDelayed(runnable, DELAY_MILLIS);
}
};
TextView textbox1;
protected void onResume() {
// more efficient to look this up once
this.textbox1 = (TextView)findViewById(R.id.TextView1);
runnable.run(); // will register itself to re-run
}
According to this answer the best way to show an incremental value in a TextView is to use ValueAnimator
public void animateTextView(int initialValue, int finalValue, final TextView textview) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(initialValue, finalValue);
valueAnimator.setDuration(1500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
textview.setText(valueAnimator.getAnimatedValue().toString());
}
});
valueAnimator.start();
}
I have 2 buttons as well as a progressbar.
Now I want to count from 0 - 100 and update the progressbar with the counter. Unfortunately this count is so fast, that I will not see a progress (I can only see the progressbar jump from 0 to 100 within a 'millisecond'.).
This is what I tried so far, however the same thing happens as before.
I click the button to start the counter, the app becomes unresponsive (I calculate within the mainThread, so that is OKAY (and exactly what I want to accomplish here(!))) and shortly after sets the progressbar to 100. Nothing in between.
Now if you could head me into the correct direction, that'd be highly appreciated! :)
public class MainActivity extends ActionBarActivity {
public String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addButtonListeners();
}
public void addButtonListeners() {
Button firstButton, secondButton;
final ProgressBar pgBar;
firstButton = (Button) findViewById(R.id.first_button);
secondButton = (Button) findViewById(R.id.second_button);
pgBar = (ProgressBar) findViewById(R.id.progressBar);
firstButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "First Button was pressed.");
for (int i = 0; i <= 100; i++) {
countProgBarUp(pgBar, i);
}
}
});
secondButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Second Button was pressed.");
}
});
}
public void countProgBarUp(ProgressBar pgBar, int counter) {
try {
Thread.sleep(100);
pgBar.setProgress(counter);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
...
}
The UI becomes unresponsive because you are doing this on the main thread and sleeping. If you do not return from the onClick() then the main thread cannot handle UI changes, such as displaying your new progress. Only the main thread can update UI components and draw them. It is often called the UI thread because of this.
You could try creating a Runnable which updates the progress bar to the new count. Create a Handler which is bound to the UI thread and call postDelayed() for the Handler and give it an instance of the Runnable. Then in the Runnable just post it again as long as you haven't reached you max progress.
I have developed an android application which extracts single line text messages from the server. Once a button is clicked, it makes a function call which gets the next message from the server. Some of those messages are time based,
i.e those messages have to be displayed in the TextView for a particular amount of time and after that time is elapsed, it should automatically make the function call to get the next message from the server(i.e without the button being clicked).
Could someone please help me out in achieving this.
I tried using while loop as follows:
while(!presentTime.equals(expiryTime)){
calculatePresentTym(); //This method calculates the presentTime value
display.settext(the received instruction);
}
if(presentTime.equals(expiryTime))
(make the function call)
If I do this, nothing is being displayed till presentTime and expiryTime are equal. Once they are equal, the next instruction is automatically fetched by the function call and is displayed in the TextView.
Use a a handler
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
T0 cancel the run
m_handler.removeCallbacks(m_handlerTask); // to cancel the run
You can also use a timer but you will have to use runOnUiThread to update ui since timer runs on a different thread.
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
//do something
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
//update ui
}
});
}
}, 1000, 1000 );
Note:
gets the next message from the server
Getting the message from server should be done on a background thread.
Edit:
While copy pasting the initialization part was missing. You have a counter i that is displayed in the textview. The counter increases by 1 every second. When it reaches 100 you cancel the run. Modify the below according to your requirements.
public class MainActivity extends Activity {
TextView tv;
Handler m_handler;
Runnable m_handlerTask ;
int i=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
m_handler = new Handler();
m_handlerTask = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if(i<=100)
{
tv.setText(""+i);
i++;
}
else
{
m_handler.removeCallbacks(m_handlerTask);
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
}
}
Use a timer. Schedule the timer for repeated interval executions, and after each execution you can get the next text from the server and display the same.
Check the Timer reference scheduleAtFixedRate(TimerTask task, long delay, long period)
For a side project of mine, I'm devoloping an android app with java. I don't know java a lot but i'm trying ^^.
The project is to have an Alarm at a random time in a certain range. The problem is that my chronometer and button freeze, but everything still works! Does anyone has maybe another solution for the thread.sleep ??
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void StartChrono(View view) {
final Chronometer chrono = (Chronometer)findViewById(R.id.chronometer1);
chrono.setBase(SystemClock.elapsedRealtime());
chrono.start();
//Tick();
}
public int RandomTime(int min, int max)
{
int random = max - min;
Random rand= new Random();
random = rand.nextInt(random)+min;
return random;
}
public boolean CheckUp(int randomtime,int chronotime)
{
boolean check = false;
if(randomtime== chronotime)
{
check = true;
}
return check;
}
public void Tick()
{
boolean check = false;
int randomtime = RandomTime(20,150);
int time=1;
do
{
check = CheckUp(randomtime,time);
time = time +1;
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Error - 000");
alertDialog.setMessage("Could not check!");
alertDialog.show();
}
}while(check == false);
if(check == true)
{
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Yuy");
alertDialog.setMessage("Switch!");
alertDialog.show();
}
}
}
I wouldn't use Thread.sleep(), I would use a Timer.
You can set a time and the Timer automatically calls the associated task.
In Android it would work something like this:
http://android.okhelp.cz/timer-simple-timertask-java-android-example/
I used it once myself, but that is some time ago.
Btw.:
You don't have to write a method to check for a boolean value.
This also works:
boolean check = 5>3;
System.out.println("check: " + check);//"check true"
I'd definately use a Handler for this task: http://developer.android.com/reference/android/os/Handler.html
A basic example would be this:
long timeDelay = 1000; // Set this to your random number.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do whatever you need to do after a specified interval.
}
}, timeDelay);
Instantiate the Handler inside your onCreate and keep the reference around so you can call it inside your method.
Just to clarify, why you can't use Thread.sleep() for "sleeping" a specific amount of time, is this: when you call Thread.sleep() you call it on the UI thread, so every component running on the UI thread (buttons, textfields and so on) will "sleep" for the given amount of time and hence you basically halt the whole application.
Also see the documentation for Thread.sleep:
Causes the thread which sent this message to sleep for the given
interval of time (given in milliseconds).