Several TextViews or Concatenated Strings? - android

Approach 1: In an android app there is shown a duration TextView (like: "2 h 45 m") and another TextView with number of Stops (like: "Stops: 15"). Between them is another TextView (" | ") to separate them.
Approach 2: using only one TextView, a String template and concatenation to put it together.
Consider the data (2 45 and 15) comes from backend and the number of stops isn't really logically connected to the duration.
My Question is:
Which approach is more efficient considering performance and code-maintainability?
Is there a better way of doing this or are there any best practices?
Thank you

You don't need multiple TextViews for this. You have a format and just want to put values in there. I would suggest the following way
int h = 2;
int m = 45;
int s = 15;
String format = String.format("%dh %dm | Stops: %d ", h, m, s);
Now assign format string to your one TextView

Related

How to loop through an int to determine the "," for dollars

I have int values I take from seekBars, and display them in a TextView via ValueOf(). I am wondering if there is a way to implement a method to turn 1000 to 1,000 or 100000 to 100,000 without endless comparing and if statements. or point me in the right direction? Thanks.
You can use the NumberFormat class to convert the numbers based on the user's locale:
int i = 1000000;
String str = NumberFormat.getIntegerInstance().format(i);
Output: 1,000,000

Android - Randomly setting a button in a grid

this is an extension to this question: Android - Handling a grid
Basically, I am wondering how to make a grid of 4x4 buttons randomly change their features(text, color, etc.) I don't need help setting the actual change in text or color, I just need a way to go about something like this. I don't know if I should write an array and choose from there, or use the GridView. Just a little start to something is all I need, I'm not asking for lots of code. Thanks in advance, I really appreciate it.
If your 4 ids are sequential as is
btnId1 = 8006;
btnId2 = 8007;
btnId3 = 8008;
btnId4 = 8009;
Random rn = new Random();
int chooseId = btnId1 + rn.nextInt(btnId4 - btnId1 + 1);
You can generate a random number like so:
Random r=new Random();
r.nextInt(4);
this will give you a random number in the range [0,4).
Based on this random number, you change the properties of the appropriate tile/square which you can enumerate yourself from 0 to 3 since you have 4 tiles in total.
From both your questions it seems that you lack some basic programming knowledge of algorithms/approaches to problems. You should try to fill that gap, which will make you progress MUCH MUCH faster in your programming endeavors!

How to displaying Float/Double in meaningful form in Android

I am trying to make a BMI application. When I run the application the BMI values are displayed in numeral form that I don't understand. I have tried both Float and Double type but results are same.
For example:
Height (m): 2
Weight (Kg): 100
BMI is displayed as : 2.0E-4 instead of 25
The part of the code that effects this is:
String editText1= height_field.getText().toString();
String editText2= weight_field.getText().toString();
try { // Parse string to int
double height = Double.parseDouble(editText1);
double weight = Double.parseDouble(editText2);
double bmi_result = (weight/(height*height));
String bmi_text = Double.toString(bmi_result);
display.setText(bmi_text);
System.out.println("OnClick: computeButton is clicked");
}
catch(NumberFormatException nfe) {
alert.show(); // Show error alert
To answer your original question, you should be using java.text.DecimalFormat, something like:
DecimalFormat formatter = new DecimalFormat("##.##");
display.setText(formatter.format(bmi_result));
Will force the result to be in the format of two digits followed by two decimal points, the table in the link above shows how to generate that.
However, since 2.0E-4 is 0.0002, I think Jon Skeet's comment is correct: You're doing your math operation wrong, since the value you're printing is a very small fraction of 25 :)
I'd recommend using Log.v() to print out your math operation before you actually do it, so you can see what the values of weight and height actually are, I highly doubt they're correctly set at what you described in the question.

Double # showing 0 on android

I'm embarrassed to ask this question, but after 45 minutes of not finding a solution I will resort to public humiliation.
I have a number that is being divided by another number and I'm storing that number in a double variable. The numbers are randomly generated, but debugging the app shows that both numbers are in fact being generated.
Lets just say the numbers are 476 & 733. I then take the numbers and divide them to get the percentage 476/733 = .64
I then print out the variable and it's always set to 0. I've tried using DecimalFormat and NumberFormat. No matter what I try though it always says the variable is 0. I know there is something simple that I'm missing, I just can't find it =/.
I imagine that you are trying to do something like this:
int x = 476;
int y = 733;
double result = x / y; // result == 0
The problem here is that you are performing integer division which gives the answer 0, and then afterwards converting the result to a double. You need to convert one or both of the numbers to floating point numbers before dividing. Here's one way to do that:
int x = 476;
int y = 733;
double result = ((double)x) / y;
I presume the 2 numbers that are being divided are "double" types?
Have you used debug mode to see the result of the division?

ANDROID How to reduce String allocations

I've managed to get my allocations down to next to nothing using DDMS (great tool), this has drastically reduced my GCs to about 1 or 2 every 3 minutes. Still, I'm not happy because those usually cause a noticeable delay in the game (on some phones) when you interact with it.
Using DDMS, I know what the allocations are, they are Strings being converted from integers used to display game information to the HUD.
I'm basically doing this:
int playerScore = 20929;
String playerScoreText = Integer.toString(playerScore);
canvas.drawText(playerScoreText, xPos, yPos);
This happens once each frame update and the HUD system is modular so I plug things in when I need and this can cause 4 or 5 hud elements to allocate Strings and AbstractStringBuilders in DDMS.
Any way to reduce these further or eliminate all the String allocations and just reuse a String object?
Thanks,
Albert Pucciani
Reading your question reminded me of one of Robert Greens articles that I read quite some time ago. It discusses your problem almost identically. http://www.rbgrn.net/content/290-light-racer-20-days-32-33-getting-great-game-performance . Skip down to day 33 and start reading.
Remember the last int score and its string representation. On a new frame check if the score is the same. If the same, then no need to create a new string - just use the old one.
Here's what I've done in the past. This will eliminate string allocations.
I create a char[] of a size that will be at least as large as the maximum number of characters you will need to display on the screen. This means that you should select a maximum high score that is achievable in the game. The way you have it now let's you display a score as high as 2^31-1 which is insanely huge, it's not practical with respect to the game. Keep in mind, this is your game, so it's ok to limit the max score to something more reasonable in the context of the game. Pick a number that will virtually be impossible to achieve. Setting this limit will then set you up to be able to not have to muck around with converting large integers to String objects.
Here's what's required:
First, you need to be able to separate the digits in an integer and convert them to char without creating String objects. Let's say you want to convert the integer of 324 into three separate characters '3','2','4' to be placed in the text char[]. One way you can do this is by taking the value 324 and do a mod 10 to get the lowest digit. So 324%10 = 4. Then divide the value by ten and do another mod 10 to get the next digit. So (324/10)%10 = 2, and (324/100)%10 = 3.
int score = 324;
int firstPlaceInt = score%10; // firstPlace will equal 4
int tensPlaceInt = (score/10)%10; // tensPlace will equal 2
int hundresPlaceInt = (score/100)%10; // hundredsPlace will equal 3
You will have to do the above in a loop, but this expresses the idea of what you're trying to do here.
Next, with these digits you can then convert them to chars by referencing a character map. One way to do this is you can create this character map by making a char[] of size 10 and placing values 0 - 9 in indexes 0 - 9.
char[] charMap = {'0','1','2','3','4','5','6','7','8','9',};
So doing this:
int score = 324;
char firstPlace = charMap[score%10];
char tenslace = charMap[(score/10)%10];
char hundredsPlace = charMap[(score/100)%10];
Will create the chars you need for the 3 digits in score.
Now, after all that, I would limit the highest score to say 99,999 (or whatever makes sense in your game). This means the largest "string" I would need to display is "Score: xx,xxx". This would require a char[] (call it text for this example) of size 13. Initialize the first 7 characters with "Score: ", these will never need to change.
char[] text = new char[13];
text[0] = 'S';
text[1] = 'c';
text[2] = 'o';
text[3] = 'r';
text[4] = 'e';
text[5] = ':';
text[6] = ' ';
The next 6 will vary based on the score. Note, that you may not necessarily fill in all 6 of those remaining characters, therefore you need to create an int (call it scoreCount for this example) which will tell you how many characters in the text char[] are actually relevant to the current score in the game. Let's say I need to display "Score: 324", this only takes 10 chars out of the 13. Write the 3 chars for the score of 324 into char[7] to char[9], and set scoreCount to 10 to indicate the number of valid characters in the char[].
int scoreCount = 7;
text[9] = charMap[score%10]; // This is firstPlace
text[8] = charMap[(score/10)%10]; // This is tensPlace
text[7] = charMap[(score/100)%10]; // This is hundredsPlace
scoreCount = 10;
You will probably have to do the above in a loop, but this should express the general idea of what you're trying to do here.
After that, you can just use drawText (char[] text, int index, int count, float x, float y, Paint paint). index will be 0, and count will be scoreCount which indicates how many characters in text should be drawn. In the example above, it doens't matter what's in text[10] to text[12], it's considered invalid. You can continue to update text[] using the character map, and this should not create any objects.
I hope this helps. The code above isn't very robust, but I wrote it out as more of an expression of the ideas I'm trying to convey. You will have to create your own loops and manage the data properly within your code, but this sums up the mechanics of what needs to happen to avoid the use of Strings/StringBuilder/StringBuffer/etc.

Categories

Resources