Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I use Toast.makeText to print the Number of an array. However, when I use it in a for- loop. It only printed the first number and did not do anything else.
Important: Toasts in android have two kinds of duration: Toast.LENGTH_SHORT, Toast.LENGTH_LONG however they're both slower than a duration of one loop execution or even a whole loop. So, in this case the system might print the first number and waits till the Toast disappears or overwrite all existing Toasts and print the last number or a random one.
There are several ways to handle this:
If you need to see the numbers your self, you can use :
Log.i("My Array Loop", "position: " + position + " value: " + array.get(position));
//check your Logcat for values
If you want to display them to the user using as a Toast, you can achieve this using a Handler or a Timer, but I prefer using Handler since it's more efficiante :
create a helper class for more flexibility :
public class ToastPrintHelper {
private Context context;
private ArrayList<Integer> list;
private int currentPosition = 0;
public ToastPrintHelper(Context context, ArrayList<Integer> list) {
this.context = context;
this.list = list;
}
public void printValuesEvery(final long periodInMillis) {
final Handler printHandler = new Handler();
//initialize your print runnable
Runnable printRunnable = new Runnable() {
#Override
public void run() {
//print your toast
Toast.makeText(
context,
"position :" + currentPosition + " value: " + list.get(currentPosition),
Toast.LENGTH_SHORT).show();
//repeat if there are still items to show
if (currentPosition < list.size() -1) {
currentPosition++;
//execute your runnable again but for a delay
printHandler.postDelayed(this, periodInMillis);
}
}
};
//execute your runnable without delay for the first time
printHandler.post(printRunnable);
}
}
Initialize your class this way :
ToastPrintHelper printHelper = new ToastPrintHelper(context, list);
Print values every one second (1000 millis)
printHelper.printValuesEvery(1000);
In such cases, I'd prefer using an AlertDialog with a ProgressBar and a TextView to make it more visible to the user and increase the UX/UI quality.
Note: The code was not tested, but I believe it has no errors. It can also be better simplified.
Happy Coding!
A loop that's running continuously can't execute this sort of actions on view if there's no delay. Either debug the code and see if the code is reaching every iteration number or Log the iteration numbers. Also, showing toast on every iteration is blocking your UI thread. You can use a Handler to put a delay to see the Toast and the iteration number like this:
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Show toast
Toast.makeText(this, "Iteration Number:" + i, Toast.LENGTH_SHORT).show();
//Show toast in about 5 seconds
handler.postDelayed(this, 5000);
}
}, 5000);
Related
So I´m writing a little egg timer for learning purpose. And actually everything works fine without that the onTick method in the CountDownTimer is only calling once at the begining and I don´t get why. Actually in the documentation it´s stated that if the action called in the method takes too long ticks can be skiped but i dont think that these calculations take longer than 60 min which is the max time usable. So the timer is ticking once like if input 30 min the display widget will show 29:59.
new CountDownTimer(timer,timer){
#Override
public void onTick(long l) {
long help = (l - (l%60000))/60000;
String help2 = "" + help;
Log.i("Minuten übrig", help2);
long help3 = (l % 60000)/1000;
String help4 = "" + help3;
Log.i("Sekunden übrig", help4);
String prov = help + ":" + help3;
display.setText(prov);
}
#Override
public void onFinish() {
button.setText("Start");
}
}.start();
Try replacing this :
new CountDownTimer(timer,timer)
with this:
new CountDownTimer(timer,1000)
You can put other value in place of 1000 but make sure it is less than timer value, else onTick will get called only once.
Also, check out Chronometer if your task is suited to this.
My result
Expected result
public void run () {
try {
handlers.addElement (this);
broadcast("Welcome " + name);
while(handlers.size() != 2){
if(handlers.size() > 2){
this.out.writeUTF ("The Room is full!");
this.out.flush();
handlers.removeElement(this);
socket.close();
}
}
broadcast("No of Player: " + handlers.size());
for(int i = 0; i < handlers.size(); i++){
GameHandler player = (GameHandler) handlers.get(i);
broadcast("Player " + (i + 1) + ": " + player.name);
}
System.out.println("Game starts!");
startGame(4);
....
}
protected static void broadcast (String message) {
synchronized (handlers) {
Enumeration e = handlers.elements ();
while (e.hasMoreElements ()) {
GameHandler handler = (GameHandler) e.nextElement ();
try {
handler.out.writeUTF (message);
handler.out.flush ();
} catch (IOException ex) {
handler.stop ();
}
}
}
}
The problem is the difference between the expected result and my actual result. I have no idea why the broadcast before the while loop runs normally but others run twice
Your problem is that in your case, each of the thread is sending the broadcast. Either you need to have a "master" / "server" of games thread that does the "system announcements" broadcasting, -or- elect one of the client threads (maybe the "player 1" thread?) to send the announcements.
The problem is the difference between the expected result and my actual result. I have no idea why the broadcast before the while loop runs normally but others run twice
You really don't give enough details on your problem but I see these issues:
You talk about TCP and the code mentions sockets but you are processing a local elements collection. Unless you are talking to the same JVM over TCP (which is strange) the elements collection is going to start 2 players on each client. Is that really what you expect?
Even though you says elements is a Vector you still need to synchronize on it at the start of the run() method because you are performing multiple operations on it and there are race conditions. For example, if 3 handlers are added, they will all remove themselves and close their own sockets.
Vector really is an outdated collection. You should be using something else.
When the first thread adds itself to elements it then enters a spin loop waiting for the second person to join the game. Seems like a waste there. Some small Thread.sleep(...) would be appropriate.
If the room is full I suspect that the thread should return; from the run() method. Instead it continues on which I suspect is not good.
Hope something here helps.
I have started a Java coding short course at a university about 5 months ago. I have learnt quite the amount of things with regards to Java coding, but am still lacking in other things such as threads, handling exceptions, or even making JFrame games. I decided to embark on a text based game to just learn and figure out how a game loop should work (kind of), and how the logic should work (still, very "kind of"). The game I wrote runs with if-else commands, thus you get displayed a screen, type in the command of the option you want to pick, and it bumps you to the next menu, very standard of course. I run these if-else statements within nested for loops.
My nested for loops looks like the following:
// This is just an example, they're actually a lot more cluttered
// in my actual source code.
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
for (int i = 0; i <= 10; i--)
{
for (int ii = 0; i <= 10; i--)
{
if (reply.equalsIgnoreCase("/help")
{
System.out.println("Here I have a separate call to a class
file (excuse me, forgot the exact wording), thus it
call something like help.writeOutput(); to display
the help menu");
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/makegameeasy")
{
// Just an example.
gamedifficultyEasy.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/makegamedifficult")
{
// Another example.
gamedifficultHard.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else
{
System.out.println("Here I print out an error for incorrect
input received, standard fare.");
mainMenu.writeOutput();
reply = keyboard.nextLine();
break;
}
}
}
As mentioned, the above is just an example, it's not very elegant, and I can probably use Exceptions for any incorrect info submitted by the user, however I do not know too much of Exceptions to comfortably add them, so I'll do that at a later time, however my main issue at the moment is a part of my game where "resource mining" has to be done on regular intervals. I have been all over Google, but still can't quite catch how to set a Thread or Timer up for my game so it does the mining automatically, and the player can go on with their game.
The game is essentially one of those games where you build up a base, upgrade your mining tools, and generate more "stuff". I have pasted a few blocks of code from my "mining" class file below that will basically run how much of one thing should be mined. In the game you will be able to buy upgrades of course, so it will get factored into your mining speed.
// I initiate my variables a lot earlier, but just for some
// clarity, I have initiated the variables in the below methods,
// they will not work correctly anyway, I am aware of that, however
// I didn't want to add the other "get, set and initiate"
// variables and methods everywhere, as to not spam this block of code.
// upgradeOS, upgradeHF, and upgradeLM all have their own respective
// set and get methods. They are also all int variables.
public void handleOS()
{
// OS = short for Oxygen Silo
int mineOS = os.getStoredO2() + (1 * upgradeOS);
os.setStoredO2(mineOS);
}
public void handleHF()
{
// HF = short for Hydrogen Fuel
int mineHF = hf.getStoredO2() + (1 * upgradeHF);
hf.setStoredO2(mineHF);
}
public void handleLM()
{
// LM = short for Liquid Minerals
int mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
lm.setStoredMinerals(mineLM);
}
// This is what's going to run the whole time on the set intervals.
public void mine()
{
mineOS = os.getStoredO2() + (1 * upgradeOS);
mineHF = hf.getStoredO2() + (1 * upgradeHF);
mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
os.setStoredO2(mineOS);
hf.setStoredO2(mineHF);
lm.setStoredMinerals(mineLM);
}
// Using 10 seconds here to have it update as quickly as possible so I can
// see any changes. This is just here to write an output.
public void getUpgradeInfo()
{
System.out.println("Oxygen: " + (1 * upgradeOS) + " / per 10 seconds.");
System.out.println("Hydrogen: " + (1 * upgradeHF) + " / per 10 seconds.");
System.out.println("Liquid Mineral: " + (1 * upgradeLM) + " / per 10 seconds.");
}
I'm not the best naming schemes for my materials...
TL;DR: I can't figure out how to implement a thread or timer just for the above mentioned mine() method since I do not have the appropriate amount of knowledge. My if-else rules aren't too elegant, but I'll work on those of course. Basically the if-else rules should run separately from the mine() method, and you can do some AFKing without the game updating the System.out output, thus you can be floating in, for example, the Oxygen Silo upgrade menu, and you won't be bounced back to a different menu due to a thread "waking up", such as being bounced to the main menu, but the mine() method will still generate resources in the background as it should.
Any help on this, or just even a nudge in the right direction will be greatly appreciated.
To answer the question you asked, you can do something like this:
import java.util.*;
TimerTask tt = new TimerTask() {
public void run() {
mine();
}
}
Timer t = new Timer();
t.scheduleAtFixedRate(tt, 0, 1000);
Alternatively, you can use an ActionListener and the swing timer in a similar way. This has the advantage of being Thread-safe in case you build a swing gui on top
Lastly, you should check out the usage of synchronized and volatile to make sure that the variable(s) that are updated in mine() are done so in a thread-safe way
Thanks to #ControlAltDel, definite shove in the right direction. I have taken a bit of code and set it up like this:
import java.util.*;
// extends TimerTask needed
public class TimerTestOne extends TimerTask
{
// Needed
#Override
public void run()
{
TimerTestTwo ttt = new TimerTestTwo();
mine();
}
// Needed, method doesn't need the same name though.
private void completeTask()
{
try
{
//assuming it takes 10 secs to complete the task
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
// You will need to define the following line of code:
TimerTask tt = new TimerTestOne();
Scanner keyboard = new Scanner(System.in);
String reply;
// Following 2 lines of code, yup, need them.
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(tt, 0, 10*1000);
previousMenu();
for (int i = 0; i <= 10000; i++)
{
for (int ii = 0; ii <= 10000; i++)
{
System.out.println("Go to another menu?");
reply = keyboard.nextLine();
if (reply.equalsIgnoreCase("/yes"))
{
yes();
reply = keyboard.nextLine();
}
}
}
}
// I added the following methods, just so I didn't have to work
// off 2 class files.
public void mine()
{
System.out.println("Mined");
}
public static void yes()
{
System.out.println("Next menu");
}
public static void previousMenu()
{
System.out.println("Previous menu");
}
}
So there, if anyone ever needs to have a look at setting a timer up that won't break your text based game.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I was digging around in some old java projects that I never finished and I pulled out this little number that is of my best projects ever built.
It's a desktop clock widget coded in java and it works perfectly fine except for one thing. The way I have it check the current time to stay updated is in a loop and the loop "crashes" in a matter of seconds so the widget no longer gets the current time.
This is how the loop is constructed (reduced in size):
public class getCurrentTime {
public static void getTime() throws InterruptedException {
int hour = global.calendar.get(Calendar.HOUR);
int minute = global.calendar2.get(Calendar.MINUTE);
if(hour == 0) {
global.hour.setIcon(new ImageIcon("resources/hours/12.png"));
}else if(hour == 23) {
global.hour.setIcon(new ImageIcon("resources/hours/11.png"));
}else {
global.hour.setText("?");
}
if(minute == 0) {
global.minute.setIcon(new ImageIcon("resources/minutes/00.png"));
}else if(minute == 59) {
global.minute.setIcon(new ImageIcon("resources/minutes/59.png"));
}else {
global.minute.setText("?");
}
Thread.sleep(1000);
getTime();
}
}
global is a class where I keep most of my variables (I know it's weird, this was like 3 years ago, it's how I used to write my programs).
So my main question is, is there a way that I can prevent the loop from "crashing"?
Thanks in advance!
This is not a loop, really. It is a recursive call. In each recursion, some more memory will be allocated, so it will after some time go out of memory. I wonder why this is a matter of seconds here, but anyway.
Try using a Timer to schedule the gui update.
Edit : you are creating a new ImageIcon in each recursion. They can be rather large in memory. Maybe they are the reason for the rapid "crash".
Apart from that I suggest sticking to java naming conventions. Class names should start with a capital letter.
Thread.sleep(1000); is not going to be a good option. You can use Timer. By using a Timer you schedule a task at regular intervals.
Timer timer = new Timer();
long interval = (1000) ; // 1 sec
timer.schedule( new TimerTask() {
public void run() {
//do your work;
}
}, 0, interval);
If you want to stop the scheduling, you can use timer.cancel();
EDIT: as Fildor said I think memory is your problem. Use timer this way, it should solve your problem.
This is first solution
class clockUpdater implements Runnable {
#Override
public void run() {
Thread.sleep(WAIT_TILL_NEW_MINUTE);
while(true){ //a infinite loop
// the Swing call below must be queued onto the Swing event thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
//your clock updating code here
}
});
try {
Thread.sleep(1000*60);//you only need to update once after a minute
} catch (InterruptedException e) {
// ....
}
}
}
}
This is second
class clockUpdater extends Thread{
#Override
public void run(){
Thread.sleep(WAIT_TILL_NEW_MINUTE);
while(true){
try{
//your update code here
Thread.sleep(60*1000)//
}
catch(Exception e){
//..
}
}
}
}
Note: You need to start this as soon as the minute changes in system time. Or clock time will lag behind. Calculate WAIT_TILL_NEW_MINUTE as soon as your program starts. Better to update only when it is needed.
The answer for your question is
use set timeout function for the function
which you want to avoid loop crashing.
Like:
setTimeout(function() {
// write the logic
},1000);
I need to check how many events are detected within 2 seconds. I have the timer working and I have everything else working...but I ran into a problem: the loop only checks one time, per second and I can't seem to figure out how to fix that. I need it to check constantly during these two seconds to see how many events there were in total!
Here is what I have:
int seconds = 0;
System.out.println("Seconds: " + seconds);
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {}
seconds++;
System.out.println("Seconds: " + seconds);
//This needs to be looping the whole time.
//But right now, it's being blocked and only checked once
if(eventDetected() && seconds <= 2){
events++;
}
}
So you can see my problem. I can't split them up because then the second timer would run, and THEN eventDetected() would be checked. I need it to check constantly DURING the two second timer...so I basically need both things to happen at once. Is there any way I can do this?
Thanks for any help ahead of time!
I think your design pattern needs work -- I don't know what type event you're looking to detect, but no matter how short your sleep time is, there's a chance you could miss an event using the current pattern. Here's what I suggest:
Have eventDetected() increment your events counter. That way, you won't miss an event.
Then, you just need a way to turn on and off listening (and perhaps resetting the event counter). If you're sure that in you're current pattern you are really in a different thread that won't block your eventDetected() method, you could set a flag to check. For example:
When you want to start listening:
listenForEvents = true;
In eventDetected():
if (listenForEvents) { events++; }
When you want to stop listening (for example, after your Thread.sleep() call):
listenForEvents = false;
With multithreading, make sure to watch out for concurrency issues checking and setting the variables, of course.
I would tell you what kind of event I have to keep track of but then I'd have to kill you :D
Answered my own question. Hopefully this will help anyone else out who has a similar problem at some point! I looked up multithreading a bit...
I created a new class EventTimer which implements Runnable, with a public field for seconds:
public class EventTimer implements Runnable{
int seconds;
static int timerThreadCount = 0;
Thread t;
public EventTimer() {
timerThreadCount++;
this.seconds = 0;
t = new Thread(this, "Event Timer");
t.start(); // Start the thread
}
#Override
public void run() {
// TODO Auto-generated method stub
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {
System.out.println("Waiting interupted.");
}
seconds++;
System.out.println("Seconds: " + seconds);
}
}
}
Then I used an instance of the EventTimer, and used a while loop & if statement to solve my problem.
EventTimer t = new EventTimer();
while(t.seconds < 2){
if(eventDetected()) events++;
}
It was actually quite simple! I realize that each iteration of my loop of operation (since the entire code piece above is inside an infinite loop) will create a new EventTimer thread and I will eventually run into memory problems however. How would I close/end a thread after the timer has reached 2 seconds?