Android #Intdef for flags how to use it - android

I am not clear how to use #Intdef when making it a flag like this:
#IntDef(
flag = true
value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
this example is straight from the docs. What does this actually mean ? does it mean all of them are initially set to true ? if i do a "or" on the following:
NAVIGATION_MODE_STANDARD | NAVIGATION_MODE_LIST
what does it mean ...im a little confused whats happening here.

Using the IntDef#flag() attribute set to true, multiple constants can be combined.
Users can combine the allowed constants with a flag (such as |, &, ^ ).
For example:
public static final int DISPLAY_OP_1 = 1;
public static final int DISPLAY_OP_2 = 1<<1;
public static final int DISPLAY_OP_3 = 1<<2;
#IntDef (
flag=true,
value={
DISPLAY_OP_1,
DISPLAY_OP_2,
DISPLAY_OP_3
}
)
#Retention(RetentionPolicy.SOURCE)
public #interface DisplayOptions{}
public void setIntDefFlag(#DisplayOptions int ops) {
...
}
and Use setIntDefFalg() with '|'
setIntDefFlag(DisplayOptions.DISPLAY_OP1|DisplayOptions.DISPLAY_OP2);

Related

# annotations not working anymore

I have defined this #IntDef
public static final int LINE = 0;
public static final int CORNER = 1;
#IntDef({LINE, CORNER})
#Retention(RetentionPolicy.SOURCE)
public #interface ShapeTypes {}
and assigned it to one of my class members like this
public #ShapeTypes int shapeType;
and if I remember correctly, it used to work, but now, in Android Studio 3.1.2 I'm able to do something like this
myClassObj.shapeType = 99;
Shouldn't it cause compilation and/or runtime errors? Is there a way I can define range of allowed values for the variables now?
Update
It seems, that all annotations are not working anymore.
#IntRange(from = 4, to = 18)
public int size;
does not affect the statement size = 20;
Am I missing something? Some setting to turn on the annotations?
I'm having same problem in Android Studio 3.1.2. But one of my colleagues tested it in 3.1.0 and it seems it is working in that version.
IntDef treat like enum so you can't initialize later. You have declare manually.
#IntDef({ShapeTypes.SHAPETYPE})
#Retention(RetentionPolicy.SOURCE)
#interface ShapeTypes {
int SHAPETYPE= 0;
}
For more details have look this

Support Annotation #StringDef, #IntDef declaration standards?

#StringDef, #IntDef etc has made life much simpler and good alternatives to using enums.
Typically we see that these are defined as follows:
#IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
#Retention(RetentionPolicy.SOURCE)
public #interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
....
Would there be any issue if one was to define these inside of the annotation itself. eg:
#IntDef({NavigationMode.NAVIGATION_MODE_STANDARD, NavigationMode.NAVIGATION_MODE_LIST, NavigationMode.NAVIGATION_MODE_TABS})
#Retention(RetentionPolicy.SOURCE)
public #interface NavigationMode {
int NAVIGATION_MODE_STANDARD = 0;
int NAVIGATION_MODE_LIST = 1;
int NAVIGATION_MODE_TABS = 2;
}
....
This comes in handy when these def annotation is defined separately so it could be used across modules.
I am using #IntDef notoriously. It's awesome, especially since Android Studio 2.0 can work correctly with this annotation and switch statement.
I am usually using this pattern:
public static final class NavigationMode {
#IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
#Retention(RetentionPolicy.SOURCE)
public #interface Value {
}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
// Suppress default constructor for noninstantiability
private NavigationMode() {
throw new AssertionError();
}
}
Then I can refer to the value through NavigationMode.NAVIGATION_MODE_STANDARD and the annotation is #NavigationMode.Value with a bit simpler #IntDef definition (without NavigationMode. prefixes).
But I must say... I like your second approach really much!
#IntDef({NavigationMode.NAVIGATION_MODE_STANDARD, NavigationMode.NAVIGATION_MODE_LIST, NavigationMode.NAVIGATION_MODE_TABS})
#Retention(RetentionPolicy.SOURCE)
public #interface NavigationMode {
int NAVIGATION_MODE_STANDARD = 0;
int NAVIGATION_MODE_LIST = 1;
int NAVIGATION_MODE_TABS = 2;
}
I might even switch to it. Although I'm not a big fan of the way Android Studio colors it then:
I don't think there should be any issues with values defined this way.

