位掩码(BitMask)

位运算在实际开发中用得很少,主要原因还是它对于不熟悉的人不好读不好懂不好计算,如果不经常实践会生疏。但它的优点自然是计算快,代码更少。在某些地方它的优势会更加明显比如如下代码(http://xxgblog.com/2013/09/15/Java-bitmask/):

  1. public class NewPermission {  
  2.     // 是否允许查询,二进制第1位,0表示否,1表示是  
  3.     public static final int ALLOW_SELECT = 1 << 0// 0001  
  4.       
  5.     // 是否允许新增,二进制第2位,0表示否,1表示是  
  6.     public static final int ALLOW_INSERT = 1 << 1// 0010  
  7.       
  8.     // 是否允许修改,二进制第3位,0表示否,1表示是  
  9.     public static final int ALLOW_UPDATE = 1 << 2// 0100  
  10.       
  11.     // 是否允许删除,二进制第4位,0表示否,1表示是  
  12.     public static final int ALLOW_DELETE = 1 << 3// 1000  
  13.       
  14.     // 存储目前的权限状态  
  15.     private int flag;  
  16.   
  17.     /** 
  18.      *  重新设置权限 
  19.      */  
  20.     public void setPermission(int permission) {  
  21.         flag = permission;  
  22.     }  
  23.   
  24.     /** 
  25.      *  添加一项或多项权限 
  26.      */  
  27.     public void enable(int permission) {  
  28.         flag |= permission;  
  29.     }  
  30.       
  31.     /** 
  32.      *  删除一项或多项权限 
  33.      */  
  34.     public void disable(int permission) {  
  35.         flag &= ~permission;  
  36.     }  
  37.       
  38.     /** 
  39.      *  是否拥某些权限 
  40.      */  
  41.     public boolean isAllow(int permission) {  
  42.         return (flag & permission) == permission;  
  43.     }  
  44.       
  45.     /** 
  46.      *  是否禁用了某些权限 
  47.      */  
  48.     public boolean isNotAllow(int permission) {  
  49.         return (flag & permission) == 0;  
  50.     }  
  51.       
  52.     /** 
  53.      *  是否仅仅拥有某些权限 
  54.      */  
  55.     public boolean isOnlyAllow(int permission) {  
  56.         return flag == permission;  
  57.     }  
  58. }  
public class NewPermission {
	// 是否允许查询,二进制第1位,0表示否,1表示是
	public static final int ALLOW_SELECT = 1 << 0; // 0001
	
	// 是否允许新增,二进制第2位,0表示否,1表示是
	public static final int ALLOW_INSERT = 1 << 1; // 0010
	
	// 是否允许修改,二进制第3位,0表示否,1表示是
	public static final int ALLOW_UPDATE = 1 << 2; // 0100
	
	// 是否允许删除,二进制第4位,0表示否,1表示是
	public static final int ALLOW_DELETE = 1 << 3; // 1000
	
	// 存储目前的权限状态
	private int flag;

	/**
	 *  重新设置权限
	 */
	public void setPermission(int permission) {
		flag = permission;
	}

	/**
	 *  添加一项或多项权限
	 */
	public void enable(int permission) {
		flag |= permission;
	}
	
	/**
	 *  删除一项或多项权限
	 */
	public void disable(int permission) {
		flag &= ~permission;
	}
	
	/**
	 *  是否拥某些权限
	 */
	public boolean isAllow(int permission) {
		return (flag & permission) == permission;
	}
	
	/**
	 *  是否禁用了某些权限
	 */
	public boolean isNotAllow(int permission) {
		return (flag & permission) == 0;
	}
	
	/**
	 *  是否仅仅拥有某些权限
	 */
	public boolean isOnlyAllow(int permission) {
		return flag == permission;
	}
}

业务上,权限可以有多个,通过普通方式实现上面的业务功能也不会太麻烦。但上面这种取巧的方式在Android的源码中是不少的,可以说是随处可见,比如EditText的InputType:

  1. /* 
  2.  * Copyright (C) 2008 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package android.text;  
  18.   
  19. import android.text.TextUtils;  
  20.   
  21. /** 
  22.  * Bit definitions for an integer defining the basic content type of text 
  23.  * held in an {@link Editable} object. Supported classes may be combined 
  24.  * with variations and flags to indicate desired behaviors. 
  25.  * 
  26.  * <h3>Examples</h3> 
  27.  * 
  28.  * <dl> 
  29.  * <dt>A password field with with the password visible to the user: 
  30.  * <dd>inputType = TYPE_CLASS_TEXT | 
  31.  *     TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 
  32.  * 
  33.  * <dt>A multi-line postal address with automatic capitalization: 
  34.  * <dd>inputType = TYPE_CLASS_TEXT | 
  35.  *     TYPE_TEXT_VARIATION_POSTAL_ADDRESS | 
  36.  *     TYPE_TEXT_FLAG_MULTI_LINE 
  37.  * 
  38.  * <dt>A time field: 
  39.  * <dd>inputType = TYPE_CLASS_DATETIME | 
  40.  *     TYPE_DATETIME_VARIATION_TIME 
  41.  * </dl> 
  42.  */  
  43. public interface InputType {  
  44.     /** 
  45.      * Mask of bits that determine the overall class 
  46.      * of text being given.  Currently supported classes are: 
  47.      * {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER}, 
  48.      * {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}. 
  49.      * <p>IME authors: If the class is not one you 
  50.      * understand, assume {@link #TYPE_CLASS_TEXT} with NO variation 
  51.      * or flags.<p> 
  52.      */  
  53.     public static final int TYPE_MASK_CLASS = 0x0000000f;  
  54.       
  55.     /** 
  56.      * Mask of bits that determine the variation of 
  57.      * the base content class. 
  58.      */  
  59.     public static final int TYPE_MASK_VARIATION = 0x00000ff0;  
  60.       
  61.     /** 
  62.      * Mask of bits that provide addition bit flags 
  63.      * of options. 
  64.      */  
  65.     public static final int TYPE_MASK_FLAGS = 0x00fff000;  
  66.       
  67.     /** 
  68.      * Special content type for when no explicit type has been specified. 
  69.      * This should be interpreted to mean that the target input connection 
  70.      * is not rich, it can not process and show things like candidate text nor 
  71.      * retrieve the current text, so the input method will need to run in a 
  72.      * limited "generate key events" mode, if it supports it. Note that some 
  73.      * input methods may not support it, for example a voice-based input 
  74.      * method will likely not be able to generate key events even if this 
  75.      * flag is set. 
  76.      */  
  77.     public static final int TYPE_NULL = 0x00000000;  
  78.       
  79.     // ----------------------------------------------------------------------  
  80.     // ----------------------------------------------------------------------  
  81.     // ----------------------------------------------------------------------  
  82.       
  83.     /** 
  84.      * Class for normal text.  This class supports the following flags (only 
  85.      * one of which should be set): 
  86.      * {@link #TYPE_TEXT_FLAG_CAP_CHARACTERS}, 
  87.      * {@link #TYPE_TEXT_FLAG_CAP_WORDS}, and. 
  88.      * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  It also supports the 
  89.      * following variations: 
  90.      * {@link #TYPE_TEXT_VARIATION_NORMAL}, and 
  91.      * {@link #TYPE_TEXT_VARIATION_URI}.  If you do not recognize the 
  92.      * variation, normal should be assumed. 
  93.      */  
  94.     public static final int TYPE_CLASS_TEXT = 0x00000001;  
  95.       
  96.     /** 
  97.      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters.  Overrides 
  98.      * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and 
  99.      * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  This value is explicitly defined 
  100.      * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}. Of course, 
  101.      * this only affects languages where there are upper-case and lower-case letters. 
  102.      */  
  103.     public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;  
  104.       
  105.     /** 
  106.      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of 
  107.      * every word.  Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  This 
  108.      * value is explicitly defined 
  109.      * to be the same as {@link TextUtils#CAP_MODE_WORDS}. Of course, 
  110.      * this only affects languages where there are upper-case and lower-case letters. 
  111.      */  
  112.     public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;  
  113.       
  114.     /** 
  115.      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of 
  116.      * each sentence.  This value is explicitly defined 
  117.      * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}. For example 
  118.      * in English it means to capitalize after a period and a space (note that other 
  119.      * languages may have different characters for period, or not use spaces, 
  120.      * or use different grammatical rules). Of course, 
  121.      * this only affects languages where there are upper-case and lower-case letters. 
  122.      */  
  123.     public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;  
  124.       
  125.     /** 
  126.      * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form 
  127.      * text that should have auto-correction applied to it. Without this flag, 
  128.      * the IME will not try to correct typos. You should always set this flag 
  129.      * unless you really expect users to type non-words in this field, for 
  130.      * example to choose a name for a character in a game. 
  131.      * Contrast this with {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE} and 
  132.      * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}: 
  133.      * {@code TYPE_TEXT_FLAG_AUTO_CORRECT} means that the IME will try to 
  134.      * auto-correct typos as the user is typing, but does not define whether 
  135.      * the IME offers an interface to show suggestions. 
  136.      */  
  137.     public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;  
  138.       
  139.     /** 
  140.      * Flag for {@link #TYPE_CLASS_TEXT}: the text editor (which means 
  141.      * the application) is performing auto-completion of the text being entered 
  142.      * based on its own semantics, which it will present to the user as they type. 
  143.      * This generally means that the input method should not be showing 
  144.      * candidates itself, but can expect the editor to supply its own 
  145.      * completions/candidates from 
  146.      * {@link android.view.inputmethod.InputMethodSession#displayCompletions 
  147.      * InputMethodSession.displayCompletions()} as a result of the editor calling 
  148.      * {@link android.view.inputmethod.InputMethodManager#displayCompletions 
  149.      * InputMethodManager.displayCompletions()}. 
  150.      * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and 
  151.      * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}: 
  152.      * {@code TYPE_TEXT_FLAG_AUTO_COMPLETE} means the editor should show an 
  153.      * interface for displaying suggestions, but instead of supplying its own 
  154.      * it will rely on the Editor to pass completions/corrections. 
  155.      */  
  156.     public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;  
  157.       
  158.     /** 
  159.      * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be 
  160.      * entered into the field.  If this flag is not set, the text field  
  161.      * will be constrained to a single line. The IME may also choose not to 
  162.      * display an enter key when this flag is not set, as there should be no 
  163.      * need to create new lines. 
  164.      */  
  165.     public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;  
  166.       
  167.     /** 
  168.      * Flag for {@link #TYPE_CLASS_TEXT}: the regular text view associated 
  169.      * with this should not be multi-line, but when a fullscreen input method 
  170.      * is providing text it should use multiple lines if it can. 
  171.      */  
  172.     public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;  
  173.       
  174.     /** 
  175.      * Flag for {@link #TYPE_CLASS_TEXT}: the input method does not need to 
  176.      * display any dictionary-based candidates. This is useful for text views that 
  177.      * do not contain words from the language and do not benefit from any 
  178.      * dictionary-based completions or corrections. It overrides the 
  179.      * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set. 
  180.      * Please avoid using this unless you are certain this is what you want. 
  181.      * Many input methods need suggestions to work well, for example the ones 
  182.      * based on gesture typing. Consider clearing 
  183.      * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} instead if you just do not 
  184.      * want the IME to correct typos. 
  185.      * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and 
  186.      * {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE}: 
  187.      * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME should never 
  188.      * show an interface to display suggestions. Most IMEs will also take this to 
  189.      * mean they should not try to auto-correct what the user is typing. 
  190.      */  
  191.     public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;  
  192.   
  193.     // ----------------------------------------------------------------------  
  194.       
  195.     /** 
  196.      * Default variation of {@link #TYPE_CLASS_TEXT}: plain old normal text. 
  197.      */  
  198.     public static final int TYPE_TEXT_VARIATION_NORMAL = 0x00000000;  
  199.       
  200.     /** 
  201.      * Variation of {@link #TYPE_CLASS_TEXT}: entering a URI. 
  202.      */  
  203.     public static final int TYPE_TEXT_VARIATION_URI = 0x00000010;  
  204.       
  205.     /** 
  206.      * Variation of {@link #TYPE_CLASS_TEXT}: entering an e-mail address. 
  207.      */  
  208.     public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020;  
  209.       
  210.     /** 
  211.      * Variation of {@link #TYPE_CLASS_TEXT}: entering the subject line of 
  212.      * an e-mail. 
  213.      */  
  214.     public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030;  
  215.       
  216.     /** 
  217.      * Variation of {@link #TYPE_CLASS_TEXT}: entering a short, possibly informal 
  218.      * message such as an instant message or a text message. 
  219.      */  
  220.     public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040;  
  221.       
  222.     /** 
  223.      * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly  
  224.      * formal message such as the body of an e-mail. 
  225.      */  
  226.     public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050;  
  227.   
  228.     /** 
  229.      * Variation of {@link #TYPE_CLASS_TEXT}: entering the name of a person. 
  230.      */  
  231.     public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060;  
  232.       
  233.     /** 
  234.      * Variation of {@link #TYPE_CLASS_TEXT}: entering a postal mailing address. 
  235.      */  
  236.     public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070;  
  237.       
  238.     /** 
  239.      * Variation of {@link #TYPE_CLASS_TEXT}: entering a password. 
  240.      */  
  241.     public static final int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;  
  242.       
  243.     /** 
  244.      * Variation of {@link #TYPE_CLASS_TEXT}: entering a password, which should 
  245.      * be visible to the user. 
  246.      */  
  247.     public static final int TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090;  
  248.       
  249.     /** 
  250.      * Variation of {@link #TYPE_CLASS_TEXT}: entering text inside of a web form. 
  251.      */  
  252.     public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x000000a0;  
  253.       
  254.     /** 
  255.      * Variation of {@link #TYPE_CLASS_TEXT}: entering text to filter contents 
  256.      * of a list etc. 
  257.      */  
  258.     public static final int TYPE_TEXT_VARIATION_FILTER = 0x000000b0;  
  259.       
  260.     /** 
  261.      * Variation of {@link #TYPE_CLASS_TEXT}: entering text for phonetic 
  262.      * pronunciation, such as a phonetic name field in contacts. This is mostly 
  263.      * useful for languages where one spelling may have several phonetic 
  264.      * readings, like Japanese. 
  265.      */  
  266.     public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0;  
  267.       
  268.     /** 
  269.      * Variation of {@link #TYPE_CLASS_TEXT}: entering e-mail address inside 
  270.      * of a web form.  This was added in 
  271.      * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target 
  272.      * this API version or later to see this input type; if it doesn't, a request 
  273.      * for this type will be seen as {@link #TYPE_TEXT_VARIATION_EMAIL_ADDRESS} 
  274.      * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int) 
  275.      * EditorInfo.makeCompatible(int)}. 
  276.      */  
  277.     public static final int TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 0x000000d0;  
  278.   
  279.     /** 
  280.      * Variation of {@link #TYPE_CLASS_TEXT}: entering password inside 
  281.      * of a web form.  This was added in 
  282.      * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target 
  283.      * this API version or later to see this input type; if it doesn't, a request 
  284.      * for this type will be seen as {@link #TYPE_TEXT_VARIATION_PASSWORD} 
  285.      * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int) 
  286.      * EditorInfo.makeCompatible(int)}. 
  287.      */  
  288.     public static final int TYPE_TEXT_VARIATION_WEB_PASSWORD = 0x000000e0;  
  289.   
  290.     // ----------------------------------------------------------------------  
  291.     // ----------------------------------------------------------------------  
  292.     // ----------------------------------------------------------------------  
  293.       
  294.     /** 
  295.      * Class for numeric text.  This class supports the following flags: 
  296.      * {@link #TYPE_NUMBER_FLAG_SIGNED} and 
  297.      * {@link #TYPE_NUMBER_FLAG_DECIMAL}.  It also supports the following 
  298.      * variations: {@link #TYPE_NUMBER_VARIATION_NORMAL} and 
  299.      * {@link #TYPE_NUMBER_VARIATION_PASSWORD}. 
  300.      * <p>IME authors: If you do not recognize 
  301.      * the variation, normal should be assumed.</p> 
  302.      */  
  303.     public static final int TYPE_CLASS_NUMBER = 0x00000002;  
  304.       
  305.     /** 
  306.      * Flag of {@link #TYPE_CLASS_NUMBER}: the number is signed, allowing 
  307.      * a positive or negative sign at the start. 
  308.      */  
  309.     public static final int TYPE_NUMBER_FLAG_SIGNED = 0x00001000;  
  310.       
  311.     /** 
  312.      * Flag of {@link #TYPE_CLASS_NUMBER}: the number is decimal, allowing 
  313.      * a decimal point to provide fractional values. 
  314.      */  
  315.     public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;  
  316.       
  317.     // ----------------------------------------------------------------------  
  318.   
  319.     /** 
  320.      * Default variation of {@link #TYPE_CLASS_NUMBER}: plain normal 
  321.      * numeric text.  This was added in 
  322.      * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target 
  323.      * this API version or later to see this input type; if it doesn't, a request 
  324.      * for this type will be dropped when passed through 
  325.      * {@link android.view.inputmethod.EditorInfo#makeCompatible(int) 
  326.      * EditorInfo.makeCompatible(int)}. 
  327.      */  
  328.     public static final int TYPE_NUMBER_VARIATION_NORMAL = 0x00000000;  
  329.   
  330.     /** 
  331.      * Variation of {@link #TYPE_CLASS_NUMBER}: entering a numeric password. 
  332.      * This was added in {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An 
  333.      * IME must target this API version or later to see this input type; if it 
  334.      * doesn't, a request for this type will be dropped when passed 
  335.      * through {@link android.view.inputmethod.EditorInfo#makeCompatible(int) 
  336.      * EditorInfo.makeCompatible(int)}. 
  337.      */  
  338.     public static final int TYPE_NUMBER_VARIATION_PASSWORD = 0x00000010;  
  339.   
  340.     // ----------------------------------------------------------------------  
  341.     // ----------------------------------------------------------------------  
  342.     // ----------------------------------------------------------------------  
  343.       
  344.     /** 
  345.      * Class for a phone number.  This class currently supports no variations 
  346.      * or flags. 
  347.      */  
  348.     public static final int TYPE_CLASS_PHONE = 0x00000003;  
  349.       
  350.     // ----------------------------------------------------------------------  
  351.     // ----------------------------------------------------------------------  
  352.     // ----------------------------------------------------------------------  
  353.       
  354.     /** 
  355.      * Class for dates and times.  It supports the 
  356.      * following variations: 
  357.      * {@link #TYPE_DATETIME_VARIATION_NORMAL} 
  358.      * {@link #TYPE_DATETIME_VARIATION_DATE}, and 
  359.      * {@link #TYPE_DATETIME_VARIATION_TIME}. 
  360.      */  
  361.     public static final int TYPE_CLASS_DATETIME = 0x00000004;  
  362.       
  363.     /** 
  364.      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering 
  365.      * both a date and time. 
  366.      */  
  367.     public static final int TYPE_DATETIME_VARIATION_NORMAL = 0x00000000;  
  368.       
  369.     /** 
  370.      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering 
  371.      * only a date. 
  372.      */  
  373.     public static final int TYPE_DATETIME_VARIATION_DATE = 0x00000010;  
  374.       
  375.     /** 
  376.      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering 
  377.      * only a time. 
  378.      */  
  379.     public static final int TYPE_DATETIME_VARIATION_TIME = 0x00000020;  
  380. }  
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import android.text.TextUtils;

/**
 * Bit definitions for an integer defining the basic content type of text
 * held in an {@link Editable} object. Supported classes may be combined
 * with variations and flags to indicate desired behaviors.
 *
 * <h3>Examples</h3>
 *
 * <dl>
 * <dt>A password field with with the password visible to the user:
 * <dd>inputType = TYPE_CLASS_TEXT |
 *     TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
 *
 * <dt>A multi-line postal address with automatic capitalization:
 * <dd>inputType = TYPE_CLASS_TEXT |
 *     TYPE_TEXT_VARIATION_POSTAL_ADDRESS |
 *     TYPE_TEXT_FLAG_MULTI_LINE
 *
 * <dt>A time field:
 * <dd>inputType = TYPE_CLASS_DATETIME |
 *     TYPE_DATETIME_VARIATION_TIME
 * </dl>
 */
public interface InputType {
    /**
     * Mask of bits that determine the overall class
     * of text being given.  Currently supported classes are:
     * {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER},
     * {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}.
     * <p>IME authors: If the class is not one you
     * understand, assume {@link #TYPE_CLASS_TEXT} with NO variation
     * or flags.<p>
     */
    public static final int TYPE_MASK_CLASS = 0x0000000f;
    
    /**
     * Mask of bits that determine the variation of
     * the base content class.
     */
    public static final int TYPE_MASK_VARIATION = 0x00000ff0;
    
    /**
     * Mask of bits that provide addition bit flags
     * of options.
     */
    public static final int TYPE_MASK_FLAGS = 0x00fff000;
    
    /**
     * Special content type for when no explicit type has been specified.
     * This should be interpreted to mean that the target input connection
     * is not rich, it can not process and show things like candidate text nor
     * retrieve the current text, so the input method will need to run in a
     * limited "generate key events" mode, if it supports it. Note that some
     * input methods may not support it, for example a voice-based input
     * method will likely not be able to generate key events even if this
     * flag is set.
     */
    public static final int TYPE_NULL = 0x00000000;
    
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    
    /**
     * Class for normal text.  This class supports the following flags (only
     * one of which should be set):
     * {@link #TYPE_TEXT_FLAG_CAP_CHARACTERS},
     * {@link #TYPE_TEXT_FLAG_CAP_WORDS}, and.
     * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  It also supports the
     * following variations:
     * {@link #TYPE_TEXT_VARIATION_NORMAL}, and
     * {@link #TYPE_TEXT_VARIATION_URI}.  If you do not recognize the
     * variation, normal should be assumed.
     */
    public static final int TYPE_CLASS_TEXT = 0x00000001;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters.  Overrides
     * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and
     * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  This value is explicitly defined
     * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}. Of course,
     * this only affects languages where there are upper-case and lower-case letters.
     */
    public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
     * every word.  Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  This
     * value is explicitly defined
     * to be the same as {@link TextUtils#CAP_MODE_WORDS}. Of course,
     * this only affects languages where there are upper-case and lower-case letters.
     */
    public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
     * each sentence.  This value is explicitly defined
     * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}. For example
     * in English it means to capitalize after a period and a space (note that other
     * languages may have different characters for period, or not use spaces,
     * or use different grammatical rules). Of course,
     * this only affects languages where there are upper-case and lower-case letters.
     */
    public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form
     * text that should have auto-correction applied to it. Without this flag,
     * the IME will not try to correct typos. You should always set this flag
     * unless you really expect users to type non-words in this field, for
     * example to choose a name for a character in a game.
     * Contrast this with {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE} and
     * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}:
     * {@code TYPE_TEXT_FLAG_AUTO_CORRECT} means that the IME will try to
     * auto-correct typos as the user is typing, but does not define whether
     * the IME offers an interface to show suggestions.
     */
    public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: the text editor (which means
     * the application) is performing auto-completion of the text being entered
     * based on its own semantics, which it will present to the user as they type.
     * This generally means that the input method should not be showing
     * candidates itself, but can expect the editor to supply its own
     * completions/candidates from
     * {@link android.view.inputmethod.InputMethodSession#displayCompletions
     * InputMethodSession.displayCompletions()} as a result of the editor calling
     * {@link android.view.inputmethod.InputMethodManager#displayCompletions
     * InputMethodManager.displayCompletions()}.
     * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and
     * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}:
     * {@code TYPE_TEXT_FLAG_AUTO_COMPLETE} means the editor should show an
     * interface for displaying suggestions, but instead of supplying its own
     * it will rely on the Editor to pass completions/corrections.
     */
    public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be
     * entered into the field.  If this flag is not set, the text field 
     * will be constrained to a single line. The IME may also choose not to
     * display an enter key when this flag is not set, as there should be no
     * need to create new lines.
     */
    public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: the regular text view associated
     * with this should not be multi-line, but when a fullscreen input method
     * is providing text it should use multiple lines if it can.
     */
    public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
    
    /**
     * Flag for {@link #TYPE_CLASS_TEXT}: the input method does not need to
     * display any dictionary-based candidates. This is useful for text views that
     * do not contain words from the language and do not benefit from any
     * dictionary-based completions or corrections. It overrides the
     * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set.
     * Please avoid using this unless you are certain this is what you want.
     * Many input methods need suggestions to work well, for example the ones
     * based on gesture typing. Consider clearing
     * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} instead if you just do not
     * want the IME to correct typos.
     * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and
     * {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE}:
     * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME should never
     * show an interface to display suggestions. Most IMEs will also take this to
     * mean they should not try to auto-correct what the user is typing.
     */
    public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;

    // ----------------------------------------------------------------------
    
    /**
     * Default variation of {@link #TYPE_CLASS_TEXT}: plain old normal text.
     */
    public static final int TYPE_TEXT_VARIATION_NORMAL = 0x00000000;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering a URI.
     */
    public static final int TYPE_TEXT_VARIATION_URI = 0x00000010;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering an e-mail address.
     */
    public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering the subject line of
     * an e-mail.
     */
    public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering a short, possibly informal
     * message such as an instant message or a text message.
     */
    public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly 
     * formal message such as the body of an e-mail.
     */
    public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050;

    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering the name of a person.
     */
    public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering a postal mailing address.
     */
    public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering a password.
     */
    public static final int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering a password, which should
     * be visible to the user.
     */
    public static final int TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering text inside of a web form.
     */
    public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x000000a0;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering text to filter contents
     * of a list etc.
     */
    public static final int TYPE_TEXT_VARIATION_FILTER = 0x000000b0;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering text for phonetic
     * pronunciation, such as a phonetic name field in contacts. This is mostly
     * useful for languages where one spelling may have several phonetic
     * readings, like Japanese.
     */
    public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0;
    
    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering e-mail address inside
     * of a web form.  This was added in
     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
     * this API version or later to see this input type; if it doesn't, a request
     * for this type will be seen as {@link #TYPE_TEXT_VARIATION_EMAIL_ADDRESS}
     * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
     * EditorInfo.makeCompatible(int)}.
     */
    public static final int TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 0x000000d0;

    /**
     * Variation of {@link #TYPE_CLASS_TEXT}: entering password inside
     * of a web form.  This was added in
     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
     * this API version or later to see this input type; if it doesn't, a request
     * for this type will be seen as {@link #TYPE_TEXT_VARIATION_PASSWORD}
     * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
     * EditorInfo.makeCompatible(int)}.
     */
    public static final int TYPE_TEXT_VARIATION_WEB_PASSWORD = 0x000000e0;

    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    
    /**
     * Class for numeric text.  This class supports the following flags:
     * {@link #TYPE_NUMBER_FLAG_SIGNED} and
     * {@link #TYPE_NUMBER_FLAG_DECIMAL}.  It also supports the following
     * variations: {@link #TYPE_NUMBER_VARIATION_NORMAL} and
     * {@link #TYPE_NUMBER_VARIATION_PASSWORD}.
     * <p>IME authors: If you do not recognize
     * the variation, normal should be assumed.</p>
     */
    public static final int TYPE_CLASS_NUMBER = 0x00000002;
    
    /**
     * Flag of {@link #TYPE_CLASS_NUMBER}: the number is signed, allowing
     * a positive or negative sign at the start.
     */
    public static final int TYPE_NUMBER_FLAG_SIGNED = 0x00001000;
    
    /**
     * Flag of {@link #TYPE_CLASS_NUMBER}: the number is decimal, allowing
     * a decimal point to provide fractional values.
     */
    public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;
    
    // ----------------------------------------------------------------------

    /**
     * Default variation of {@link #TYPE_CLASS_NUMBER}: plain normal
     * numeric text.  This was added in
     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
     * this API version or later to see this input type; if it doesn't, a request
     * for this type will be dropped when passed through
     * {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
     * EditorInfo.makeCompatible(int)}.
     */
    public static final int TYPE_NUMBER_VARIATION_NORMAL = 0x00000000;

    /**
     * Variation of {@link #TYPE_CLASS_NUMBER}: entering a numeric password.
     * This was added in {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An
     * IME must target this API version or later to see this input type; if it
     * doesn't, a request for this type will be dropped when passed
     * through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
     * EditorInfo.makeCompatible(int)}.
     */
    public static final int TYPE_NUMBER_VARIATION_PASSWORD = 0x00000010;

    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    
    /**
     * Class for a phone number.  This class currently supports no variations
     * or flags.
     */
    public static final int TYPE_CLASS_PHONE = 0x00000003;
    
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    // ----------------------------------------------------------------------
    
    /**
     * Class for dates and times.  It supports the
     * following variations:
     * {@link #TYPE_DATETIME_VARIATION_NORMAL}
     * {@link #TYPE_DATETIME_VARIATION_DATE}, and
     * {@link #TYPE_DATETIME_VARIATION_TIME}.
     */
    public static final int TYPE_CLASS_DATETIME = 0x00000004;
    
    /**
     * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
     * both a date and time.
     */
    public static final int TYPE_DATETIME_VARIATION_NORMAL = 0x00000000;
    
    /**
     * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
     * only a date.
     */
    public static final int TYPE_DATETIME_VARIATION_DATE = 0x00000010;
    
    /**
     * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
     * only a time.
     */
    public static final int TYPE_DATETIME_VARIATION_TIME = 0x00000020;
}


