2014-01-07 10:46:30 將百度空間裡的東西移過來。
在前面的文章中我們分析了UI的載入,其中提到了一個重要的對象:RawContactDeltaList mState,我前面說過這個對象很重要,和連絡人儲存有關,現在就分析一下連絡人到底是怎麼儲存的。
1. 千裡追蹤mState
ContactEditorFragment類 bindEditorsForNewContact()方法中建立了一個RawContactDelta對象insert,代碼如下:
RawContact rawContact = (newAccount != } RawContactDelta insert = (mState == mState = } }
mState是一個RawContactDeltaList對象,而insert是一個RawContactDelta,上面代碼中mState.add(insert),接著看,在bindEditors()方法中:
RawContactDelta rawContactDelta = (rawContactDelta != editor = ( (!rawContactDelta.isVisible()) }
我們發現,createContactEditorView(rawContactDelta)中的rawContactDelta就是mState中的第一個對象,也就是前面建立的insert,那麼insert究竟什麼呢?
insert = (Uri=content: Values==_id, FromTemplate=, data_set=, _id=-2==={})
可以看到,此時的insert只不過是一個只包含account資訊,Entries為空白的RawContactDelta對象,這個對象被當作參數傳給createContactEditorView(rawContactDelta)方法,該方法中有:
editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile());
我們前面分析過,editor是一個自訂的BaseRawContactEditorView,參數如下:
rawContactDelta:傳進來的RawContactDelta對象;
type:賬戶類型,此處為LocalAccountType;
isEditingUserProfile():是否是要編輯“我自己”條目;
此時rawContactDelta對象進入BaseRawContactEditorView類,該類又調用了父類RawContactCommonEditorView的super.setState(state, type, vig, isProfile);該方法有一個重要的else語句塊,前面分析過,如下:
(kind.fieldList == ) KindSectionView section = (KindSectionView)mInflater.inflate(R.layout.item_kind_section, mFields, section.setState(kind, state, }
rawContactDelta又被當作參數傳到KindSectionView, 通過代碼section.setState(kind, state, false, vig);進入KindSectionView類,在rebuildFromState()方法中:
(! }
可以看到,在這裡mState.getMimeEntries(mKind.mimeType),根mKind.mimeType從mState中取出entry,然後把entry傳到reateEditorView()方法中,有如下代碼:
view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, } (view Editor editor = editor.setDeletable( editor.setEditorListener( }
發現rawContactDelta以及根據mimetype產生的entry,又被當作參數傳送,通過editor.setValues()方法,前面分析過editor是TextFieldsEditorView,那麼看它的setValue()方法:
fieldCount = mFieldEditTexts = ( index = 0; index < fieldCount; index++ EditField field = EditText fieldView = ...
這個方法應該很熟悉了,就是根據kind中fieldlist載入EditText的那個方法,同時還給產生的EditText註冊了一個TextChangedListener, 如下:
fieldView.addTextChangedListener( });
至於傳進來的rawContactDelta和entry對象,調用了父類的setValues()方法,並將它們分別賦給了LabeledEditorView的mState和mEntry對象。既然給EditText對象添加了TextChangedListener,那麼我們可以想到,應該是EditText中的內容發生改變後觸發設定的監聽方法,看這個監聽方法:
(! }
onFieldChanged()方法是在LabeledEditorView類裡,和mState,mEntry對象在同一個類,我們看他的saveValue()方法:
}
我們發現,最終把使用者輸入的資訊放到了mEntry中,既然mEntry是從mState中產生的,那麼這些值也就儲存到mState,我們在saveValue()方法中打Log,如下:
Log.d("David", "column = " + Log.d("David", "value = " + Log.d("David", "mState = " + }
如,我只在Name裡面輸入了“D”,我們看log:
column就是BaseAccountType中“StructuredName.GIVEN_NAME”,data2和資料庫中的field是對應的,關於資料庫,以後再分析;
kind.fieldList.add( FLAGS_PERSON_NAME).setNeedFocus());
value表示的是使用者輸入的值;
mState是從ContactEditorFragment中傳進來的RawContactDelta對象,取自RawContactDeltaList mState,這個mState(ContactEditorFragment中的)對象非常重要,因為當使用者儲存連絡人時,會用到它。中倒數第二行,mimetype=vnd.android.cursor.item/name, data2=D,也就是說,使用者輸入的連絡人資訊是儲存在對應的mimetype,比如這個是Name,下面我同時輸入姓名和號碼,再看一下log:
其中我輸入的Name=David,number=18611975588.
上面我們千裡追mState,以及弄清楚了使用者輸入的資料是怎麼組織的,只是因為當使用者點擊儲存Button時,要用到這個對象,以及該對象包含的值。