Problems increasing an integer in android studio - java

I am making an android studio app and am trying to get my screen to loop through the digits 0-9 until the user clicks and stops the loop on a particular number. The code I have written so far is:
public void loop () {
for (int a = 0; a<10; a = ++a % 10) {
textView2.setText("" + a);
}
Relevant xml section
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="#+id/textView2"
.../>
This code doesn't output anything onscreen. I have tried a few different variations of the code and if it does display a number, it only displays the last digit, '9'. This makes me think that it has worked but it goes through the numbers too quickly for me to see and stops on the last one instead of looping indefinitely. Is anyone able to point out where I may be going wrong? I'm still learning so apologies for the relatively simple query.
Also when I do get it to work, and I want to make it clickable, do I put the onclicklistener in the for-loop?
Many thanks.

You were right, when it displays 9, it just looped through the numbers very quickly, you couldn't even see them changing.
You are not doing anything wrong, you just have to take pauses between changing the numbers. The very easy and ugly fix would be adding: wait(1000) after the setText(...) method.
However, this is not recommended, because Android draws and receives events on the main thread. When you block the thread for 1000 milliseconds with the wait, you make the thread unable to accept any events for that one second, which makes your app freeze.
To fix the freezing, you need to update your TextView, and then post a message on the main thread, that it should update again over 1 second. Because of the separation, it won't really look like a loop.
For posting messages on the main thread, I will use a Handler (android.os.Handler), which executes messages on the thread it was created, unless you use a different Looper.
Here's a rough example:
private int a = 0;
private Handler handler = new Handler();
private TextView textView2;
public void loop() {
handler.post(new Runnable() {
#Override
public void run() {
updateText();
a = a++ % 10;
if (a < 10) {
handler.postDelayed(this, 1000);
}
}
});
}
public void updateText() {
textView2.setText("" + a);
}
Just call loop() when the button was clicked, the rest will be handled automatically.

Related

runOnUiThread() and infinite loop on Android

I do not understand the behaviour of my code. To summarize, I have an editText (variable hours in my code) that start with "00". I am creating a thread which prevents this editText to not have 2 digit. Let s assume that this editText cannot have more than 2 digits. What I am doing is that I create a thread. In this thread, whenever this editText does not have 2 digits(so 1 digit), I add to it a "0".
However, whenever I just put one digit on the editText, it is getting crazy and go into an infinite loop and other stuff that I don't understand. Here is my code:
Thread digitLessThanTwoThread;
EditText hours = (EditText) findViewById(R.id.hours);
digitLessThanTwoThread= new Thread(){
#Override
public void run()
{
while(true) {
if (hours.getText().toString().length() != 2 && !hours.isFocused()) {
main_activity.runOnUiThread(new Runnable() {
#Override
public void run() {
hours.setText("0" + hours.getText().toString());
}
});
}
}
}
};
digitLessThanTwoThread.start();
Moreover, at the end, The editText hours displayed "00".
I also get a message "suspending all threads took: XXX seconds" before doing anything actually!
There are two problems here. First, the simple one:
while(true)
This will run the thread at full power until as you seem to be noticing, the OS steps in to stop the runaway thread. You should instead add an addTextChangedListener() listener, for example.
The more complex one is:
main_activity.runOnUiThread(new Runnable() {
#Override
public void run() {
hours.setText("0" + hours.getText().toString());
}
});
I think you are assuming that this is executed synchronously, that is the setText() is executed before runOnUiThread() returns. However, it is asynchronous, so next time round the loop your if is still true, and you queue another action on the UI thread to set the text and so on, so the UI thread may never get a chance to run until the OS steps in to halt the runaway thread.

How to handle event in a program running in a cycle (loop)?

I´ve been dealing with this for some days now I´ve serach over the internet and tried everything that came up to my mind but nothing works. My problem is that I am making a pexeso game, we have some additionaly library directly from school or something like that which allows us to draw some pictures instead of comad line only... (We didn´t have graphics yet) So my problem is that my game is running in cycle and waiting for my click som I am checking the condition if click was made. And if I want to click I have to have just a method public void vyberSuradnice(int, int) declared in my code.
So the problem is that my game is runinng in cycle and checking if click was made. But when the click was made the method vyberSuradnice is executed and there I am setting the value off atrrbiute - cakatNaKlik on false, so click was made and one step of game can be made.. But since the function is running in cycle, then even If I clicked and in the method vyberSuradnice the value of attribute is changed, my function which is running in cycle isn´t respond to that change, so the game isn´t going on.
this is the method for clicking
public void vyberSuradnice(int paSuradnicaX, int paSuradnicaY) {
this.riadokOdkry = (paSuradnicaY ) / 25;
this.stlpecOdkry = (paSuradnicaX - 10) / 25;
if (this.riadokOdkry > this.aPocetRiadkov || this.stlpecOdkry > this.aPocetStlpcov) {
System.out.println("Klikli ste mimo hracieho pola ");
} else {
this.cakatNaKlik = false;
}
}
This the part of code where I am waiting for cakatNaklik - false value
while (uhadol) {
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
But even if the value is changed in method vyberSuradnice this condition is not triggered. But when I make something like this :
while (uhadol) {
System.out.print(this.cakatNaKlik);
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
the game is working like by writing the variable refresh it or something... but I am getting neverending print of true true or false on command line and this is something I can´t afford to have...
I know this may can be dan by threads but it´s something I can´t allowed to make and I am basically trying to do two things at once.
Is there any other to do this that the variable will be refreshed even without that println and the code will work ?
Thanks very much for every help
Thanks everybody for help, I finally solved it. I just tried tu put a sleep before the if condition. It only need to sleep for even a one miliseconds and it´s seems that the condition is refreshed so it works.
Try this:
Implement an ActionListener interface or extend a class that implements an ActionListener interface. For example:
public class MyClass implements ActionListener {
}
Register an instance of the event handler class as a listener on one or more components. For example:
someComponent.addActionListener(instanceOfMyClass);
instanceOfClass = this; //(if it is handled in the same Class)
Include code that implements the methods in listener interface. For example:
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
Reference:
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html

For Loop delay not working Android

I am a newbie to android development so bear with me. I have scoured the site and implemented several suggested answers but I am still running into a problem. I want to iterate through an object array and display the contents of the array with delay to allow user interaction(The user gets to say if the object and the text displayed is what they were looking for by clicking on a yes or no button). My objects however display last first and then start zooming real fast in a seemingly endless loop. Here is the method I call to load the images:
private void displayInstructions() {
for (Emergency_Instructions instruction : instructions) {
final Emergency_Instructions instruction2 = instruction;
final Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
public void run() {
displayimages(instruction2.getStep(), instruction2.getStepImage());
handler.postDelayed(this, 5000);
}
}, 5000);
}
void displayimages(String text, Bitmap image)
{
instructiontext.setText(text);
instructionbmp.setImageBitmap(image);
}
Any help will be greatly appreciated
You create multiple Handlers where you need only one. You tell each one to post a Runnable to the current thread's message queue, to be run after the same delay. That delay expires at pretty much the same time for all the tasks, so they are then executed one right after another, as fast as the queue can go. Each of those tasks also posts a message via the handler, to be run after the same delay. Once that delay expires, that will produce a second group of messages posted rapidly one right after the other, as fast as the device can go.
If you just want to schedule what is effectively a slide show, you might do it like this:
private void displayInstructions() {
final Handler handler = new Handler();
int delay = 0;
int step = 5000;
for (Emergency_Instructions instruction : instructions) {
final Emergency_Instructions instruction2 = instruction;
handler.postDelayed(new Runnable() {
public void run() {
displayimages(instruction2.getStep(), instruction2.getStepImage());
// handler.postDelayed(this, 5000);
}
}, delay);
delay += step;
}
}
Note there that each task is posted with a larger delay than the last -- this is a delay with respect to when the message it posted, not with respect to when the preceding message was displayed.
With that said, I'm doubtful that this is really what you want to do, or at least that it is all you want to do. As it stands, this approach will cause all the messages to be displayed (eventually) regardless of any user interaction. At minimum, you will probably want to provide for subsequent messages to be canceled in the event that the user accepts one, or cancels the overall operation.

Simple Sum Program Android java

No errors, compiles, no run time error.
Hey, I have a simple question about Android sum. I'm doing a simple summation, the code compiles, it does technically do what it suppose to do, sum the number until its greater than 120. However, I wanted the output to show each sum as it goes through the loop. Unfortunately, it just jumps immediately to the last sum on the textview. I tried using a sleep function, wait function, but what ended up happening was it would wait the amount of time for all the loops until the sum was greater than 120, then output the final sum. In this case 4950. Any suggestions for showing each sum on the text view?
I also tried using this line of code, which worked in showing each sum individually, however, it started the timer immediately. Which it should not do.
Toast.makeText(MainActivity.this, "SUM:"+sum1, Toast.LENGTH_SHORT).show();
Basic goal of my simple application
1) Show each sum
2) When the sum is greater than 120 start timer
Question: How do I get it to show each sum individually on the text-view instead of jumping to the final summation?
public void onClick(View v)
for(i=0;i<100;i++)
{
sum1 = sum1 + i;
sum.setText("Sum:"+sum1);
if(sum1 > 120)
{
timer.start();
}
}
}
Thank you for your time.
The reason it "Jumps" to the last one is because the act of clicking runs the for loop while blocking the UI thread. You are in effect not able to see the text changing, but its changing. You can accomplish what you need by using a Timer or TimerTask, which basically creates a separate thread for you. It also handles the delays which you need. Simply do the math in the Timers execution method.
//make sure these are global
int i = 0;
int sum1 = 2;//not really sure where your sum starts so you choose
TimerTask leTask = new TimerTask() {
public void run() {
sum1 = sum1+i;
i++;
/*I don't actually remember if you must go back to the main thread
* when in the tasks run method. Incase you get an error because
* of that then just do that quickly. I have included a link for
* you on how to do that if necessary.*/
sum.setText("Sum:"+sum1);
if(sum1 > 120){
/*Start your actually timer here
* and stop execution of leTask by calling the cancel method*/
}
}
int delay = 0;//you don't really want a delay since you want it immediately after click
int everySecond = 1000;
timer.scheduleAtFixedRate(leTask, 0, everySecond);
Keep in mind the way I set ti up is just an example. You should make sure that you have access to leTask (or whatever you call it) when its cancelled. i and sum1 should also be global. delay and everySecond don't have to be in variables. I did that to kind of explain what they do so it makes a bit more sense. I like this method better because you aren't worried about UI thread stuff with the exception of updating the TextView.
Edit: You can also access the UI from the timer using the post method from TextView. It would look something like this:
sum.post(new Runnable() {
public void run() {
sum.setText("Sum:"+sum1);
});
}
EDIT2:
I have to include this edit to be thorough for future user who come across this as I just found out that Timer and TimerTask is no longer becoming the preferred method for scheduling commands, etc. It should be ScheduledThreadPoolExecutor now. Although this has been the case for some time it hasn't really been reported much in questions on here that i've come across. In either case, android has it in the docs here. It's literally like the second sentence.
This is my proposed solution :D
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="#+id/resultView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start counting" />
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity implements OnClickListener {
private static final long SUM_DELAY = 100;
private TextView mResultView;
private Button mStartButton;
private Handler mHandler = new Handler();
private int mSum = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResultView = (TextView) findViewById(R.id.resultView);
mStartButton = (Button) findViewById(R.id.startButton);
mStartButton.setOnClickListener(this);
}
private Runnable sumTask = new Runnable() {
#Override
public void run() {
mSum += 1;
if (mSum > 120) {
mSum = 0;
mStartButton.setEnabled(true);
return;
}
mResultView.setText(String.valueOf(mSum));
mHandler.postDelayed(this, SUM_DELAY);
}
};
#Override
public void onClick(View view) {
if (view.getId() == mStartButton.getId()) {
mStartButton.setEnabled(false);
sumTask.run();
}
}
}
The thing is that onClick() runs on the UI thread. That means that the whole method has to be finished before the UI can update again, hence the sudden jump to the last number. That is also the reason why nothing happens when you use Thread.Sleep(). sleep() applies in that case to the UI thread, so the whole app will freeze.
If you want the TextView to count up, you have to use an AsyncTask. Add the loop and a Thread.sleep() to doInBackground(), publish the progress and set the text in onProgressUpdate(). The link actually contains a nice example that should work for you.

