I'm new to Android & Java programming but have been programming in .NET for many years. We've recently developed an android app and it's now in the final stage to be prepped for the customer (not via the market/google play btw). At any rate, while cleaning up the code. I've noticed we use a TON of strings and I'd like to cut down on this if possible. I've read a few articles and took the suggestion that anything the end-user may see, I put it in the strings.xml (for better localization, not too sure what they mean by that) but we also use SQLite table names, column names, etc. and I'd like to know the best way to construct a class (or set of classes) that allows us (my developers and I) to access them with ease.
This is how I started to construct it but wanted some opinions as to if there's a better way (design, performance issues, etc.)
public class Constants {
static enum SQLiteTableNames { Issues, Activities }
static class SQLiteTables {
static class Issues {
static class ColumnNames {
static String ID = "_id";
static String DateReceived = "DateReceived";
}
}
static class IssueActivites {
static class ColumnNames {
static String ID = "_id";
static String IssueID = "IssueID";
static String ActivityDate = "ActivityDate";
static String ActivityType = "ActivityType";
static String FullName = "FullName";
static String Notes = "Notes";
}
}
}
}
This allows us to reference column names like so:
Constants.SQLiteTables.IssueActivites.ColumnNames.ActivityDate;
Should I use final static on the properties instead of just static?
Constants should be static final. This does have a performance benefit, as it allows the value to be compiled in. It's also just good style.
By the way, the convention is to put constant names in ALL_CAPS.
Related
I'm developing an Android application and I would like to keep my SQLite query statements outside of my Java classes.
I considered using a .properties file, in which to store all of my SQL statements. Sounds fine, each property in a .properties file holds a string - I can even store prepared statements and give them the needed parameters, for example:
get.student.with.first.name=SELECT * FROM Students WHERE FirstName = ?;
However, I have also implemented Persistence Contracts for my database tables like so:
public final class StudentPersistenceContract {
private StudentPersistenceContract() {}
public static abstract class StudentEntry implements BaseColumns {
public static final String TABLE_NAME = "Student";
public static final String COLUMN_FIRST_NAME = "FirstName";
public static final String COLUMN_LAST_NAME = "LastName";
}
}
I wouldn't want to hardcode the table and column names into the entries of the .properties file, I would like to access them dynamically like so: StudentPersistenceContract.StudentEntry.TABLE_NAME, etc.
One thing I thought of was creating a class which can't be instantiated in which to "construct" the queries I need. Something along the lines of...
public final class SqlQueryConstructor {
private SqlQueryConstructor() {}
public static final String GET_STUDENT_WITH_FIRST_NAME = "SELECT * FROM " + StudentPersistenceContract.StudentEntry.TABLE_NAME + " WHERE " + StudentPersistenceContract.StudentEntry.COLUMN_FIRST_NAME + " = ?;";
}
This way I can get the desired SQL query by accessing: SqlQueryConstructor.GET_STUDENT_WITH_FIRST_NAME
This is still a Java class, but it'll be good to know that all of my SQL is there and not scattered around all over the place.
Is this a good idea? Are there any other alternatives?
I have decided to use my second approach - using a class with static fields for the SQLite statements. I read about when it's good to use strings.xml and when to use static final Strings: android - strings.xml vs static constants, Android strings, Should I use strings.xml or java strings, etc.
So I'll use strings.xml for localization and the class with static fields for the SQL statements.
I have an old doubt about constants in Java Projects maintenance. From my perspective, when we try putting the constants inside an Abstract class like that:
public final class MyConstants {
public static final String CONSTANT1 = "const1";
public static final String CONSTANT2 = "const2";
public static final String CONSTANT3 = "const3";
public static final String CONSTANT4 = "const4";
}
after that using those constants inside classes in the project:
public void myMethod(final Map params) {
final String myparam = (String) params.get(MyConstants.CONSTANT1);
//DO SOMETHING WITH PARAMS
}
It leads to boiler plate code, verbose use of constants and no real advances. In other hand if we put those constants inside the class for somehow people don't like it. They say "what about we have the same constant declare somewhere?" the problem is maintainance issues, if we change those constants in that class the change can be visible on several parts without any big problem.
Those constants are mainly used for mapping webservices for java perspective without having to generating POJOs like JAXB based on WSDL, the webservices operations are mapped directly for key value maps in Java.
I want to know what do you think about this approach and if we have any other choice.
Thank you.
If I understand your concern, don't hardcode those constants as values except perhaps as defaults and store them with Properties and/or ResourceBundle(s). You might also read the Java Tutorial on Properties. Something like,
Properties props = new Properties();
FileInputStream in = new FileInputStream("my.proprties");
props.load(in);
String v = props.get("CONSTANT_ONE", "const1"); // <-- the "1" is a default.
Then if you need to change the property later you only have to modify the properties file.
Sorry for my bad English and for maybe stupid question but I'm new in Java.
I need use same string in 2 java files for example:
In first java file I've got code for sending emails, I've got string set to default email:
public String mail = new String ("lala#gmail.com");
and I use this string in code for send email:
email.addTo(mail);
In second java file something like set up where can user set new email address I want to have same string, connected with string in first java file. When user put new email String mail will be change to new email address and in email.addTo(mail); will be use this new address
How can I do this?
use Shared Preferences, you can store it as key-value Pair. value being your email and key can be any unique string which you want to identify it with.
I'm a bit confused with the question, but I'll take a stab at it. Basically, you would like to have one String in a given file be used in multiple locations. This is easily done using class-level variables and making them publicly accessible.
For example, in the file:
EmailObject.java
public class EmailObject {
public static final String mail = "lala#gmail.com";
// The rest of your code
}
Another file can access this like so:
OtherObject.java
public void sendEmail() {
EmailMessage email = new EmailMessage();
email.addTo(EmailObject.mail);
}
Note the static and final modifiers on the original. This ensures that you do not need an actual instance of EmailObject to access the string and it also ensures that the string is never modified accidentally by some other object.
There are, of course, other ways to do this, but this one matches your code the most. This is also a very "Java" solution. Android has other ways to share data (as indicated by the other answer).
The simplest way that I would not recommend is to have a public static field:
class A {
public static String commonString;
}
class B {
public void methodThatUsesString () {
// Do stuff with the string
Log.d("I have the string", A.commonString);
}
}
If you have two Activities, and one starts another, you can send data through Intents.
The forementioned SharedPreferences way is a good solution too, if the email address is a persistent thing, a preference if you will, and not just data reqired for an operation.
You can keep a reference of one instance of a class in the otherone, and access it's fields through it:
class A {
public String commonString;
}
class B {
private final A instaceOfA;
public B (A instanceOfA) {
this.instanceOfA = instanceOfA;
}
public void methodThatUsesString () {
// Do stuff with the string
Log.d("I have the string", instanceOfA.commonString);
}
}
Or even use a getter or setter if performance is not an issue.
Many answers depending on how the string will be used.
If it's a constant string, one that will never change, never use final static String
public final static String AUTHOR_MAIL = "lala#gmail.com";
Then you can use it in a static way wherever you want.
email.addTo(MyClass.AUTHOR_MAIL);
If this String will be used in different Activities you can not access it directly (you can not tell if the other Activity is still alive). You have to use Persistence Mechanisms such as SharedPreferences or directly send needed data in your Intent.
If it's in a helper class inside your Activity, you can just use mObject.mail to get it.
How will I be able to retrieve the value of a variable which has a dynamic name
For Example I have list of constants
public class Constant{
public static final String S_R = "Standard(240)";
public static final String S_W = "Standard(180)";
public static final String L_R = "Large(360)";
public static final String L_W = "Large(280)";
}
Based on database I build a variable name
String varName = "S" + "_" +"R"; // This can be S_R , S_W , L_R or L_W
String varVal = // How do i get value of S_R
Use a normal HashMap with variable names as strings against their values. Or use a EnumMap with enums as key and your value as values. AFAIK, that's the closest you can get when using Java. Sure, you can mess around with reflection but IMO the map approach is much more logical.
You can use a Map<String, String> and locate the value by its key.
Even better, you can have an enum:
public enum Foo {
S_R("Standard", 240),
S_W("Standard", 180),...;
private String type;
private String duration;
// constructor and getters
}
And then call Foo.valueOf(name)
(You can also do this via reflection - Constants.class.getField(fieldName) and then call field.get(null) (null for static). But that's not really a good approach.)
If you really must do this (and it's unlikely), you would have to use the Java "reflection" APIs.
I have seen constructs with an enum declared inside an enum. What is this used for ?
Enums in Java can't be extended, so if you wanna collate strongly-related enums in one place you can use these nested enum constructs. For example:
public enum DepartmentsAndFaculties
{
UN (null, "UN", "University"),
EF (UN, "EF", "Engineering Faculty"),
CS (EF, "CS", "Computer Science & Engineering"),
EE (EF, "EE", "Electrical Engineering");
private final DepartmentsAndFaculties parent;
private final String code, title;
DepartmentsAndFaculties(DepartmentsAndFaculties parent, String code, String title)
{
this.parent = parent;
this.code = code;
this.title = title;
}
public DepartmentsAndFaculties getParent()
{
return parent;
}
public String getCode()
{
return code;
}
public String getTitle()
{
return title;
}
}
Here, inner enums consist of {parent enum, code, title} combinations. Example usage:
DepartmentsAndFaculties cs = DepartmentsAndFaculties.CS;
cs.getTitle();
You can see the power of nested enums when constructing hierarchical entities/enums.
You might mean an Enum as an inner type. This is most typically seen when the outer type is a class or an interface, but I suppose there isn't any reason this couldn't be done with enum as an outer.
Inner types are partly about code organization. They can be useful in avoiding creating a bunch of separate files when you have a few types that are related. Sometimes it can make type name more intuitive. For instance, see Map class and its inner Entry class. Most external references to Entry would use Map.Entry format, which is very readable.
The other reason for inner types is that if outer type is a class or an enum, then inner type can be non-public. This is useful for hiding types that are implementation details of the outer type.
I have used nested enums in rare cases where I wanted to enforce a naming convention on the enum values, if additions of new names would have implications for operations or other folks. Here's one example:
public enum MessageTemplateName {
account_verify,
vendor_job_request,
account_job_confirmed,
vendor_job_confirmed,
account_friend_request,
account_job_accepted,
vendor_job_accepted_by_other;
/** Make sure you tell operations if you're adding a new recipient */
private enum Recipient { account, vendor }
private Recipient recipient;
private String messageName;
MessageTemplateName () {
final int firstUnderscore = name().indexOf('_');
recipient = Recipient.valueOf(name().substring(0, firstUnderscore));
messageName = name().substring(firstUnderscore+1);
}
public String getTemplateUrl (String baseUrl) {
if (!baseUrl.endsWith("/")) baseUrl += "/";
return baseUrl + recipient.name() + "/" + messageName + ".vm";
}
}
I'm using an Enum because I want to be able to pass around a generic "message template name" in various places. As you can see, the first part of the enum name corresponds to a directory on a server, and the remainder of the name refers to a Velocity template file name. If fellow engineers started introducing new constants, I'd want to make sure they were filed under the appropriate "recipient", or if a new recipient legitimately needs to be created, that it's a conscious effort to do so, and you'll inform operations (create the directory in production, put any monitoring/permissions in place, etc).
There's a decent argument that, if at some point your Enum becomes too complex, you can replace it with a class/class hierarchy coupled with a much simpler enum. Not sure where I draw the line, but I suppose the above is heading in that direction.