Just a random question. I'm learning a bit of Android right now, and in most examples, it seems a lot of common items (such as buttons, editboxes etc) get requested within each function using (cast) findViewById().
Is it considered good or bad practice to store the result of that in an Activity's member values? Simple example:
public class MyActivity extends Activity {
private EditText myText;
public void onCreate(blah blah) {
// blah
this.myText = (EditText) findViewById(R.id.mytext);
}
}
and use the myText field from there on. I think it'd be good for performance (depending on findViewById's inner workings, I'm quite sure it's already very fast), but I haven't seen it be encouraged yet. Also, it wouldn't be the first time I encountered a situation where 'caching' something like this leads to problems (had a case where database connections weren't released properly because I remembered a ConnectionManager or something in that fashion).
Secondly, somewhat related, if you want to remember something across methods in your Activity (and later on too, when the Activity is restarted later), is it wiser to keep up both a class field and a value in SharedPreferences, or would calling SharedPreferences each time for setting / getting the value where it's needing be a better solution? (better being 'cleaner, without impacting performance significantly)
That is completely normal practice and is exactly what you SHOULD be doing. If you're worried about memory leaks, or holding references or whatever, don't be concerned about that when dealing with views.
However, you SHOULD be careful about holding references to other contexts because that COULD cause a memory leak. That doesn't mean you shouldn't do it, just be careful about when you're doing it.
is it wiser to keep up both a class field and a value in SharedPreferences, or would calling SharedPreferences each time for setting / getting the value where it's needing be a better solution?
You should do both. You should keep a member variable for when you only need to read the data, just be sure that when you WRITE to the member variable, you also change the shared preference.
Also, it wouldn't be the first time I encountered a situation where 'caching' something like this leads to problems (had a case where database connections weren't released properly because I remembered a ConnectionManager or something in that fashion).
This is what I was saying first. It all depends on what you're storing. Views are fine to store, contexts can be dangerous, and database connections and registered listeners can cause really weird bugs. It all depends on the specific case.
Related
Whenever we need a reference to the widget, we uses findByViewById.
When we are referring the widget lots of time in the code of the same Activity class, we can follow either of the approach:
Call findViewById every time in Activity lifecycle.
Get it first time, store the reference as a private instance variable of the Activity class.
Which approach is beter? What would be pros and cons of each approach in terms of performance and memory. Please help.
EDIT: If we move to new activity from A to B, we do not finish A as we want to open A on pressing back. In this scenario how to approach above problem? Please help.
Both approaches have their risks. In general, you should call findViewById() the less times you can, by the other hand, storing a reference on the Activity class may lead to memory leaks. It depends so much on what you want to do, how much times are you calling it and basing on it choose one of the approaches. For that, you'll need to analyze your code and if you're not clear about which is better, just try both and choose the "less bad", but generally the first approach is worse than the second one because you know you'll always have to find across ALL elements you've defined an id.
Most developers use method 2, mostly because its more effective. If your layout is complicated then findViewById must traverse its tree to find given widget which takes time. In list views you mostly use ViewHolder pattern which allows you to store references to list item widgets. Since lists are redrawn very ofthen this greatly speeds up its rendering.
Storing widgets in private references is quite safe, those references gets invalidated on configuration changes, but your activity is also destroyed then.
The second possibility is clearly the better.
findViewById iterates through the whole view hierachy, which of course costs much more time than a reference.
Dianne Hackborn (Android engineer) gave some details about the topic here: https://groups.google.com/forum/#!topic/android-developers/_22Z90dshoM
Accessing a member variable is always faster than any function call. The used space for that variable is insignificant.
By the way: The code looks much cleaner!
You should decide this according to your purpose. Holding an object for your views are faster than getting your view with an activity method. But this also means that you are using a memory for your reference and it can cause a memory leak.
I may be wrong since i am new to Android, but i prefer storing a a variable;
it's less coding to write.
for example: if you have to access an imageview that is nested in layouts how would you wish to access it and get its tag.
Access 1:
public Integer getTag(){
FrameLayout frame1 = (FrameLayout) findViewById(R.id.frame_1);
LinearLayout linear3 = (LinearLayout) frame1.findViewById(R.id.linear_3);
ImageView imgView = (ImageView) linear3.findViewById(R.id.myImg);
return Integer.valueOf( imgView.getTag().ToString());
}
Access 2:
private ImageView myImageView;
#Override
public void onCreate( Bundle savedInstanceState){
//set access to variable
}
public Integer getTag(){
//return Integer.valueOf( myImageView.getTag().ToString());
//can be written
Integer mTag = Integer.valueOf(myImageView.getTag().ToString());
return mTag;
}
My app has some UI elements that are based on some settings from the user and I am not sure how I should go about coding this for best performance and there doesn't seem to be a good way to Google this to try to find if this has been asked previously.
Basically I want to check for the App Version UI set in the settings and I currently do it via a function:
public String appVersion() {
appSettings = currentActivity.getSharedPreferences(APP_SETTINGS, 0);
String prefAppVersion = appSettings.getString("appVersion", "v2");
return prefAppVersion;
}
Then I will display certain UI elements via an if/else statement:
if (appVersion().equals("v2")) {
// do something here
}
else {
// do something else
}
Is this going to cause memory problems if I call the function 5-6 times within my app (getting a SharedPreference over & over again) or am I better somehow declaring a global variable that gets the SharedPreference once and then uses that for the tests? My only concern with that being if the Preference changes and the UI needs to be redrawn if the variable is not reset.
Your thoughts / input is greatly appreciated.
I don't think the appVersion function will cause any memory problem, but maybe make appSettings as a local variable would be a better practice.
I don't understand the second question, do you mean how to know the preference being changed? SharedPreferences.OnSharedPreferenceChangeListener may help you.
i am new in android and java ... i am reading from couples of day about android parceling tutorial for transfer data or variables values from one activity to other or one class to other ... but i am not so understood about that.
can u tell me that is it necessary to use Parcelable for this purpose because same task can also be perform using static key word for variables as string,int or array type then why parcelable pls explain in detail ..
thanks for explanation in advance please provide comparison with example
While technically both approaches will work, there are a couple of flaws.
The first is that the static variable is static. If you have two instances of the same activity, they will both reference the same static object. This is probably not what you want.
Secondly, it's considered bad practice to access global variables. It makes it difficult to see what is going on, is difficult to test and you someone (another class) can modify your data. This creates some horrendous bugs.
By passing the data via a Parcelable object it is very clear what you are doing and you avoid both of these problems.
Note that this advice is not specific to Android, rather to Java and programming in general.
Static references never get garbage collected so you end up creating something called a memory leak.
You are keeping an object in memory that you don't need and it can't be freed up.
If you instantiate enough objects like this you will get an out of memory (oom) exception which will cause the app to crash.
I know rule #1 of optimization is: don't do it! But I figured this was an easy question, and if I start using the faster method now I can save a lot of cpu time when I'm finished.
I'm making an RPG, and let's say this is part of a custom class:
public class Baddie{
int health;
int magic;
public Baddie(int health, int magic){
this.health = health;
this.magic = magic;
}
public int getHealth(){
return health;
}
Now, the answer to my question may be "there's no difference" and that's fine with me.. I just want to know. Is it quicker to get the Baddie's health using field access:
//Somewhere in the main thread, I get an instance of Baddie..
Baddie b = getScaryBadGuy();
int baddieHealth = b.health;
Or is it quicker to use a return method?
int baddieHealth = b.getHealth();
Copied and pasted from Designing for Performance:
Avoid Internal Getters/Setters
In native languages like C++ it's
common practice to use getters (e.g. i
= getCount()) instead of accessing the field directly (i = mCount). This is
an excellent habit for C++, because
the compiler can usually inline the
access, and if you need to restrict or
debug field access you can add the
code at any time.
On Android, this is a bad idea.
Virtual method calls are expensive,
much more so than instance field
lookups. It's reasonable to follow
common object-oriented programming
practices and have getters and setters
in the public interface, but within a
class you should always access fields
directly.
Without a JIT, direct field access is
about 3x faster than invoking a
trivial getter. With the JIT (where
direct field access is as cheap as
accessing a local), direct field
access is about 7x faster than
invoking a trivial getter. This is
true in Froyo, but will improve in the
future when the JIT inlines getter
methods.
Performance is always relative. It's usually better to think in terms of percentages or factors. If something takes a microsecond, maybe that's a lot, and maybe it's nothing. It depends on how many times per second you need to do it. That's the main reason premature optimization is frowned upon, it is done without knowing if there is a problem.
The compiler will optimize if it can. This is a perfect example of premature optimization. use whatever makes sense in your code. Don't worry about "saving cycles". The 2-3 cycles this may or may not save is outweighed by the millions of cycles it takes for any other operation.
IMO it's more a design question than optimization question. I would suggest not writing/generating any getter or setter until you actually need them to be accessed from outside of your class. This tends to keep coupling as low as possible.
Alternatively making those getters/setters private by default would have the same result but it's more code for no real benefit.
This is probably an easy one. I have about 20 TextViews/ImageViews in my current project that I access like this:
((TextView)multiLayout.findViewById(R.id.GameBoard_Multi_Answer1_Text)).setText("");
//or
((ImageView)multiLayout.findViewById(R.id.GameBoard_Multi_Answer1_Right)).setVisibility(View.INVISIBLE);
My question is this, am I better off, from a performance standpoint, just assigning these object variables? Further, am I losing some performance to the constant "search" process that goes on as a part of the findViewById(...) method? (i.e. Does findsViewById(...) use some sort of hashtable/hashmap for look-ups or does it implement an iterative search over the view hierarchy?)
At present, my program never uses more than 2.5MB of RAM, so will assigning 20 or so more object variables drastically affect this? I don't think so, but I figured I'd ask.
Thanks.
Yes, this would be correct to cache references to the views. That's what the ListView's Tag/Holder is about which is there for performance reasons.