ContentValues介紹及使用


轉自https://www.cnblogs.com/xiaocai20091687/p/xiaocai-android-contentvalues.html

這本篇博客里面我想重點來分析一下ContentValues的源碼以及它里面涉及到的繼承接口Parcelabel,還有HashMap的源碼。

      相信使用過android里面數據庫操作的朋友對於ContentValues一定不會感到陌生吧,它其實很像一個字典對象,可以用來存儲鍵值對。比如代碼如下:

1
2
3
4
ContentValues contentValues= new  ContentValues();
contentValues.put( "name" , "xiao" );
contentValues.put( "age" , 20 );
contentValues.put( "isStudent" , true );

 你會發現ContentValues里面可以用來put各種類型的數據,它是怎樣擁有這種神奇的功能的呢?下面讓我們來看看它的源碼。首先,是ContentValues類的定義:

1
2
public  final  class  ContentValues  implements  Parcelable {
}

 我們可以看到它實現了Parcelabel接口,這個接口主要是用來實現數據安裝、傳輸相關操作的。說到這里,讓我們也來看看Parcelabel接口里面到底定義了哪些方法,源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  interface  Parcelable {
    
     public  static  final  int  PARCELABLE_WRITE_RETURN_VALUE =  0x0001 ;
     
     public  static  final  int  CONTENTS_FILE_DESCRIPTOR =  0x0001 ;
     
     public  int  describeContents();
     
     public  void  writeToParcel(Parcel dest,  int  flags);
 
     public  interface  Creator<T> {
        
         public  T createFromParcel(Parcel source);
         
         public  T[] newArray( int  size);
     }
 
     public  interface  ClassLoaderCreator<T>  extends  Creator<T> {
        
         public  T createFromParcel(Parcel source, ClassLoader loader);
     }
}

 我們可以看到里面有個writeToParcel方法是用來傳輸數據的,至於它是怎么用來包裝數據的,就要看看具體實現Parcelabel接口類的實現了。

       好了說回我們所要討論的重點對象ContentValues,首先來看看ContentValues里面包括的構造函數,源碼如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private  HashMap<String, Object> mValues;
 
public  ContentValues() {
     // Choosing a default size of 8 based on analysis of typical
     // consumption by applications.
     mValues =  new  HashMap<String, Object>( 8 );
}
 
/**
  * Creates an empty set of values using the given initial size
  *
  * @param size the initial size of the set of values
  */
public  ContentValues( int  size) {
     mValues =  new  HashMap<String, Object>(size,  1 .0f);
}
 
/**
  * Creates a set of values copied from the given set
  *
  * @param from the values to copy
  */
public  ContentValues(ContentValues from) {
     mValues =  new  HashMap<String, Object>(from.mValues);
}
 
/**
  * Creates a set of values copied from the given HashMap. This is used
  * by the Parcel unmarshalling code.
  *
  * @param values the values to start with
  * {@hide}
  */
private  ContentValues(HashMap<String, Object> values) {
     mValues = values;
}

 相信大家從注釋里面就能夠看看,ContentValues的構造主要是根據代碼里面傳入的具體參數來構造對應的HashMap對象,然后里面的各種put操作、get操作、remove操作都是針對HashMap進行的,其中put類型的方法源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public  void  put(String key, String value) {
     mValues.put(key, value);
}
 
public  void  putAll(ContentValues other) {
     mValues.putAll(other.mValues);
}
 
public  void  put(String key, Byte value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Short value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Integer value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Long value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Float value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Double value) {
     mValues.put(key, value);
}
 
public  void  put(String key, Boolean value) {
     mValues.put(key, value);
}
 
public  void  put(String key,  byte [] value) {
     mValues.put(key, value);
}
 
public  void  putNull(String key) {
     mValues.put(key,  null );
}

 通過上面的方法,我們就能夠明白為什么ContentValues能夠put各種類型的數值了吧,接下來讓我們來看看get方法,源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