Android postDelayed works but can't put it in a loop?

Sorry I am a noob I've read countless tutorials about making a simple timer and was wondering why it doesn't work until I noticed it is the while-loop causing the issue o.O I have removed it and then it works but only 1 time I need to use the loop though so the movement finishes :C
Heres the code:
old_x is the coordinate from an ImageView and new_x from the onTouch Event, maybe the problem because I am casting them as an int? I don't know what I need to do so it works please help O:
while(old_x != new_x)
{
timedMoveIV(100);
old_x = (int)img.getX();
}
It calls this method which works if I do it without the loop.
public void timedMoveIV(int time_ms)
{
//sleep for time_ms milliseconds
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
if(new_x > img.getX())
{
img.setX(img.getX() + 1);
}
else
{
img.setX(img.getX() - 1);
}
}
}, time_ms);
}
Your main problem is that your loop doesn't take a break, so it's constantly running the function, posting a gazillion runnables.
What you want to do is make the runnable call itself after another 100 ms. Take a look at this example:
if(old_x != new_x)
timedMoveIV(100);
Here you simply call the function once. After that, you let the posted runnable decide whether or not it needs to move again:
public void timedMoveIV(final int time_ms)
{
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run()
{
if(new_x > img.getX())
img.setX(img.getX() + 1);
else
img.setX(img.getX() - 1);
// if not in position, call again
if((int)img.getX() != new_x)
timedMoveIV(time_ms);
}
}, time_ms);
}
It should stop once img.getX() == new_x. Notice the cast to int, though, because if you leave it out, you might get some oscillation as it gets within a pixel of the destination.
This assumes that new_x is an int. If it's a float as well, you should either cast both to int to compare, or compare them to a minimum threshold. For instance, if there's less than 0.5 difference, treat it as "done".

Categories

Resources