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.
Related
This is possibly the noobiest of noob questions, but I can't find the answer anywhere - maybe because I have my terminology wrong, maybe because it's not possible.
What I'm trying to do is determine whether a chronometer widget in Android is running, but the more general question is:
How do I read the field values that I can see in the IDE/debugger programatically?
For example, if I set a breakpoint after my chronometer is started, in the variables list (or when evaluating the chronometer), I can see a load of useful stuff all beginning with the letter 'm'. For example, mVisible, mRunning, mStarted, but I can't for the life of me figure out how to access them.
I'd like to know if this is possible in both Java and Kotlin, please. I've attached a screengrab of what I'm talking about :)
Thanks,
Iain
I think I've worked this out. I've declared an extension function:
fun Chronometer.isRunning(): Boolean {
val f = this::class.java.getDeclaredField("mRunning")
f.isAccessible=true // make it readable
return f.get(this) as Boolean
}
I can then read the value of mRunning with myChronometer.isRunning()
Suggestions for improvements are welcome. :)
I have a test case for my app which fills in the TextViews in an Activity and then simulates clicking the Save button which commits the data to a database. I repeat this several times with different data, call Instrumentation.waitForIdleSync(), and then check that the data inserted is in fact in the database. I recently ran this test three times in a row without changing or recompiling my code. The result each time was different: one test run passed and the other two test runs reported different data items missing from the database. What could cause this kind of behavior? Is it possibly due to some race condition between competing threads? How do I debug this when the outcome differs each time I run it?
Looks like a race condition.
remember in the world of threading there is no way to ensure runtime order.
I'm not an android dev so I'm only speculating but UI is only on one event thread generally so when you call the method from another thread (your test) you're probably breaking that as you're outside of the event thread.
You could try using a semaphore or more likely a lock on the resource.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html
I (finally!) found a solution to this problem. I now call finish() on the tested Activity to make sure that all of its connections to the database are closed. This seems to ensure consistency in the data when I run the assertions.
I would suggest making a probe for the database data rather than a straight assert on it. By this I mean make a piece of code that will keep checking the database for up to a certain amount of time for a condition rather than waiting for x seconds (or idle time) then check, I am not on a proper computer so the following is only pseudo code
public static void assertDatabaseHasData(String message, String dataExpected, long maxTimeToWaitFor){
long timeToWaitUntil = System.getCurrentTimeMillis() + maxTimeToWaitFor;
boolean expectationMatched = false;
do {
if(databaseCheck() == dataExpected){
expecttionMatched == true;
}
}while(!expectationMatched && System.getCurrentTimeMillis() < timeToWaituntil);
assertTrue(message, expectationMatched);
}
When i get to a computer i will try to relook into the above and make it better (I would actually of used hamcrest rather than asserts but that is personal preference)
Philosophically, is it better to work with preferences throughout some code, getting and setting the values as the user interacts with the activity; or is it better to work with class fields, then later in some onDestroy() perhaps, set the preferences to the final values of the class fields than one wants to save.
//-- Is this better?
if (a==preferences.getInt(pref1,default){
preferenceEditor.putInt(pref2,someNumber);
}
//-- Or is this?
if (a==field1){
field2 = someNumber;
}
...
onDestroy(){
preferenceEditor.putInt(pref1,field1);
preferenceEditor.putInt(pref2,field2);
}
So, please don't "work with preferences".
What you're doing there (in your first sample) is interaction with a global variable. Never do this if you can help it. It's an anti-pattern. You don't want globals in your code. It makes the code harder to understand / harder to test. Instead, whenever you instantiate a class, read your global settings and add them to your class' fields (preferably in the constructor). The class itself must NOT know about your preferences storage.
Also, DO NOT USE onDestroy (WTF?). Here's a note from the reference:
Note: do not count on this method being called as a place for saving data!
Instead, place that logic in onPause().
for performance reasons fields should be preferred over preferences, but it also depends on how often the values change
I am new to Android and have learned a lot with this project. I am almost there but, but one of my missing parts is... the game does something like the Simon Says game, and right now I am able to click on the Images and it also loops through them for the user but I can touch them while the loop goes through them. I want now to be able to set like a boolean flag that says userTurn if 0 then it's user turn and if 1 then its the system. Something of that sort.
What would be the best way to approach this?
If the various states in which your application can be in is very large and/or complex, I would recommend the state pattern. But if you just need two states, either system or user, I would use something like this:
private boolean isSystemTurn = false;
and then check it like that:
if (isSystemTurn) {
// the user has to wait
} else {
// it is user turn
}
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.