[Android] Bit computing applications in Android

Many people may have encountered such a problem during the interview:
There are 1,000 identical bottles, of which 999 bottles are ordinary water, and one of them is highly toxic (it is still toxic after dilution), and you only have 10 small bottles. White rats, they will die immediately after drinking the poison, how can they use them to determine which bottle is the poison in the shortest time?
We all know that in computer languages, all numbers will eventually be converted into binary for calculation, and each "bit" in the binary can represent two states, which are the numbers 0 and 1.
Going back to the previous question, the life and death status of each mouse can represent a "bit" in the binary system. 10 mice can represent 1024 combinations of states in total. Therefore, a solution to this problem is to give These 1000 bottles of water are marked in binary format (10 digits can mark all), so that these 10 mice correspond to one of the ten digits, and then the current digit of the ten digits The water of 1 above is mixed together to drink for the mouse corresponding to this position. According to the death of the mouse, it is possible to locate which bottle of water is poisonous.

1. Understanding bit operations from MeasureSpec

In Android development, we are also often seen in place operations. When customizing a View, the int makeMeasureSpec(int size, int mode) method will be used to obtain the size and measurement mode of the View, so how does it assemble the two variables into one? Simply put, the upper two bits of a 32-bit binary number are used to store the measurement mode MeasureMode, and the lower 30 bits are used to store the size MeasureSize. MeasureSpec is an internal class in the android.view.View class. The key code is as follows:

public static class MeasureSpec {
    
    
    private static final int MODE_SHIFT = 30;
    //SpecMode 掩码,用于屏蔽高两位
    //11 000000 00000000 00000000 00000000
    private static final int MODE_MASK = 0x3 << MODE_SHIFT;
    //00 000000 00000000 00000000 00000000
    public static final int UNSPECIFIED = 0 << MODE_SHIFT;
    //01 000000 00000000 00000000 00000000
    public static final int EXACTLY = 1 << MODE_SHIFT;
    //10 000000 00000000 00000000 00000000
    public static final int AT_MOST = 2 << MODE_SHIFT;

    //获取 MeasureSpec
    public static int makeMeasureSpec(int size, int mode) {
    
    
        // API 17 之前,忽略此条件
        if (sUseBrokenMakeMeasureSpec) {
    
    
            return size + mode;
        } else {
    
    
            return (size & ~MODE_MASK) | (mode & MODE_MASK);
        }
    }

    //获取 SpecMode
    public static int getMode(int measureSpec) {
    
    
        return (measureSpec & MODE_MASK);
    }

    //获取 SpecSize
    public static int getSize(int measureSpec) {
    
    
        return (measureSpec & ~MODE_MASK);
    }
}

There are several types of operators for bitwise operations:
1. Or operator |: 0|0=0, 0|1=1, 1|1=1
2. And operator &: 0&0=0, 0&1=0, 1&1 =1
3. Non-operator^: 0=1, 1=1
4. Right shift operator >> and left shift operator <<:001<<2=100,110>>1=11

in the MeasureSpec class, The getMode method is to perform an AND operation between the parameter measureSpec and MODE_MASK. MODE_MASK can be understood as the mask of SpecMode. The result of the operation is to retain the upper two bits of measureSpec, and the remaining 30 positions are 0, and the result is MeasureMode.
The getSize method first reverses MODE_MASK and then performs an AND operation with measureSpec. The result is a constant value with the upper two bits being 0 and the lower 30 bits, namely SpecSize.
In the makeMeasureSpec method, the result of size & ~MODE_MASK is the SpecSize of size, and the result of mode & MODE_MASK is SpecMode. If they are ORed, the result is the superimposed value of the two.

Second, the use of bit operations in actual development

Similarly, in daily development, we can also use bit arithmetic to simplify some operations. If the server returns a number, there may be several states that overlap (the following figure). It will be very troublesome to deal with it according to the traditional method. , This time you need to use bit operations.
Insert picture description here

We can create a new StatusManager class to handle this complex state:

public class StatusManager {
    
    
    // 正常
    public static final int STATUS_NORMAL = 0 ; // 0000
 
    //时间同步失败
    public static final int STATUS_TIME_ASY = 1 ; // 0001
 
    // 开门指令失败
    public static final int STATUS_OPEN_DOOR = 1 << 1; // 0010
 
    // 添加固定密码失败
    public static final int STATUS_ADD_FIXED_PSW = 1 << 2; // 0100
 
    // 删除固定密码失败
    public static final int STATUS_DEL_FIXED_PSW = 1 << 3; // 1000
 
    // 存储目前的权限状态
    private int flag;
 
    /**
     *  重置状态
     */
    public void setStatus(int status) {
    
    
        flag = status;
    }
 
    /**
     *  添加一种或者多种状态
     */
    public void addStatus(int status) {
    
    
        flag |= status;
    }
 
    /**
     *  删除一种或者多种状态
     */
    public void deleteStatus(int status) {
    
    
        flag &= ~status;
    }
 
    /**
     *  是否具有某些状态
     */
    public boolean hasStatus(int status) {
    
    
        return (flag & status) == status;
    }
 
    /**
     *  是否不具有某些状态
     */
    public boolean isHasnotStatus(int status) {
    
    
        return (flag & status) == 0;
    }
 
    /**
     *  是否仅仅具有某些状态
     */
    public boolean isOnlyHas(int status) {
    
    
        return flag == status;
    }
}

When adding a state, you can write:

manager.addStatus(StatusManager.STATUS_TIME_ASY | STATUS_ADD_FIXED_PSW )

If you need to judge whether the time synchronization and the door open command fail at the same time, you can write:

manager.hasStatus(StatusManager.STATUS_TIME_ASY | STATUS_OPEN_DOOR)

Is it easy to go back and understand the interview questions at the beginning of the article?

Guess you like

Origin blog.csdn.net/sinat_36955332/article/details/108445042