Android source code using hexadecimal state management method

  • 2021-12-13 09:39:13
  • OfStack

Preface

In the Android source code, the management of "multi-state" is always represented by hexadecimal numbers, similar to this format:


//ViewGroup.java

protected int mGroupFlags;

static final int FLAG_CLIP_CHILDREN = 0x1;
private static final int FLAG_CLIP_TO_PADDING = 0x2;
static final int FLAG_INVALIDATE_REQUIRED  = 0x4;
private static final int FLAG_RUN_ANIMATION = 0x8;
static final int FLAG_ANIMATION_DONE = 0x10;
private static final int FLAG_PADDING_NOT_NULL = 0x20;

So, have you ever wondered why you need hexadecimal when you encounter multi-state management?

Simple state representation

To give a practical example, as a person, we will definitely have many labels on our bodies, such as 帅气、可爱、博学、机智、懒惰、小气 .

For these labels, we can set different people's settings:


// Defining Entity Classes 
	data class Person(var tag : String)

// Modify Label 
	val person1 = Person(" Handsome ")

 // Judgment label 
 	fun isCute():Boolean{
 		return person1.tag == " Cute "
 	}

When a person has only one label, it is very simple, and it can be directly assigned or judged. But what if one person has more than one label?

It is also very simple, just use collection storage:


val person2 = Person(mutableListOf())
    person2.tags.add(" Handsome ")
    person2.tags.add(" Cute ")

    person2.tags.remove(" Cute ")

    person2.tags.contains(" Cute ")	

But after using sets, this calculation becomes more complicated because remove And contains Methods are implemented by traversing the set. From the perspective of time complexity, when deleting a label or judging whether a label exists, the time complexity is O(n) .

Is there any way to make multiple tags as simple as a single tag just now?

Binary operation

Of course there is, otherwise this article will not have, before that, let's review the next binary several operations.

1. Bitwise and ( & )

When the values of both corresponding bits are 1, the result is 1, otherwise it is 0.

Examples: 0x1 & 0x4

0001 &
0100
=
0000

2. Bitwise or ()

When the values of both corresponding bits are 1 as long as 1 bit is 1, the result is 1.

Examples: 0x1 | 0x4

0001 |
0100
=
0101

3. Inverse (~)

Inversion of 1 number by bit.

Examples: ~ 0x1

0001 ~
=
1110

Well, with these three operations, our state management is enough.

Introducing hexadecimal

Next, let's complete a complete example of state management.


// Set the corresponding to all states 16 Binary value 

// Lovely, corresponding 2 Binary system 0001
val TAG_CUTE = Ox1  
// Handsome, corresponding 2 Binary system 0010 
val TAG_HANDSOME = Ox2
// Erudite, corresponding 2 Binary system 0100
val TAG_LEARNED = Ox4

var personTag = 0

State increase

If a binary number wants to leave the mark of another binary number (the mark of the number 1), we can pass the OR operation, so that as long as the second number has a 1 in one digit, the final result must be a 1 in the same digit.

Therefore, we can complete the function of state increase by this method:


// Increase cute status 
personTag |= TAG_CUTE

0000 |
0001 
=
0001

After this operation, the number on the fourth bit of personTag is 1, which is accompanied by TAG_CUTE This is marked.

State removal

According to the above logic, the removal of state actually needs to change the corresponding number of bits from 1 to 0.

Hypothesis personTag Now the value becomes a binary number 0111 .

If you want to delete TAG_CUTE Property, you need to change the 1 in bit 4 to 0. Then what we can do is to correct the TAG_CUTE Inverted, that is, 0001 is changed into 1110. And then with personTag Do an AND operation, so that the fourth bit will definitely become 0, while the values above other bits will not change.


//personTag For 2 Binary number 0111
personTag &= ~TAG_CUTE

0001 ~
=
1110 &
0111
=
0110

Complete the pair TAG_CUTE Removal of state.

State judgment

By the same token, judging whether there is a certain state is actually judging whether there is a value of 1 in a certain bit.
So we just need to do an AND operation on the state. If the result is 0, it means there is no state, otherwise it means there is a state.


//personTag For 2 Binary number 0111
(personTag & TAG_CUTE) != 0

0111 &
0001
=
0001

The result is not 0, so it represents personTag Includes TAG_CUTE This state.

Points of attention

Careful friends may find that the hexadecimal value we used just now has been skipped Ox3 This value, why is this?

In fact, it is not difficult to find that the so-called management of state through hexadecimal is actually the management of state through binary, and in the final analysis, it is managed through the number of digits where 1 is located in binary.

Therefore, when we assign values to states, we need to select binary values that occupy 1 bit alone, such as 0001 ,0010,0100,1000,10000 Wait.

What happens if you use other values? For example, add Ox3 TAG of.


// Lazy, corresponding 2 Binary system 0011
val TAG_LAZY = Ox3

// Increase cute status 
personTag |= TAG_CUTE
// Increase handsome status 
personTag |= TAG_HANDSOME

After we added cute and handsome status, personTag The binary value of is contains0 .

At this time, judge whether it contains laziness:


// Does it contain lazy state 
(personTag & TAG_LAZY) != 0

0011 &
0011 
=
0011

The result is not 0. Do we increase our laziness? Obviously not, I'm not lazy, but I'm lazy, which is framed!

So do you understand the range of state values?

Why hexadecimal?

At this point, the function of managing state through hexadecimal system has been realized. Obviously, it is much simpler to manage state in this way, and its fundamental principle is to complete the management of state through binary calculation.

Someone has to ask again, since the essence is to complete management through binary system, it is ok to express it with decimal system, such as the above example:


// Set the corresponding to all states 10 Binary value 

// Lovely, corresponding 2 Binary system 0001
val TAG_CUTE = 1  
// Handsome, corresponding 2 Binary system 0010 
val TAG_HANDSOME = 2
// Erudite, corresponding 2 Binary system 0100
val TAG_LEARNED = 4

var personTag = 0

Isn't this like hexadecimal?

Fundamentally speaking, it is one, but hexadecimal has the advantages of hexadecimal, which involves the reason why hexadecimal was designed.

In a computer, a byte has 8 bits, and the maximum value is 1111 1111. The corresponding decimal number is 255, and the corresponding hexadecimal number is FF.
Therefore, half a byte can be represented by one letter in hexadecimal, while converting to decimal is an irregular number.
For convenience, the code 1 generally uses hexadecimal to represent binary, because it can carry out a more convenient and intuitive conversion with binary.

Summarize

Today and everyone introduced the source code commonly used through the conversion of hexadecimal binary to manage the state of the method.


Related articles: