I have a question regarding performance and best approach for my Android code.
What I need to do is fairly simple, I want to dynamically assign a text value to a string ressource, depending on a int parameter:
For now I am using a big switch case
int messagesCategory;
if(extras !=null) {
messagesCategory = extras.getInt("category");
}
TextView titleText;
titleText = (TextView) findViewById(R.id.headerTitle);
switch (messagesCategory) {
case 1: titleText.setText(R.string.TitleMessageList1); break;
case 2: titleText.setText(R.string.TitleMessageList2); break;
case 3: titleText.setText(R.string.TitleMessageList3); break;
case 4: titleText.setText(R.string.TitleMessageList4); break;
case ...: titleText.setText(R.string.TitleMessageList...); break;
case n: titleText.setText(R.string.TitleMessageListn); break;
default: titleText.setText("a default title"); break;
}
Let's say I have 30 lines in this switch...
It works but for many cases, it looks there is a better way to achieve this.
Unfortunately it does not look possible to assign something dynamic to R.string..
So my first question is: 1) performance wise, in this case, is it a problem to use a big switch for 30 cases or so?
2) what should be the best approach?
Thanks and have a good day
Simple,
int[] stringIds = {R.string.TitleMessageList1, R.string.TitleMessageList2,...};
int messagesCategory;
TextView titleText = (TextView) findViewById(R.id.headerTitle);
if(extras !=null) {
messagesCategory = extras.getInt("category");
if(messagesCategory <= n)
titleText.setText(stringIds[messagesCategory]);
else titleText.setText("a default title");
}
Now, there is no switch-case and comparison,, Basic Java and Android fundamentals make it to easy and short..
As R.string.XXX is an int value generated in R.java file you have to make a just int array of that values and just get value using your int messagesCategory. And directly set it to TextView..
You can also do this:
Field f = R.id.class.getField("TitleMessageList" + String.valueOf(messagesCategory));
int val = f.getInt(null);
titleText.setText(val);
It is fast without need to load all ids in the memory.
Enjoy!
switch case is the equivalent of GOTO in your code, and there is nothing to worry about with performance.
your code is fine, may not be nice but it works and it's efficient.
I don't think 30 case statements don't hurt much except you execute them in a loop, iterating over an array, and such.
Why don't you directly use the integers which R.string gives you? Is the mapping really necessary? You could pass the R.string identifiers around. Or else, you could have a lookup in an array if you're really worried about performance.
Related
I have several objects in an activity and I would like to check their id before I perform any actions on them. However I'm not sure how to go about it, I tried :
if (v.getId().contains("empty")){
but that gives an error and then I tried
if (v.getId() == "[attr^=empty]"){
and that is also wrong. To be honest I am aware that both of these don't use proper assignments and so on but I'm really lost on how to check whether an id contains a certain substring.... I would appreciate it if someone could help
PS: v is a View object
v.getId() returns an integer. In order to check id before doing something, I'd recommend something like:
switch (v.getId()){
case R.id.ViewElement1:
//do something here
break;
case R.id.ViewElement2:
//do something here
break;
case R.id.ViewElement3:
//do something here
break;
}
What this code does is that it gets the Id of your View then compares it through a switch-case block. If the id taken from v.getId(), the code in the case block executes. The break; is important, otherwise, the code in the cases below the one executed will also run. You can also do this for an if-else if that fits your style more.
If you want to fetch the id as a string, you can try:
String ResourceIdAsString = v.getResources().getResourceName(v.getId());
and then you can do your if contains operations on the String object.
I am not entirely sure what you are trying to achieve. So there's some overview of how id works.
First you have to id all of your views in xml like:
<TextView
android:height="wrap_content"
android:weight="match_parent"
android:id="#+/myTextView" />
Then in your JAVA code use a switch case like:
switch(view.getId()){
case R.id.myTextView1:
break;
}
If you have some views that do same thing you can use them like:
switch(view.getId()){
case R.id.myTextView1:
case R.id.myTextView2:
case R.id.myTextView3:
case R.id.myTextView4:
perfomeSomeAction();
break;
}
I want to make some kinda dictionary,But not exactly a dictionary,
I have two text views, One for the word, The other one for the meaning.
I have two Buttons which they change an integer's number
And finally I have lots of if, For Example:
(if i==1){
txt1.setText("x");
txt2.setText("y");
}
(if i==2){
txt1.setText("n");
txt2.setText("m");
}
Q1: Its better with switch right?
Q2: Where should I put those Switch? In each Button's ClickListener ?
Q3: Can you suggest a better way to do that?
Switch is definitely a better option.
You can have a common API that will handle this logic like:
toggleText(int i){
switch(i){
case 1:
txt1.setText("x");
txt2.setText("y");
break;
case 2:
txt1.setText("n");
txt2.setText("m");
break;
}
}
Then u can call this API from ur button cick:
button.setOnClickListener(new View.OnClickListener{
#Override
onClick(){
toggleText(pass your value here)
}
});
Let me know if u need any help.
Switch is good option than if else
Make a function and put all switch conditions in it and call that function on button click
I'm new to bitwise operator, I don't know what are they use for, but I know the following:
5 & 3 = 1
because
0101 & 0011 = 0001
So yeah, I understand that we multiply each bit pair like 1 x 0 = 0, 1 x 1 = 1 and 0 x 0 = 0
Now when it comes to coding, I found the following code for onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch(action) {
case MotionEvent.ACTION_DOWN : {
break;
}
case MotionEvent.ACTION_MOVE : {
break;
}
case MotionEvent.ACTION_POINTER_DOWN : {
break;
}
case MotionEvent.ACTION_POINTER_UP : {
break;
}
case MotionEvent.ACTION_UP : {
break;
}
}
return true;
}
Ok firstable, the part int action = event.getAction() & MotionEvent.ACTION_MASK; what is the value of action after the operation, and what does it means? why not just simply use action = event.getAction() what's the meaning.
second, I've never seen the use of {} to define a code block for a case: is this specific because we're using the bitwise and operator or this is something totally normal and I happen to just notice that you can use them?
The reason the event is masked is to remove unrelated bits from the event. Performing bitwise-and with ACTION_MASK isolates only those particular bits. This is how you combine and test status flags that are packed into an integer. If you did not mask it, then if any other bit is set on the event, you would not be able to easily test your actions for equality.
What this is actually doing is reserving a small number of bits for an action, like having a 3-bit integer (or whatever it actually is). The mask just sets the relevant bits, so that all other bits are thrown away (ie are unimportant).
As for the braces in case statements, that's fine. You can put braces just about anywhere - it creates a a block-scope level, where any new variables you create inside that block will only exist in the block. In case statements this is quite normal, and prevents a variable in one case from "falling through" to subsequent cases. For example:
switch(foo)
{
case 0:
int i = 42;
// do something with i
break;
case 1:
// The variable i is still in scope here, which is often not
// intentional (but can sometimes be useful)
}
To stop i from falling through:
switch(foo)
{
case 0:
{
int i = 42;
// do something with i
}
break;
case 1:
// The variable i defined above is not available here.
}
In your case, the braces are superfluous, but are probably there because the person who wrote the code has adopted this practice into their coding style. Most likely they've been burned by an unwanted side-effect before, or their compiler emits warnings about variable fall-through and they've decided to just use braces all the time. Personally, I think it's cleaner to only use them when necessary.
The event that comes back from event.getAction() is actually an integer. It contains more than just information about the type of action apparently. It probably contains flags that describe the action in more detail. And by passing all that detail in through an int, it saves the use of a class object to represent the action itself.
The mask is bitwise for the first byte in the integer. Only the first two bytes out of the eight. And for comparison purposes, you need to remove the upper parts of the integer before comparing it against the actions, which are themselves only using the bottom byte of an integer.
The upper parts of the event integer are still useful for other purposes when checking against them. So the mask is 0x000000ff representing that you only want information related to the action type at the bottom and the entire event takes up the rest of it with other useful information.
This is the simplified version of my question.
There are
movieclip1
movieClip2
movieClipadd
TextA
TextB
Text C
Text answer
Touching movieclip1 should change TextA to 1 (the content should be 1)
Touching movieclip2 should change TextC to 2 (the content should be 2)
Touching movieclipadd should change TextB to + (the content should be +)
Then automatical Textanswer should give the answer. that is 3(1+2=3)
This is for mobile and I know to use ontouchbegin and ontouchend.
There's a couple of ways to accomplish what you want to do, one way would be to have a method for each operation type that you plan to have your calculator support, then you can just have a switch statement that calls the appropriate method, something like this (I got lazy and just did the operation inline, if it were more complicated would probably want methods):
switch(textB.text)
{
case '+': textAnswer.text = parseInt(textA.text)+parseInt(textC.text);
break;
case '-': textAnswer.text = parseInt(textA.text)-parseInt(textC.text);
break;
//etc.
default: throw new Error('unhandled operator');
}
assuming that you are going to use your knowledge of the touch handlers to populate the text boxes.
While I sort of agree with arunkumar due to the lack of code provided it's a simple enough problem with enough easy solutions to provide one. But note that on SO it is standard that you provide your current work and as much background information as is relevant.
So I'm trying to make a calculator app (just to get a hang of android development), and I noticed with some testing that the parseInt conversion from "String tack1" is causing the app to crash. Can someone tell me why? I can't seem to figure it out and I've been searching the internet for quite a while now. (hehe I'm a noob so please go easy) In the code below, I've modified a couple lines to make it seem obvious what it's supposed to print however it still crashes. Here's the code:
equals.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
oC = 1; //operator checker is on 1 (for plus)
switch(oC){ //check for operator clicked
case 0: break;
case 1:
tack1 = "1"; //INSERTED THIS TO MAKE OUTPUT OBVIOUS
tack1 = tack1.trim(); tack2 = tack2.trim(); //INSERTED BEFORE TO DEAL WITH WHITESPACE
numOne = Integer.parseInt(tack1); //CRASHES HERE
answer.setText(numOne);
modeChecker = 0; oC = 0;break;
NOTES ON PROGRAM(some of comments repeated and other stuff as well):
The tack1 = "1"; is to make output obvious
The tack1.trim() is to deal with whitespace
Yes whatever is in tack is a number and an integer (not even a negative integer)
Yes numOne is an integer and is defined wayy above (not in code listed here)
Sorry the indents are all messed up(after case 1) because of the comments I added
This is a section of my onClick method, so closing brackets aren't included in here.
Can someone please help me?
THANKYOU :D
I'd be willing to bet it's actually crashing on the following line AFTER the call to parseInt.
You're calling setText(int) on your TextView. When you pass an int to this method, that int is a pointer to a string resource...you're probably expecting an auto-conversion to a string. Since you are passing it an int that is generated in your application, it's extremely unlikely that this int also points to a string resource in your res/values/strings.xml file. What you really want to do is change numOne to a string first, which you can do inline:
Change
answer.setText(numOne);
to
answer.setText(String.valueOf(numOne));
and you're good to go.