读Android学Java基础之按位操作符

本文探讨了Android Framework中按位操作符的使用,通过View源码分析了按位与(&)、按位或(|)、按位非(~)、按位异或(^)如何控制View的可见性、焦点和启用状态。通过实例展示了如何添加、删除和检查特定标记,并总结了按位操作在状态计算中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天准备讲讲在Android Framework中按位操作符的运用,讲之前大家最好再回顾一下,按位“与”(&)、按位“或”(|)、按位“非”(~)、按位“异或”(^)的定义

// VISIBILITY_MASK = VISIBLE + INVISIBLE + GONE
// VISIBILITY_MASK 称为掩位码
public static final int VISIBLE = 0x00000000;
public static final int INVISIBLE = 0x00000004;
public static final int GONE = 0x00000008;
static final int VISIBILITY_MASK = 0x0000000C;

private static final int NOT_FOCUSABLE = 0x00000000;
private static final int FOCUSABLE = 0x00000001;
private static final int FOCUSABLE_MASK = 0x00000001;

static final int ENABLED = 0x00000000;
static final int DISABLED = 0x00000020;
static final int ENABLED_MASK = 0x00000020;

int mViewFlags;

通过View源码,看看能不能发现什么规律。

  1. INVISIBLE + VISIBLE + GONE = VISIBILITY_MASK
  2. INVISIBLE & VISIBILITY_MASK; //0100 & 1100 = 0100; = >INVISIBLE
  3. VISIBLE & VISIBILITY_MASK;// 0000 & 1100 = 0000;=> VISIBLE
  4. GONE & VISIBILITY_MASK;// 1000 & 1100 = 1000; => GONE
  5. mViewFlags = INVISIBLE | FOCUSABLE;// 0100 | 0001= 0101
  6. mViewFlags & FOCUSABLE_MASK;// 0101 & 0001 = 0001; => FOCUSABLE
  7. mViewFlags & ENABLED_MASK;// 000101 & 100000 = 000000; => ENABLE
  8. mViewFlags & = ~INVISIBLE;// mViewFlags = 0101 & 1011 = 0001 =>FOCUSABLE
  9. mViewFlags & = ~FOCUSABLE;// mViewFlags = 0001 & 1110 => 0
  10. 重新执行第5步mViewFlags = 0101
  11. mViewFlags & ~VISIBILITY_MASK;// 0101 & 0011 = 0001;=> FOCUSABLE

小结:

  • 1,2,3,4是这类常量在View或者Android中的通用规律,INVISIBLEVISIBLEGONE都是控制View的可见性的常量,而VISIBILITY_MASK恰好是这三个常量之和,前面三个常量的每一个与VISIBILITY_MASK按位“与”操作可得到本身的值。
  • 5用到了按位“或”操作,可以使用按位“或”(|),来为mViewFlags添加值。
  • 6表示与FOCUSABLE_MASK进行按位“与”(&),可以得到对应的XX_MASK属性的状态。
  • 7表示与ENABLED_MASK进行按位“与”(&),得到了对应ENABLED_MASK的属性的默认状态ENABLED
  • 8,9则表明可以用&= ~的方式从mViewFlags删除某个值
  • 10,11则表明通过mViewFlags & ~XX_MASK可以删除这一类的标记

接下来在View.java中还有一处用到了按位运算:

// 这里假设 mViewFlags = FOCUSABLE | SAVE_DISABLED = 0x00000001 | 0x000010000
// => 0x00010001
// flags 和mask这两个参数,我们调用setVisibility(View.GONE),即
// flags = GONE,mask = VISIBILITY_MASK
void setFlags(int flags, int mask) {
    int old = mViewFlags;// old = 0x00010001
    // mViewFlags = (0x00010001 & 0x11110011) | (0x00001000 & 0x00001100)
    //            = 0x00010001 | 0x00001000
    //            = 0x00011001
    mViewFlags = (mViewFlags & ~mask) | (flags & mask);
    int changed = mViewFlags ^ old; // 0x00011001 ^ 0x00010001 = 0x00001000                                     //                         = GONE
    if (changed == 0) {
        return;
    }
}

小结:

  • 其中比较难理解的一句就是mViewFlags = (mViewFlags & ~mask) | (flags & mask);上面的小结中已经提到了mViewFlags & ~mask是将mask下的标记删除;flags & mask也在上一小结中介绍过可以得到flags,这样(mViewFlags & ~mask) | (flags & mask)的结果就是将mask下的flags添加到mViewFlags中。
  • 一个是带有新的mViewFlags,一个是旧的mViewFlags(old),从得出的结果0x00001000(GONE),恰好是要添加的新flags—GONE。所以这里的按位“异或”就是获得两者的差异。

总结:

  1. Android中使用按位操作来计算某种属性(比如,可见性)状态的改变。特征是状态1;状态2;。。。状态n,属性_MASK。这里的属性_MASK叫做掩码(MaskBit)。XX_MASK = 状态1 + 状态2 + 。。。+ 状态n;

  2. 不同的属性应该有默认状态,比如visibility(可见性)默认值是VISIBLE(0X00000000),所有的默认值都是0;这样做的好处是不用初始化。

  3. 运算

    1. 添加某种状态:

      mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
    2. 删除特定的某种状态:

      viewFlagValues &= ~SOUND_EFFECTS_ENABLED;// 方法一
      mViewFlags ^= SCROLLBARS_HORIZONTAL;//方法二
    3. 删除某种属性

      mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
    4. 获取指定属性的状态值

      public int getVisibility() {
          return mViewFlags & VISIBILITY_MASK;
      }
    5. 比较两个flags的区别

      int old = mViewFlags;
      mViewFlags = (mViewFlags & ~mask) | (flags & mask);
      
      int changed = mViewFlags ^ old;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值