I noticed myself constantly typing:
someVar = getResources().getString(R.string.someString);
I have several XML files that I am parsing and building and in order to make sure that the files stay consistent, I have placed the tag names in the res/values/strings.xml file. The same handles are used throughout several activities, and some of those activities extend ListActivity while others do not so creating a simple super class which houses these variables ( ex:
public class thisClass extends thatClass
{...}
public class thatClass
{
package String someTag = "this";
package String otherTag = "that";
}
I would assume that all of these calls to getResources() could get pretty taxing and was wondering if it is beneficial to instead create an R-type file where I can store these types of commonly used variables statically ex:
public final class globalVars
{
public static final class XML_TAGS
{
static final String someTag = "this";
static final String otherTag = "that";
}
}
and to reference these variables like such:
serializer.startTag("", globalVars.XML_TAGS.someTag);
instead of
serializer.startTag("", getResources().getString(R.string.someTag));
Thanks for the input!
OK, after looking into the source code of android.content.res.resources and some other classes, it is evident that using Resources and getting resources through getResources() is costly compared to a static class.
Indeed, the instance of Resources returned is not a static container but rather an object that gets resources by executing a couple of statements (whether a string or drawable or any other form).
However, using getResources() has its advantages:
It helps you externalize your resources.
For any type of resource, you can specify default and multiple alternative resources depending maybe on Locale, Screen Depth/Resolution...
A static container might provide a less costly alternative than using resources but remember: any later attempt at localization would be relatively extremely costly.
Related
Why the R class in android is not static? when it contains all static content.
public final class R {
//static content
}
As per Java language policies, A top level public class cannot be static. And when you dive deep into the usage of static class you will find it is used to create independent inner class that does not hold anonymous reference of outer class. Therefore the purpose and use of static keyword before class is completely different.
non-static inner class
class A
{
int var1;
class B{
int calc(){
// can access A.var1 directly
}
}
}
static inner class
class A
{
int var1;
static class B{
int calc(){
// cannot access A.var1 directly, need object to be passed
}
}
}
R.java is the dynamically generated class, created during build process to dynamically identify all assets (from strings to android widgets to layouts), for usage in java classes in Android app. Note this R.java is Android specific (though you may be able to duplicate it for other platforms, its very convenient), so it doesn't have much to do with Java language constructs.
android.R.java is not just where XML ids are stored. It also contains access to resources - such as drawables, layouts, strings, arrays, and basically anything you can declare in resources.
Personally I find that it is useful when using Eclipse. I can simply type findViewById(R.id. and Eclipse will show a tooltip with a list of options to choose from.
However at a platform level, I would say that the hardcoded id variables help prevent errors when using Strings to identify resources -- something that can be debuggable while programming (or during compilation, rather than runtime).
In several tutorials, I've seen result codes set as "private static final int"s at the top of pertaining activities. To me this does not seem like the best way to do this since I find myself having to constantly refer to other classes to find the correct code rather than referring to the same code created somewhere else.
Is there a better way to do this? Is it bad practice to just make a utility class to hold the common result codes, request codes, data keys, etc? I've just never seen this done before.
Another way is to keep this variables in Gradle build and use them like this: BuildConfig.VARIABLE
Example:
In gradle file:
buildTypes {
release {
buildConfigField "java.lang.String", "DATABASE_NAME", "\"db_name\""
}
}
In Java:
BuildConfig.DATABASE_NAME
Pros:
can change constants values for different builds
there is one place with all program constants
auto generated (BuildConfig) by IDE/Gradle
References:
0.14.3 http://tools.android.com/tech-docs/new-build-system
http://toastdroid.com/2014/03/28/customizing-your-build-with-gradle/
I think it's personal preference, although it seems more meaningful to have all your statics in utility class. The tutorials probably show them in Activies for simplicity which is far easier to understand than using utility classes when they only need a couple of statics.
If you need to share constants for few classes, you can create special "constants" class and refer to it.
package ru.kopeyko.***;
/**
* class for holding various CONSTANTs for '***' app
*
* #author Andrey Kopeyko <andrey#kopeyko.ru>
*/
public final class Const {
public static final String UUID_DEFAULT = "00000000-0000-0000-0000-000000000000";
public static final String VERSION_CODE = "versionCode";
public static final long ONESECOND = 1000L;
public static final int POSITIONS_MAX_DAYS = 32;
public static final long DB_MAINTENANCE_INTERVAL = 1*86400*1000L;
}
I am working on my first Android Project. I have a Service class that waits for receive intents to retrieve some information from a remote server. This service of mine looks something like this:
public class MyService extends IntentService{
public static final String ACTION_INTENT_01 = "xyz.actionIntent01";
public static final String ACTION_INTENT_02 = "xyz.actionIntent02";
public static final String ACTION_INTENT_03 = "xyz.actionIntent03";
... A lot of constant more...
public static final String ACTION_INTENT_01_EXTRA = "xyz.actionIntent01Extra";
...more and more constants...
public MyService(){
...
}
/*The Rest of The Service*/
}
My question is, what is better, having a lot of constant strings inside this class or declare them on the String.xml file and access them by getString(R.string.ACTION_INTENT_03) ??
Thanks!
None of these. I would recommend to have a constants class and put these constants in that class. In this way your service class is smaller and easier to maintain.
You should put strings in strings XML files only if those are subject for localization changes: in English have a specific value, in French a different value and so on. Or if you want to use them in XML UI layouts. So if you have constants to use only in code, there's no reason to have them in XML strings.
You can do in both ways. Personally I declare the strings that are showed in the UI into strings.xml, and string constants in the source code.
One reason the string resources to be declared in the strings.xml is that later they are easy to localize.
Declare them in strings.xml because if you are modifying value that modified will be reflected everywhere.
I'm developing an android application which uses web service to get data from server, for that I'm having three different set of URLs to point development system, test server and live server. It's difficult to change URL whenever I want to give application for testing/live. so I planned to make it as configurable, so that application can get appropriate URL based on me build type configuration constant.
So,
which is the best way to keep this constants, java static class or
java public interface or xml resource file.? When? Why?
which gives better performance?, When? Why?
Ex: xml resource
<integer name="config_build_type">0</integer>
<string-array name="url_authentication">
<item >http://development.com/xxxx</item>
<item >http://test.com/xxx</item>
<item >http://example.com/xxx</item>
</string-array>
Java static constant
public class Config {
public static final int BUILD_TYPE = 0; // 0 - development, 1 - test, 2 - live
public static final String[] URL_AUTHENTICATION = {"http://development.com/", "http://test.com/", "http://example.com"};
}
There is a big difference between the two in that you can reference project resources in your XML layouts. They are available in the application context and are therefore accessible across the global application. The biggest advantages of using project resources is the ease of access and that they allow you to organize your project significantly.
static final constants are compiled into the java bytecode; project resources are compiled into a binary format within the apk. Accessing either is extremely efficient... if there is a difference between the two, it is trivial at most.
There isn't a set rule on how you should be using resources/constants in your project. That said, I personally use resources for values that I might need to use in my XML or java code. On the other hand, I typically use static final constants for values that will only be used by my java code and are specific to my implementation.
Also note that it is possible to load XML resources at runtime depending on the device's current configuration (i.e. screen size, locale, etc.). So you should take this into consideration when deciding whether or not you should declare the constant in XML or directly in your .java files.
For the people who want to see how we can use a Class to define our constants and call any where we need.
Constant.java
package org.nrum.nrum;
/**
* Created by rajdhami on 5/23/2017.
*/
public class Constant {
public static final String SERVER = "http://192.168.0.100/bs.dev/nrum";
// public static final String SERVER = "http://192.168.100.2/bs.dev/nrum";
public static final String API_END = SERVER + "/dataProvider";
public static final String NEWS_API = API_END + "/newsApi";
public static final String BANNER_API = API_END + "/bannerApi/lists";
public static final String NOTICE_API = API_END + "/noticeApi/lists";
public static final String UPLOAD_PATH = SERVER + "/uploads";
public static final String UPLOAD_PATH_BANNER = UPLOAD_PATH + "/company_1/banner";
public static final String UPLOAD_PATH_NEWS = UPLOAD_PATH + "/company_1/news";
public static final int BANNER_TRANSITION_DURATION = 5000;
public static final int NOTICE_BUTTON_BLINK_DURATION = 5000;
public static final int BANNER_FETCH_LIMIT = 3;
}
Now we can use above constants in following way.
Constant.NOTICE_BUTTON_BLINK_DURATION
In general case:
XML values have the advantage of accessbilty in layout file and manifest file over Constants in java file
XML values have the advantage for multi language support over Constants in java file
It’s always a good practice to extract UI strings from your app code and keep them in an external file. Android makes this easy with a resources directory in each Android project.
http://developer.android.com/training/basics/supporting-devices/languages.html
I think both way seems to be good but thing is that it depends on your requirements.
If you have your values(web service link) in your XML and suppose there is any change in your values(web service link) , you can easily change only in XML file.
But if you use inside classes as static variables you have to change in all class files.
So my suggestion is that separate constants from source file and put into resource and access it..
If the constant related or depend on locale or language or use in manifest you may consider to use xml values
If the constant dont't related to translation or locale or use in manifest I would avoid to put it in xml resource
I would add enum inside the viewmodel or whatever that need to use constant as a key.
enum class Key{
key,rule,practice
}
Or
const val MY_CONST = "my constant"
In Kotlin:
class Foo() {
// any other code for the class Foo
companion object {
const val MY_CONSTANT = "my constant"
}
}
This method is particularly recommended for data object.
Project resources need access to Context, which is not available in static methods unless you pass it in, but is always available in Activities -- there seems to be a preferential connection between resources and layouts.
For app variables and constants that may be processed in static methods I create an abstract class and do a static import (of this constants class) in all the other project class files.
R class on android has it's limitations. You can't use the resources dynamically for loading audio, pictures or whatever. If you wan't for example, load a set of audio files for a choosen object you can't do something like:
R.raw."string-upon-choosen-object"
I'm new to android and at least I didn't find how you could do that, depending on what objects are choosen or something more dynamic than that. So, I thought about making it dynamic with a little of memory overhead. But, I'm in doubt if it's worth it or just working different with external resources.
The idea is this:
Modify the ant build xml to execute my own task. This task, is a java program that parses the R.java file building a set of HashMaps with it's pair (key, value). I have done this manually and It's working good. So I need some experts voice about it.
This is how I will manage the whole thing:
Generate a base Application class, e.g. MainApplicationResources that builds up all the require methods and attributes. Then, you can access those methods invoking getApplication() and then the desired method.
Something like this:
package [packageName]
import android.app.Application;
import java.util.HashMap;
public class MainActivityResources extends Application {
private HashMap<String,Integer> [resNameObj1];
private HashMap<String,Integer> [resNameObj2];
...
private HashMap<String,Integer> [resNameObjN];
public MainActivityResources() {
super();
[resNameObj1] = new HashMap<String,Integer>();
[resNameObj1].put("[resNameObj1_Key1]", new Integer([resNameObj1_Value1]));
[resNameObj1].put("[resNameObj1_Key2]", new Integer([resNameObj1_Value2]));
[resNameObj2] = new HashMap<String,Integer>();
[resNameObj2].put("[resNameObj2_Key1]", new Integer([resNameObj2_Value1]));
[resNameObj2].put("[resNameObj2_Key2]", new Integer([resNameObj2_Value2]));
...
[resNameObjN] = new HashMap<String,Integer>();
[resNameObjN].put("[resNameObjN_Key1]", new Integer([resNameObjN_Value1]));
[resNameObjN].put("[resNameObjN_Key2]", new Integer([resNameObjN_Value2]));
}
public int get[ResNameObj1](String resourceName) {
return [resNameObj1].get(resourceName).intValue();
}
public int get[ResNameObj2](String resourceName) {
return [resNameObj2].get(resourceName).intValue();
}
...
public int get[ResNameObjN](String resourceName) {
return [resNameObjN].get(resourceName).intValue();
}
}
The question is:
Will I add too much memory use of the device? Is it worth it?
Regards,
I'm new to android and at least I
didn't find how you could do that,
depending on what objects are choosen
or something more dynamic than that.
The Resources class has a getIdentifier() method that will give you the resource ID given the name as a string. This uses reflection, so you would want to cache the results, perhaps using a LinkedHashMap as an LRU cache.
Is it worth it?
IMHO, not really. I would just use getIdentifer() or directly use reflection myself. In fact, I have directly used reflection myself (with the LRU cache) to address this issue.