For Java class applications, the memory aspect needs to be noted:
Do not occupy a large amount of memory, or less available memory, triggering GC or OutOfMemoryError
;
Do not create objects frequently, frequent memory allocations, triggering GC.
For enumerations and constants:
Using enumerations does not make the creation of objects more frequent.
Enumeration classes consume more memory than constants, and memory is always occupied by the time the program runs without unloading the enumeration class.
The enumeration consumes more memory relative to the constant.
With constants, you can save a lot of memory, and in languages such as C, you use bitmask for state representation.
In Android, bitmask is also used extensively, such as android.view.View
this class.
-bit operation
Before using bitmask, we should review the basic bit operation.
-
Not
not 0000 0001 = 1111 1110
For example:
int a = 1; int b = ~a
-
OR
or 0000 0001 0000 0010 = 0000 0011
For example: /p>
int a = Span class= "Mi" >1; int b = 2; int c = a | b
and
AND 0000 0101 0000 0110 = 0000 0100
Like what:
int a = 5;int b = 6;int c = a & b;
Bitmask
We know that each bit can be evaluated in two ways: 0 or 1.
Bitmask uses a numeric value to record the state, using each bit of the value to express a state.
Use bitmask to express a very rich state with very few resources.
In Java, a byte type, with 8 bits (bit), can express 8 different states, and these States are not affected by each other. In the case of type int, there are 32 bits, which can express 32 states.
More importantly, the bitmask can be very simple to combine state queries.
Bitmask Basic operation
Suppose we use a numeric value that represents the state: status
the initial value is 0.
byte status = 0;
We define a mask value, which is the second digit of 1: 0000 0010
.
Let's move 1 to the left 1 to get this number:
byte mask = 0x01 << 1;
Set status
Any other bit, turn the 2nd bit into 1.
xxxx xxxxOR 0000 0010 = xxxx xx1x
Code
status |= mask;
Clear status
Any other bit, place the 2nd position at 0.
xxxx xxxxAND 1111 1101 = xxxx xx0x
This is actually the status
inverse code of the pair and mask
carries out the logical "and" Operation:
status &= ~mask;
Query status
Determine whether the 2nd bit is 0 or 1, and mask
perform the logical "and" Operation:
xxxx xxxxAND 0000 0010 = 0000 00x0
If 1, returns a value greater than 0, otherwise returns 0.
boolean isOn = (status & mask) > 0;
Example
Here is an example of how to do this.
The relevant code is here: Https://github.com/liaohuqiu/android-BitMaskSample.
Li Bai is a poet, life simple "plain": sometimes write poetry, sometimes drink, sometimes while writing poetry, while drinking.
Whether it is busy writing poetry or busy drinking, Li Bai is in a busy state.
We use a byte to represent his state, a byte has 8 bits, we start from the low starting to take two to represent poetry and drink respectively.
writing ------+ | v -------+---+---+---+ x x | | | x | -------+---+---+---+ ^ | drinking --+
Two masks are:
//0000 0010private static final byte state_busy_in_writing = 0x01 << 1; 0000 0100private static final byte state_busy_in_drinking = 0x01 << 2< Span class= "O";
- The
-
State is set with clear
To set the drinking state as an example, setting the state as the mask value for logical "or", clearing the state from the mask's inverse code for logical "and" operations.
public void setbusyindrinking (boolean busy ) {if (busy{mstate |= state_busy_in_drinking} else {mstate &= ~state_busy_in_drinking} /span>
- The
-
Status query
And mask are run logically "and" to determine if it is zero:
public boolean isbusyindrinking () {return (mstate & state_busy_in_drinking != 0;< Span class= "O" _}
Group Status Query
Whether it is busy writing poetry or busy drinking, it is called "Li Bai is very busy", this is a combination of state. As long as it is in one of these two states, it is in the combined state.
For a state combination, a logical "or" operation is possible, and when multiple states are combined, it is particularly convenient:
STATE_BUSY_MASK = STATE_BUSY_IN_WRITING | STATE_BUSY_IN_DRINKING
Determine if it is in a combined state:
public boolean isBusy() { return (mState & STATE_BUSY_MASK) != 0;}
Intdef in Android
Using the intdef annotation to declare a constant value, when defining a variable, plus the declaration defined by INTDEF, the compiler checks whether the assignment is legitimate.
Statement:
Last 8 bits 0000 1100StaticFinalIntVisibility_mask=0x0000000c;PublicStaticFinalIntVISIBLE=0x00000000;Last 8 bits 0000 0100Publicstatic final int invisible = Span class= "MH" >0x00000004; Last 8 bits 0000 1000public static final int gone = 0x00000008; ({visibleinvisiblegone}) @Retention (.) public @interface visibility {} /span>
Use:
public void setVisibility(@Visibility int visibility) { setFlags(visibility, VISIBILITY_MASK);}
As we can see above, the code uses the leftmost 3, 4 bits to represent the visibility of the View.
Conclusion
In addition to Intdef, there are stringdef, interested students can see the source.
In the Android code there are a lot of bitmask, like View
, MotionEvent
such core base class, need to seriously consider the use of memory, can save the province.
If you really want to completely control the use of memory, the pursuit of excellence in quality, want to maximize memory savings, bitmask is your good choice.
At the same time, we should also be aware that enumerations are not useless.
I have heard a lot of arguments, saying that "The enumeration is not good, the official also advised not to use, because the use of a lot of memory, inefficient", these are also typical of the same.
In fact, unless you're writing a View
core base class or a very large application like this, the problem with the memory overhead of enumerating such a project is really big.
Bitmask use reference