Translating iOS Enums to Android

I'm busy trying to translate some iOS code to Android code. The iOS code contains Enums, like the following:
typedef NS_OPTIONS(NSUInteger, Traits) {
TraitNumberOne = 1<<0,
TraitNumberTwo = 1<<1,
);
I have never worked with Enums before in Android, and am having trouble interpreting the documentation and examples that are available. How would I translate the above example to Android code?
use this
public enum NS_OPTIONS {
TraitNumberOne (1<<0),
TraitNumberTwo (1<<1);
private final int Option;
public int getOption()
{
return Option;
}
private NS_OPTIONS(int option) {
this.Option= option;
}
}
Use it like this:
int value = NsOptions.TraitNumberOne.getOption();
Java enums are relatively simple, but can be made more complex to fit whatever needs you want to use them for. If you just want the type-safety of an enum, you can just declare the variable names like this:
public enum Traits{
TraitNumberOne,
TraitNumberTwo
}
If you want more advanced features of an enum, it's treated exactly like a class that is instantiated statically for each item in the enum. So, you can have a constructor and input whatever value you want associated with each individual item, like so:
public enum Traits{
TraitNumberOne(0x01),
TraitNumberTwo(0x02),
// future items go here
; // don't forget the semi-colon, which indicates the list of items is ending
// now, create a private variable to store the data
private final int data;
// and the constructor to set the data
private NsOptions(int data){
this.data = data;
}
// now, you can provide an accessor to provide access to the data
public int getData(){
return this.data;
}
}
You can use the above enum like this:
Traits currentOptions = Traits.TraitNumberOne;
int optionsData = currentOptions.getData();
The idea of NS_OPTIONS is to allow all possible combinations of the enumerated values to be represented by one value (this is why bitwise operators are used). In Java, I guess the equivalent would be:
public enum Permission {
TraitNumberOne (0b01),
TraitNumberTwo (0b10);
...
}
We can implement in android like ,
public enum NS_OPTIONS{
TraitNumberOne(1),TraitNumberTwo(2);
private int type;
NS_OPTIONS(int type){
this.type = type;
}
public int getType(){
return type;
}
}
and if you want to use above enum from your class you can use it like,
int i =NS_OPTIONS.TraitNumberOne;//which will return 1
int j =NS_OPTIONS.TraitNumberTwo;//which will return 2;

Android, Best way to provide app specific constants in a library project?