由于位掩码方式又一个很大的问题,就是类型安全,如果不对类型安全控制后果会难以想象,因此枚举被用进去,以对参数类型进行控制,源码当中使用的是@IntDef,而EnumSet作为新的实现形式,在任何方面都比位掩码方式差不多或者更好,可读性,性能,以及类型安全等。权限逻辑如下:


  1. public class NewPermission2 {  
  2.   
  3.   private EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class);  
  4.   
  5.   private enum Permission {  
  6.     SELECT, INSERT, UPDATE, DELETE;  
  7.   
  8.     public static final EnumSet<Permission> ALL_PERMISSIONS = EnumSet.allOf(Permission.class);  
  9.     public static final EnumSet<Permission> VIP_PERMISSIONS =  
  10.         EnumSet.range(Permission.SELECT, Permission.UPDATE);  
  11.   }  
  12.   
  13.   /** 
  14.    * 重新设置权限 
  15.    */  
  16.   public void setPermission(EnumSet<Permission> s) {  
  17.     this.permissions.clear();  
  18.     this.permissions = s;  
  19.   }  
  20.   
  21.   /** 
  22.    * 删除一项或多项权限 
  23.    */  
  24.   public void disable(Permission permission) {  
  25.     permissions.remove(permission);  
  26.   }  
  27.   
  28.   /** 
  29.    * 是否拥某些权限 
  30.    */  
  31.   public boolean isAllow(Permission s) {  
  32.     return permissions.contains(s);  
  33.   }  
  34.   
  35.   /** 
  36.    * 是否是游客 
  37.    */  
  38.   public boolean isVip(Permission s) {  
  39.     return Permission.VIP_PERMISSIONS.contains(s);  
  40.   }  
  41. }  
public class NewPermission2 {

  private EnumSet<Permission> permissions = EnumSet.noneOf(Permission.class);

  private enum Permission {
    SELECT, INSERT, UPDATE, DELETE;

    public static final EnumSet<Permission> ALL_PERMISSIONS = EnumSet.allOf(Permission.class);
    public static final EnumSet<Permission> VIP_PERMISSIONS =
        EnumSet.range(Permission.SELECT, Permission.UPDATE);
  }

  /**
   * 重新设置权限
   */
  public void setPermission(EnumSet<Permission> s) {
    this.permissions.clear();
    this.permissions = s;
  }

  /**
   * 删除一项或多项权限
   */
  public void disable(Permission permission) {
    permissions.remove(permission);
  }

  /**
   * 是否拥某些权限
   */
  public boolean isAllow(Permission s) {
    return permissions.contains(s);
  }

  /**
   * 是否是游客
   */
  public boolean isVip(Permission s) {
    return Permission.VIP_PERMISSIONS.contains(s);
  }
}

EnumSet具体实现可参看源码。个人觉得这种方式最大的好处,在于可控,无论是对业务逻辑很好理解,还是对代码实现的方便,各个方面来看,都是要比位掩码这种取巧方式的官方化。可是对于android开发的性能方面:

1 存在个别反射的身影

2 EnumSet是实现Set的集合类

基于以上两点,那么在设计用到Enumset的类的时候,还是需要谨慎一些,尽管官方给出了很可靠的保证。



另外一些讲得不错的博文:

http://eddmann.com/posts/using-bit-flags-and-enumsets-in-java/

http://dhruba.name/2008/12/31/effective-java-item-32-use-enumset-instead-of-bit-fields/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值