public  Object get(String key) {
        return  mValues.get(key);
    }
 
    public  String getAsString(String key) {
        Object value = mValues.get(key);
        return  value !=  null  ? value.toString() :  null ;
    }
 
    public  Long getAsLong(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).longValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Long.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Long value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Long: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Integer getAsInteger(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).intValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Integer.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Integer value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Integer: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Short getAsShort(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).shortValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Short.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Short value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Short: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Byte getAsByte(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).byteValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Byte.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Byte value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Byte: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Double getAsDouble(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).doubleValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Double.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Double value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Double: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Float getAsFloat(String key) {
        Object value = mValues.get(key);
        try  {
            return  value !=  null  ? ((Number) value).floatValue() :  null ;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                try  {
                    return  Float.valueOf(value.toString());
                catch  (NumberFormatException e2) {
                    Log.e(TAG,  "Cannot parse Float value for "  + value +  " at key "  + key);
                    return  null ;
                }
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Float: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  Boolean getAsBoolean(String key) {
        Object value = mValues.get(key);
        try  {
            return  (Boolean) value;
        catch  (ClassCastException e) {
            if  (value  instanceof  CharSequence) {
                return  Boolean.valueOf(value.toString());
            else  if  (value  instanceof  Number) {
                return  ((Number) value).intValue() !=  0 ;
            else  {
                Log.e(TAG,  "Cannot cast value for "  + key +  " to a Boolean: "  + value, e);
                return  null ;
            }
        }
    }
 
    public  byte [] getAsByteArray(String key) {
        Object value = mValues.get(key);
        if  (value  instanceof  byte []) {
            return  ( byte []) value;
        else  {
            return  null ;
        }
    }

 通過上面的代碼我們也能很直觀的看到,不同的get方法通過調用不同類型的((Number)value).intValue方法強轉一次獲取,如果拿不到的話就返回null。

       既然ContentValues是基於HashMap去實現操作的,那么我們有必要來看看HashMap到底是怎么回事?首先是HashMap類定義,源碼如下所示:

1
2
public  class  HashMap<K, V>  extends  AbstractMap<K, V>  implements  Cloneable, Serializable{
}

 通過上面的代碼,我們可以看到HashMap是基於泛型去構建的,同時實現了克隆和序列化接口。這就意味着在一定程度上面,我們可以實例化任何類型的HashMap,並且使它具有克隆、序列化的功能,請看如下代碼:

1
2
3
4
HashMap<Integer,Object> hashOne= new  HashMap<>();
HashMap<String,Object> hashTwo= new  HashMap<>();
HashMap<Boolean,Object> hashThree= new  HashMap<>();
HashMap<Float,Object> hashFour= new  HashMap<>();

 只不過我們通常在項目里面一般都習慣使用String類型的key。好了,讓我們繼續往下看,首先最應該說的就是HashMapEntry內部靜態類了,源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static  class  HashMapEntry<K, V>  implements  Entry<K, V> {
         final  K key;
         V value;
         final  int  hash;
         HashMapEntry<K, V> next;
 
         HashMapEntry(K key, V value,  int  hash, HashMapEntry<K, V> next) {
             this .key = key;
             this .value = value;
             this .hash = hash;
             this .next = next;
         }
 
         public  final  K getKey() {
             return  key;
         }
 
         public  final  V getValue() {
             return  value;
         }
 
         public  final  V setValue(V value) {
             V oldValue =  this .value;
             this .value = value;
             return  oldValue;
         }
 
         @Override  public  final  boolean  equals(Object o) {
             if  (!(o  instanceof  Entry)) {
                 return  false ;
             }
             Entry<?, ?> e = (Entry<?, ?>) o;
             return  Objects.equal(e.getKey(), key)
                     && Objects.equal(e.getValue(), value);
         }
 
         @Override  public  final  int  hashCode() {
             return  (key ==  null  0  : key.hashCode()) ^
                     (value ==  null  0  : value.hashCode());
         }
 
         @Override  public  final  String toString() {
             return  key +  "="  + value;
         }
     }

 HashMapEntry類實現了Entry接口,而Entry接口又是Map接口里面的一個內部接口。通過實現Entry接口,從而使HashMap具有了getKey/getValue/setValue等相關功能。同時我們可以看到HashMap里面好多功能的實現都是針對HashMapEntry展開的。另外HashMap還有個比較重要的概念就是Set接口,讓我們來看看里面final類型的私有內部類EntrySet,源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private  final  class  EntrySet  extends  AbstractSet<Entry<K, V>> {
         public  Iterator<Entry<K, V>> iterator() {
             return  newEntryIterator();
         }
         public  boolean  contains(Object o) {
             if  (!(o  instanceof  Entry))
                 return  false ;
             Entry<?, ?> e = (Entry<?, ?>) o;
             return  containsMapping(e.getKey(), e.getValue());
         }
         public  boolean  remove(Object o) {
             if  (!(o  instanceof  Entry))
                 return  false ;
             Entry<?, ?> e = (Entry<?, ?>)o;
             return  removeMapping(e.getKey(), e.getValue());
         }
         public  int  size() {
             return  size;
         }
         public  boolean  isEmpty() {
             return  size ==  0 ;
         }
         public  void  clear() {
             HashMap. this .clear();
         }
     }

 正如其名一樣,Set接口里面主要是提供HashMap的設置相關操作。讓我們來看看Set接口里面的源碼,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public  boolean  add(E object);
 
public  boolean  addAll(Collection<?  extends  E> collection);
 
public  void  clear();
 
public  boolean  contains(Object object);
 
public  boolean  containsAll(Collection<?> collection);
 
public  boolean  equals(Object object);
 
public  int  hashCode();
 
public  boolean  isEmpty();
 
public  Iterator<E> iterator();
 
public  boolean  remove(Object object);
 
public  boolean  removeAll(Collection<?> collection);
 
public  boolean  retainAll(Collection<?> collection);
 
public  int  size();
 
public  Object[] toArray();
 
public  <T> T[] toArray(T[] array);

       好了,今天博客就到這里。技術有限,如有不對歡迎拍磚!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM