zoukankan      html  css  js  c++  java
  • Android Phonebook编写联系人UI加载及联系人保存流程(五)

    2014-01-07 10:46:30 将百度空间里的东西移过来。

    在前面的文章中我们分析了UI的加载,其中提到了一个重要的对象:RawContactDeltaList mState,我前面说过这个对象很重要,和联系人保存有关,现在就分析一下联系人到底是怎么保存的。

    1. 千里追踪mState

    ContactEditorFragment类 bindEditorsForNewContact()方法中创建了一个RawContactDelta对象insert,代码如下:

     1 private void bindEditorsForNewContact(AccountWithDataSet newAccount,
     2         final AccountType newAccountType, RawContactDelta oldState,
     3         AccountType oldAccountType) {
     4  
     5     final RawContact rawContact = new RawContact(mContext);
     6     if (newAccount != null) {
     7         rawContact.setAccount(newAccount);
     8     } else {
     9         rawContact.setAccountToLocalContact();
    10     }
    11  
    12     RawContactDelta insert = new RawContactDelta(
    13         ValuesDelta.fromAfter(rawContact.getValues()));
    14  
    15     if (mState == null) {
    16         // Create state if none exists yet
    17         mState = RawContactDeltaList.fromSingle(insert);
    18     } else {
    19         // Add contact onto end of existing state
    20         mState.add(insert);
    21     }
    22 }

    mState是一个RawContactDeltaList对象,而insert是一个RawContactDelta,上面代码中mState.add(insert),接着看,在bindEditors()方法中:

     1 RawContactDelta rawContactDelta = getFirstVisibleContact();
     2 if (rawContactDelta != null) {
     3     editor = createContactEditorView(rawContactDelta);
     4 }
     5  
     6 private RawContactDelta getFirstVisibleContact() {
     7     for (final RawContactDelta rawContactDelta : mState) {
     8         if (!rawContactDelta.isVisible()) continue;
     9         return rawContactDelta;
    10     }
    11     return null;
    12 }

    我们发现,createContactEditorView(rawContactDelta)中的rawContactDelta就是mState中的第一个对象,也就是前面创建的insert,那么insert究竟什么呢?

    insert = (Uri=content://com.android.contacts/raw_contacts,
        Values={ 
             IdColumn=_id, FromTemplate=false, data_set=null, _id=-2,
             account_name=Phone contacts,
             account_type=com.android.localcontacts, },
             Entries={})

    可以看到,此时的insert只不过是一个只包含account信息,Entries为空的RawContactDelta对象,这个对象被当作参数传给createContactEditorView(rawContactDelta)方法,该方法中有:

    1 editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile());

    我们前面分析过,editor是一个自定义的BaseRawContactEditorView,参数如下:

    rawContactDelta:传进来的RawContactDelta对象;

    type:账户类型,此处为LocalAccountType;

    isEditingUserProfile():是否是要编辑“我自己”条目;

    此时rawContactDelta对象进入BaseRawContactEditorView类,该类又调用了父类RawContactCommonEditorView的super.setState(state, type, vig, isProfile);该方法有一个重要的else语句块,前面分析过,如下:

    1 else {
    2      // Otherwise use generic section-based editors
    3      if (kind.fieldList == null) continue;
    4      final KindSectionView section = (KindSectionView)mInflater.inflate(R.layout.item_kind_section, mFields, false);
    5      section.setEnabled(isEnabled());
    6      section.setState(kind, state, false, vig);
    7      mFields.addView(section);
    8 }

    rawContactDelta又被当作参数传到KindSectionView, 通过代码section.setState(kind, state, false, vig);进入KindSectionView类,在rebuildFromState()方法中:

     1 if (hasEntries) {
     2     for (ValuesDelta entry : mState.getMimeEntries(mKind.mimeType)) {
     3         // Skip entries that aren't visible
     4         if (!entry.isVisible())
     5             continue;
     6         if (isEmptyNoop(entry))
     7             continue;
     8  
     9         createEditorView(entry);
    10     }
    11 }

    可以看到,在这里mState.getMimeEntries(mKind.mimeType),根mKind.mimeType从mState中取出entry,然后把entry传到reateEditorView()方法中,有如下代码:

     1 private View createEditorView(ValuesDelta entry) {
     2     final View view;
     3     try {
     4         view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, false);
     5     } catch (Exception e) {
     6     }
     7  
     8     view.setEnabled(isEnabled());
     9  
    10     if (view instanceof Editor) {
    11         Editor editor = (Editor) view;
    12         editor.setDeletable(true);
    13         editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);
    14         editor.setEditorListener(this);
    15     }
    16     mEditors.addView(view);
    17     return view;
    18 }

    发现rawContactDelta以及根据mimetype生成的entry,又被当作参数传送,通过editor.setValues()方法,前面分析过editor是TextFieldsEditorView,那么看它的setValue()方法:

    1 int fieldCount = kind.fieldList.size();
    2 mFieldEditTexts = new EditText[fieldCount];
    3 for (int index = 0; index < fieldCount; index++) {
    4     final EditField field = kind.fieldList.get(index);
    5     final EditText fieldView = createFieldView(field.column);
    6 ...

    这个方法应该很熟悉了,就是根据kind中fieldlist加载EditText的那个方法,同时还给生成的EditText注册了一个TextChangedListener, 如下:

    1 fieldView.addTextChangedListener(new TextWatcher() {
    2     @Override
    3     public void afterTextChanged(Editable s) {
    4         // Trigger event for newly changed value
    5         onFieldChanged(column, s.toString());
    6     }
    7 });

    至于传进来的rawContactDelta和entry对象,调用了父类的setValues()方法,并将它们分别赋给了LabeledEditorView的mState和mEntry对象。既然给EditText对象添加了TextChangedListener,那么我们可以想到,应该是EditText中的内容发生改变后触发设置的监听方法,看这个监听方法:

    1 @Override
    2 public void onFieldChanged(String column,
    3     String value) {
    4     if (!isFieldChanged(column, value)) {
    5         return;
    6     }
    7     saveValue(column, value);
    8     notifyEditorListener();
    9 }

    onFieldChanged()方法是在LabeledEditorView类里,和mState,mEntry对象在同一个类,我们看他的saveValue()方法:

    1 protected void saveValue(String column, String value) {
    2     mEntry.put(column, value);
    3 }

    我们发现,最终把用户输入的信息放到了mEntry中,既然mEntry是从mState中生成的,那么这些值也就保存到mState,我们在saveValue()方法中打Log,如下:

    1 protected void saveValue(String column, String value) {
    2     Log.d("David", "column = " + column);
    3     Log.d("David", "value = " + value);
    4     mEntry.put(column, value);
    5     Log.d("David", "mState = " + mState);
    6 }

    如上图,我只在Name里面输入了“D”,我们看log截图:

    column就是BaseAccountType中“StructuredName.GIVEN_NAME”,data2和数据库中的field是对应的,关于数据库,以后再分析;

    1 kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    2                    FLAGS_PERSON_NAME).setNeedFocus(true));

    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时,要用到这个对象,以及该对象包含的值。

  • 相关阅读:
    C#生成MD5的方法
    平常心是道
    Android 三种动画的使用 – Tween Animation
    17个Javascript日期选择器
    Javascript解码编码常用函数
    mysql 命令行导入导出数据
    技术驱动还是产品驱动
    Ubuntu 和 Redhat / Fedora 服务管理命令对比表
    jquery常用技巧
    Fedora 17安装JDK1.7
  • 原文地址:https://www.cnblogs.com/wlrhnh/p/3508401.html
Copyright © 2011-2022 走看看