I am creating a library project for a number of android apps.
The apps all have some common functionality that I wish to include in the library project but the library project functions require use of application specific constants
So I am looking for a way to provide the library functions with the names of the constants and allow each app to define them
An example of a specific app constant and how it is used within the library project
public class AppConstants {
public static final long APP_ID = 6;//Needs to be set for each app
}
public static long getCurrentAppId(Context context) {
return getLongPreference(context, CURRENT_APP_ID_KEY, AppConstants.APP_ID);
}
This is just one example of approximately 60 constants that need to be defined for each app for a large number of library functions
Obviously I would normally just import/include the project specific app_constants.java file but this is not possible in the library project files as it hasn't got a clue about the specific applications (rightly so)
So what is the best way to have each specific app override the constants?
Update
I took a long time deciding on which of the superb answers I have been provided with best suited my needs (Thanks everyone) In the end I chose the xml solution. I don't particularly like it because it clutters up my apps resources and I did seriously consider using the interface solution but the xml solution does work nicely
Option #1
Extend your AppConstants class in each project
Better Option#2
Use XML resources to define the constants
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="integer" name="app_id" format="integer">6</item>
</resources>
then you can retrieve them by
Context.getResources().getInteger(R.integer.app_id);
add the xml file to your resources in each project with only the values you need different
I don't know of a great schema to do that but it would certainly work this way:
define some base class in your library
// class, enum or whatever you want it to be.
class BaseConstants {
// use some real singleton instead
public static final BaseConstants instance = new BaseConstants();
// define those values - sadly static inheritance does not work
private static final int APP_ID = 0;
private static final int CURRENT_APP_ID_KEY = 24;
// so we have to do that via methods
protected int getAppId() {
return APP_ID;
}
protected int getAppIdKey() {
return CURRENT_APP_ID_KEY;
}
}
let each Activity that wants something custom implement that
class App1Constants extends BaseConstants {
public static final App1Constants instance = new App1Constants();
private final static int APP_ID = 1;
// want a different APP_ID here.
protected int getAppId() {
return APP_ID;
}
// getAppIdKey not implemented here, uses default
}
Use that class as context to the constants for your library
class Library {
public static long getCurrentAppId(Context context, BaseConstants settings) {
return getLongPreference(context, settings.getAppIdKey(), settings.getAppId());
}
}
Activities would be like so
class myActivity extends Activity {
// each Activity can implement it's own constants class and overwrite only some values
private static final BaseConstants CONSTANTS = App1Constants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
class myActivity2 extends Activity {
// or could just use the default ones
private static final BaseConstants CONSTANTS = BaseConstants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
That schema is kind of ugly but it would work at least
Define them as enum's in your library project, like
public enum Planet { MERCURY, VENUS, MARS }
Android proper takes another approach, the dreaded constant interface, like,
interface Planets {
static final int MERCURY = 1;
static final int VENUS = 2;
...
}
However, this is a well-known Java anti-pattern (constant interface, and is covered in detail in Effective Java, I quote,
The constant interface pattern is a poor use of interfaces. That a
class uses some constants internally is an implementation detail.
Implementing a constant interface causes this implementation detail to
leak into the class’s exported API. It is of no consequence to the
users of a class that the class implements a constant interface. In
fact, it may even confuse them. Worse, it represents a commitment: if
in a future release the class is modified so that it no longer needs
to use the constants, it still must implement the interface to ensure
binary compatibility. If a nonfinal class implements a constant
interface, all of its subclasses will have their namespaces polluted
by the constants in the interface.
If you need the constants to have int values for some reason, and calling toString() on the enum isn't sufficient, you can give the enum's a extra information like,
public enum ZipCode {
LYNNWOOD(98036), SAN_JOSE(95112), ...;
private int zipCode;
private ZipCode(int zipCode) { this.zipCode = zipCode; }
public int getZipCode() { return zipCode; }
}
Note that enum's are slightly less performing than integer constants, but from a code organization and clarity perspective they are far superior.

How to organize Android dialog IDs?

I have a base class ActivityA that has some dialogs:
public static final int SOME_DIALOG_ID = 1;
public static final int OTHER_DIALOG_ID = 2;
ActivityB inherits ActivityA and comes with its own dialogs:
public static final int MY_DIALOG_ID = 1;
public static final int CONFLICT_DIALOG_ID = 2;
As you can see, the dialog IDs are no longer unique within the activity. This is a problem that I keep running into. Easy to fix, but tedious to maintian. There must be some good design pattern for this particular issue. Please, enlighten me!
Q: What is the best way to organize dialog IDs?
In my situation, I create class called AppConstant.java that contain all constant in current application, some of it:
public static final int INTENT_REQUEST_CODE_ACT_MAIN_BROWSE_PICTURE = 1;
public static final int INTENT_REQUEST_CODE_ACT_MAIN_CAMMERA_SNAP = 2;
public static final int INTENT_REQUEST_CODE_ACT_PROCESS_IMAGE_PROCESS = 3;
public static final int INTENT_REQUEST_CODE_ACT_PROCESS_BROWSE_PICTURE_FOR_BACK_DATA = 4;
Using this convention, I can easily maintain my ID within single class.
How about use 1, 2 for ActivityA, then 11, 12 for inherited class, then 101, 102 (or 21, 22) for further inheritance depth.

Categories

Resources