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