I can't handle this method: Thread.sleep() - android

I can't handle this method: Thread.sleep() in Android Studio.
I want to fill a 9x9 size TextView with a number every 0.1 seconds.
And, this is my codes.
public class MainActivity extends AppCompatActivity {
TextView[][] basicCell=new TextView[9][9];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVar();
int cnt=0;
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
basicCell[i][j].setText(j+"");
basicCell[i][j].setTextColor(Color.BLACK);
basicCell[i][j].setTextSize(20);
basicCell[i][j].setGravity(Gravity.CENTER);
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
Log.d("COUNT", ""+cnt++);
}
}
}
TextView[][] basicCell=new TextView[9][9]
All textviews are linked with basicCells.
And, The expected results screen is as follows.
In the middle of the code,
By inserting
try {Thread.sleep (100); }
catch (InterruptedException e) { e.printStackTrace();}
I tried to get the number one every 0.1 seconds ...
When you run the app, it stays on for a few seconds and the numbers come up at once.
I took a look at the log,
Log.d ("COUNT", "" + cnt ++);
In log chat, the logs are working hard,
The screen is in a state of jamming for a few seconds,
Since cnt is 80, the numbers are displayed on the screen at once.
I thought it was an emulator lag, so I ran it on my smartphone, and the result is the same.
I do not know what the problem is.
Is there a way to see the results as intended?

Please, take a look at the official guide for Processes and Threads. Your code is being executed on the main thread, but you can't just make it sleep, because it will freeze your UI. Also, onCreate is executed in order to create your activity, so you won't be able to update your UI just by sleeping the thread in onCreate, because Android will wait until onCreated is executed, then it will show your UI.
You need to create an AsyncTask. Please, read here:
https://developer.android.com/guide/components/processes-and-threads.html

setText(...), setTextColor(...), etc. don't change anything on the screen. They only change values recorded in the TextView objects to which you apply them. The framework will then ask the TextView objects to render themselves to the screen after your function has returned.
I don't know Android, so I don't know the proper names of things, but if you want things on the screen to change over time (i.e., if you want to animate your display), then you'll need to set up some kind of a timer task---a callback function that gets called periodically. Each time it gets called, it should change one thing (e.g., update one cell), and then it should return so that the cell will have a chance to render itself to the screen.

Related

Measuring the load time of individual GUI elements

I am writing a program to measure the load time of every GUI element (like button, Text box etc.). Right now I am working on Windows Phone and I plan to expand it to Android and iOS (using swift probably, still undecided) and Java desktop.
I am using the click event of a button to generate a GUI element (a button in this case)
private void btnCreate_Click(object sender, RoutedEventArgs e)
{
CleanUp(); // to Garbage collect
watch.Start();
Button btn = new Button();
btn.Width = 110;
btn.Height = 56;
btn.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
btn.Content = "Button";
btn.Click += btn_Click;
gridMain.Children.Add(btn);
watch.Stop();
}
I use a different button, with the following code in its event handler, to show the results
private void btnResults_Click(object sender, RoutedEventArgs e)
{
long ticks = watch.ElapsedTicks;
double ms = 1000.0 * (double)ticks / Stopwatch.Frequency;
// show results in a message box
}
I also have a button to remove the generated button and garbage collect so that I can remove and recreate and take several readings
private void btnRemove_Click(object sender, RoutedEventArgs e)
{
gridMain.Children.RemoveAt(3); //the dynamically generated button is at 3
watch.Reset();
}
The problem is that I am getting some what inconsistent results.
Here are few of my results (excluding the first run):
0.6028 ms
0.7217 ms
0.9596 ms
1.3834 ms
0.5626 ms
1.3814 ms
0.7343 ms
I don't understand the reason. Is this significantly inconsistent? if yes, then is my method flawed? is there a better way to do this? Thanks
Right now you're measuring constructing two objects (a Button and a SolidColorBrush), setting various properties, inserting a couple of things into vectors (the event handler and the children), etc. but I don't think the button is actually visible when you call Stop (there is probably a layout and render pass still to happen). So you're measuring some random things.
Off-hand (and I'm not a XAML perf guru by any stretch of the imagination) a variance of +/- 1ms wall-clock time for adding a Button to a Grid seems reasonable given the way you're measuring (eg, what else is your computer doing at the same time?). If you want to do perf analysis, use the performance analyzer tools.

How to pass a turn to AI in a game?

I am writing a simple game for 2 players, where they have to make turns after each other - select a few objects to remove from the board (removing is actually setting an ImageView invisible), then a player presses "End turn" at the end to pass the turn to another player.
The board is a GridLayout with the ImageViews, all ImageViews have onClickListener(), and they are all visible at the beginning of the game. A player clicks on several ImageViews (at these moments their IDs are placed in an array) and then clicks "End turn", this array of his move is analyzed, the corresponding ImageViews are set to invisible, and after that the turn should be passed to another player (the array is cleaned and the number of the current player changes).
All objects on the board have onClickListeners() attached. Upon clicking, their IDs are placed in an array, and a variable contains the number of the current player. The turns are switched in onClick() method on a onClickListener(), attached to the "End turn" button, and it's simply cleaning the array of the IDs and updating the number of the current player.
It works fine for the case of 2 humans playing (on the same device). But if a person plays with the computer, the AI calculates and makes its move in the same onClick() method. Since the user interface updates only after processing the onClick(), (ImageViews are set to invisible, and so on), AI's moves are not drawn on the screen and the player sees as if after his move (clicks on the objects), the board was redrawn immediately with the added changes made by the computer's move (objects removed).
So, I need to pass the turn to AI somehow differently, not in onClick() of the "End turn" button to be able to draw the AI's selection and hide selected views - before the player can make his next move. But how to do that and where?
onClick() method for the "End turn" button:
public void onClick(View v) {
hideSelectedImageViews();
if (currentGame.isWinningState()) {
//you won
} else {
changePlayer();
if (playWithAI) {
calculateAImove(currentGame);
showSelectedImageViewsByAI(); //doesn't work even with .invalidate()
hideSelectedImageViews();
if (currentGame.isWinningState()) {
//AI won
}
changePlayer();
}
}
}
In showSelectedImageViewsByAI(), a specific image resource is set for the ImageViews, so that they will look differently ("selected").
You can create a new Thread where it will run the AI's moves, when the AI makes their selections you can make the thread delay some seconds (so their selection can be shown) and then remove them. Your code has that problem, once the AI makes a selection, it's removed instantly (even if you did invalidate() twice)
If you are not familiar with Threads here is an example:
//I assume your code was inside an Activity
public class mainActivity extends Activity implements Runnable
{
Thread aiThread;
/*...*/
public void onClick(View v)
{
hideSelectedImageViews();
if (currentGame.isWinningState()) { /*you won*/ }
else
{
changePlayer();
if (playWithAI)
{
aiThread = new Thread(this);
aiThread.start();
}
}
}
public void run()
{
calculateAImove(currentGame);
showSelectedImageViewsByAI();
Thread.sleep(1000); //This will make thread wait for 1 second before removing selected (note the number is in milliseconds)
hideSelectedImageViews();
if (currentGame.isWinningState()) { /*AI won*/ }
changePlayer();
}
}
Please note that when using a thread to influence the UI you shouldn't affect views directly, you should instead call view.post() instead, if you are unfamiliar with either Threads or the view.post() method I recommend searching online for them.

Display Score In A Different Way in a Game

I am making a game and would like To display the score in such a fashion that if my score is 0 and is increased by 10, then the score should increment through all of the numbers from 0 to 10. After reaching the new score it should stop, for at least a small pause.
If, again, the score is increased by another 10, the scoreboard should increment through every number from 10 to 20 and then stop again.
I have tried using handlers but unsuccessful in getting them a pause or stop, in any way.
The example in this video demonstrates what I am trying to accomplish. If you look at the scoreboard in the top right, you will see the score constantly incrementing. Here is the url in case the above link does not work: http://www.youtube.com/watch?v=NdZ8YupmEmA&feature=fvwrel
This is the code for my Runnable to increment the score.
final Handler mHandler=new Handler();
mRunnable=new Runnable() {
public void run() {
String s = null;
++i;
s= new Integer(i).toString();
tv.setText(s);
mHandler.postDelayed(mRunnable,1000);
}
/*protected void onStop() {
mHandler.removeCallbacks(mRunnable);
}*/
};
mHandler.postDelayed(mRunnable,1000);
What I specifically need is how to get the code to stop counting.
You can simply print all the numbers between 2 end points.
Say:
int counter = 0;
while(counter%10 != 0)
{
textView.setText(counter.toString());
counter++;
}
And then again continue with the loop, just start with 11 this time,not 0.
I'm not sure it'll work as you want, like in your Temple Run example. I would want to add a little sleep() of very small amount, but yesterday I was advised not use sleep() method in Android development.
EDIT:
Ok. This tutorial seems pretty easy to handle. You can apply the same logic to your score display mechanism using Handler(as you probably guessed).

android button animation with click

I'm trying to make flying balloons (up and down, infinitely) and by clicking on one of them, it will changes its direction. I tried to use Animation, but it don't support click on a view at a current position at a current time. I know, that there are two methods, for at least:
use an OpenGL
and use a Canvas.
I don't want to use OpenGL for so quit simple animation. And I don't understand how to do it, using Canvas(were read this, google docs and some google search links).
I don't need a code, all I need it's the way how to do it and the algorithm.
Alright, this is what I've set up for one of my projects that would work exactly as you need...
You need to create 4 main aspects:
- An Activity (extend Activity)
- A SurfaceView (extend SurfaceView implement SurfaceHolder.Callback)
- A Thread (Extend Thread)
- Objects that interact (extend Drawable)
The Activity starts and generates a SurfaceView that creates a Thread. The View or the Thread can contain the objects that you draw/interact with, its up to you how you want to store the data at this point but its easiest if you come up with a design that has the least coupling between classes.
Once started, the Thread runs constantly until stopped (setting isRunning to false):
/**
* Processing loop
*/
public void run() {
while (isRunning) {
try {
sleep(25);
} catch (InterruptedException e) {
Log.e("Thread","Thread Interruption");
e.printStackTrace();
}
update();
}
Log.d("Thread", "Game Loop Stopped");
}
/**
* Main processing of the game loop.
*/
private void update() {
handleInput();
updatePhysics();
updateUI();
updateState();
updateAI();
updateAnimations();
updateSound();
updateVideo();
}
In this class you see the update() method that does a bunch of actions each iteration of the thread.
The methods that will interest you mostly are the handleInput, updateUI and updatePhysics methods.
In the handleInput you'll do a callback to the SurfaceView to get the data that you need for processing information. My handleInput is fairly simple in that it just grabs the MotionEvent from the SurfaceView class's onTouchEvent (this gets implemented when you use the SurfaceHolder.OnCallBack interface).
The updateUI method calls the SurfaceView's update where it re-draws the Canvas with each object, or balloon
public void update(List<Actor> actors) {
Canvas canvas = null;
try {
canvas = surface.lockCanvas();
synchronized (surface) {
//Blank the Canvas
for (int i = 0; i < actors.size(); i++) {
actors.get(i).draw(canvas);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
} finally {
if (canvas != null) {
surface.unlockCanvasAndPost(canvas);
}
}
}
Here we can see that it calls the draw method passing the canvas object to each one of your interactable objects. I've called mine "Actors" in the code above. How you choose to implement draw is up to you but it sounds like you'll be using a lot of canvas.drawBitmap() functions.
Going back to the Thread's updatePhysics method you'll want to use it to update the objects before or after they're drawn to the screen. For you you'll want to have them change their X and/or Y positions on the screen or change the direction its moving after the handleInput decides you've hit a balloon.
Its very hard to explain this well in a StackOverflow reply. If you really want I can try to put something more informative together this weekend and post it externally for you (I can provide my UML class diagrams among other information such as picture examples, structures and data flows.
Please let me know if I can help you further! Please note that this isn't all my work. I used a lot of tutorials online for basic Android Game structure but don't have the links available right now to provide references.

Android game scrolling background

I'm just trying to figure out the best approach for running a scolling background on an android device. The method I have so far.... its pretty laggy. I use threads, which I believe is not the best bet for android platforms
#Override
public void run() {
// Game Loop
while(runningThread){
//Scroll background down
bgY += 1;
try {
this.postInvalidate();
t.sleep(10);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
where postinvalidate in the onDraw function simply pushings the background image down
canvas.drawBitmap(backgroundImage, bgX, bgY, null);
Thanks in advance
UPDATE
I've identified the problem. And it is the fact that my player updates the same rate as the background scrolls (making it look choppy). from top to bottom. This is because both get drawn in the same function. I'm not really sure how to tackle this and would be grateful for any help. i.e so that player movement is handled separately from the map scrolling
Also how can I control the speed at which onDraw(canvas) get called?
Thanks in advance.
However, I have patched together a different run loop for anyone having the same problem. This is partially from the jetboy example on google.
Below is my inner class in my surfaceview
class MapThread extends Thread{
private Map map;
private SurfaceHolder holder;
private boolean run = false;
public MapThread(Map map, SurfaceHolder holder){
this.holder = holder;
this.map = map;
setRunning(true);
}
public void setRunning(boolean run){
this.run = run;
}
#Override
public void run(){
while(run){
try{
Canvas c = null;
try {
c = holder.lockCanvas(null);
synchronized (holder) {
map.onDraw(c);
}
} finally {
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
}
}
SOLUTION
https://gamedev.stackexchange.com/questions/8127/android-game-scrolling-background
Use the SurfaceView implementation draw on the screen. It allows you more control of what to draw and when.
The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy. The aim is to offer this drawing surface to an application's secondary thread, so that the application isn't required to wait until the system's View hierarchy is ready to draw.
The basic design is to have a surfaceview that draws continuously in a while loop. Then add an if-statement whose condition is to be true if a timer thread tells you its time to draw. Say, every 30ms, draw the bitmap. This will give you about 33 fps.
Now you may also have another timer thread that tells you when to update the the bgX or bgY values. Say at every 60ms, it will set a boolean updateFlag = true; Then in your main thread, you have an if-statement check this flag, set it to false, and update your bgX and bgY values. By accurately controlling the timer and the bgX/bgY increments, you should be able to produce smooth animations.
It would be a good idea to look at the LunarLander source code provided by Google.
One thing to keep in mind is that sleep is very inaccurate. To work around this, you can keep track of exactly how much time passed during the sleep and update how much you move things accordingly.
Its not clear from you code, but you need to make sure that all of your UI updates happen in the UI thread.
You do need to do your timing outside of the UI thread, because otherwise the UI will never update. There are other methods of timing, like using a Handler that can be a little bit cleaner, but I think the overhead on them might be a bit much for what you are trying to do. I think a simple thread has the least amount of overhead.
I am using this method on the second level of my SpaceQuestAlpha game. This makes a seemless scroll.
I used the 2 lines below to set original position.
moony=0;
moon2y=-(heighty);
Then these lines increment both versions of the background image. One starts at 0 and one starts at negative screen height. Every time one of the images goes below the bottom of the screen it is moved up twice the height to move it back into position. I am using surface view with no latency issues.
moony+=5;
moon2y+=5;
if(moon2y>=heighty) {moon2y=moon2y-(heighty*2);}
canvas.drawBitmap(lavabackground, 0, moon2y, null);
if(moony>=heighty){moony=moony-(heighty*2);}
canvas.drawBitmap(lavabackground, 0, moony, null);

Categories

Resources