Android Phonebook编写联系人UI加载及联系人保存流程(二)

2014-01-06 17:18:29 

1. Phonebook中新建/编辑联系人的UI不是用xml文件写的,它是随着帐号类型的改变来加载不同的UI,比如SIM联系人,只有Name、Phone Number,如果是USIM,或许还有第二个号码、Email,但是本地联系人除了包含这些,还有Nickname,Website等,所以帐号如何定义以及UI如何加载就变得很复杂。

2. 帐号类型(以AdnAccountType SIM帐号为例)

继承关系:AdnAccountType.java --> BaseAccountType.java --> AccountType.java,在AccountType中有两个很重要的方法,如下:

 1 public ArrayList<DataKind> getSortedDataKinds() {

 2     Collections.sort(mKinds, sWeightComparator);

 3     return mKinds;

 4 }

 5  

 6 public DataKind addKind(DataKind kind) throws DefinitionException {

 7     kind.resourcePackageName = this.resourcePackageName;

 8     this.mKinds.add(kind);

 9     this.mMimeKinds.put(kind.mimeType, kind);

10     return kind;

11 }

addKind()方法添加kind到mKinds,getSortedDataKinds()取出来所有的kind,这两个方法的使用将在后面介绍。关于BaseAccountType,这个类是所有帐号类的父类,下面看AdnAccountType:

 1 public AdnAccountType(Context context, String resPackageName, String accountType) {

 2     this.accountType = accountType;

 3     //this.resPackageName = null;

 4     this.syncAdapterPackageName = resPackageName;

 5 

 6     try {

 7         addDataKindStructuredName(context);

 8         addDataKindPhone(context);

 9 

10         int simType = SimUtil.getIccType(context, AdnHelper.getSlotNumber(accountType));

11         if (simType == IccProviderConstant.USIM_TYPE

12                 || simType == IccProviderConstant.CSIM_TYPE) {

13             addDataKindEmail(context);

14         }

15 

16         mIsInitialized = true;

17     } catch (DefinitionException e) {

18         SpbLog.e(TAG, "Problem building account type", e);

19     }

20 }

21 

22 @Override

23 protected DataKind addDataKindStructuredName(Context context) throws DefinitionException {

24     DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,

25             R.string.nameLabelsGroup, -1, true, R.layout.structured_name_editor_view));

26 

27     kind.fieldList = Lists.newArrayList();

28     kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.nameLabelsGroup,

29             FLAGS_PERSON_NAME).setNeedFocus(true));

30 

31     return kind;

32 }

33 

34 @Override

35 protected DataKind addDataKindPhone(Context context) throws DefinitionException {

36     DataKind kind = super.addDataKindPhone(context);

37 

38     kind.iconAltRes = R.drawable.ic_message_icon;

39     kind.actionHeader = new PhoneActionInflater();

40     kind.actionAltHeader = new PhoneActionAltInflater();

41     kind.actionBody = new SimpleInflater(Phone.NUMBER);

42 

43     kind.typeColumn = Phone.TYPE;

44     kind.typeList = Lists.newArrayList();

45     kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));

46 

47     kind.fieldList = Lists.newArrayList();

48     kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));

49 

50     return kind;

51 }

可以看到,SIM卡帐号添加了Name和Phone number两种数据的UI,这符合SIM联系人只能添加名称和号码的规则,如果SIM卡是USIM或者CSIM,那么还可以添加Email信息,看if判断语句就知道了。在addDataKindStructuredName()方法里面,调用了前面介绍的addKind()方法,将一个DataKind对象添加进去,同时为这个DataKind对象的fieldList添加了EditField,这个fieldList包含的是要显示的View,其实就是phone number或者Email条目包含的子条目,这些item会在后面具体介绍。下面看一下较复杂的LocalAccountType:

 1 public LocalAccountType(Context context, String resPackageName) {

 2     this.accountType = SpbIntents.ACCOUNT_TYPE;

 3     this.resourcePackageName = null;

 4     this.syncAdapterPackageName = resPackageName;

 5 

 6     try {

 7         addDataKindStructuredName(context);

 8         addDataKindNickname(context);

 9         addDataKindPhone(context);

10         addDataKindEmail(context);

11         addDataKindStructuredPostal(context);

12         addDataKindIm(context);

13         addDataKindOrganization(context);

14         addDataKindPhoto(context);

15         addDataKindNote(context);

16         addDataKindWebsite(context);

17         addDataKindEvent(context);

18         addDataKindSipAddress(context);

19         addDataKindGroupMembership(context);

20 

21         mIsInitialized = true;

22     } catch (DefinitionException e) {

23         SpbLog.e(TAG, "Problem building account type", e);

24     }

25 }

26 

27 @Override

28 protected DataKind addDataKindPhone(Context context) throws DefinitionException {

29     final DataKind kind = super.addDataKindPhone(context);

30 

31     kind.typeColumn = Phone.TYPE;

32     kind.typeList = Lists.newArrayList();

33     kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));

34     kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));

35     kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));

36     kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));

37     kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));

38     kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));

39     kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));

40     kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(

41             Phone.LABEL));

42 

43     kind.fieldList = Lists.newArrayList();

44     kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));

45 

46     return kind;

47 }

可以看到,本地帐号包含更多的信息,而且光Phone number就包含了好多类型,如HOME,MOBILE,FAX等。

addDataKindStructuredName添加的是姓名相关的UI,都包含在在kind.fieldList中,每一个EditField基本可以认为是一个EditTest,如图:

Android Phonebook编写联系人UI加载及联系人保存流程(二)

 

而addDataKindPhone添加的是PhoneNumber相关的UI,kind.fieldList只包含一个EditField,可以看见只有一个EditText,但是kind.typeList添加了很多东西,可以通过点击Type Spinner来看到,共八个,和代码一致,如下图:

Android Phonebook编写联系人UI加载及联系人保存流程(二)

 

3. 上面分析了一个帐号类型类包含的东西,包含了一些DataKind,而每一个DataKind又有kind.typeList,kind.fieldList以及其他的属性。所以一个DataKind代表一个类型的信息,如Name,Phone number,Email等,但是Name里面包含很多具体信息,如prefix,suffix,first name等,Phone number里面包含一个EditText,但是有很多种号码类型等等,这样构成了一个完整的帐号类,而在加载UI的时候,就是根据当前的帐号来添加帐号里面包含的UI。具体如何加载后面分析。

4. 上面的分析涉及到两个辅助类:DataKind和EditField,下面分别看一下这两个类:

 1 public final class DataKind {

 2  

 3     public String resourcePackageName;

 4     public String mimeType;

 5     public int titleRes;

 6     public int iconAltRes;

 7     public int iconAltDescriptionRes;

 8     public int weight;

 9     public boolean secondary;

10     public boolean editable;

11     public StringInflater actionHeader;

12     public StringInflater actionAltHeader;

13     public StringInflater actionBody;

14     public boolean actionBodySocial = false;

15     public String typeColumn;

16     public int typeOverallMax;

17     public List<EditType> typeList;

18     public List<EditField> fieldList;

19     public ContentValues defaultValues;

20     public final int editorLayoutResourceId;

21     public SimpleDateFormat dateFormatWithoutYear;

22     public SimpleDateFormat dateFormatWithYear;

23  

24     public int maxLinesForDisplay;

25  

26     public DataKind() {

27         editorLayoutResourceId = R.layout.text_fields_editor_view;

28         maxLinesForDisplay = 1;

29     }

30  

31     public DataKind(String mimeType, int titleRes, int weight, boolean editable,

32             int editorLayoutResourceId) {

33         this.mimeType = mimeType;

34         this.titleRes = titleRes;

35         this.weight = weight;

36         this.editable = editable;

37         this.typeOverallMax = -1;

38         this.editorLayoutResourceId = editorLayoutResourceId;

39         maxLinesForDisplay = 1;

40     }

41 }

由上可见,DataKind就是一个封装信息的类,只起到封装信息的作用。

 1 public static final class EditField {

 2     public String column;

 3     public int titleRes;

 4     public int inputType;

 5     public int minLines;

 6     public boolean optional;

 7     public boolean shortForm;

 8     public boolean longForm;

 9     public boolean needFocus = false;

10     public boolean editable = true;

11  

12     public InputFilter[] inputFilters;

13  

14     public EditField(String column, int titleRes) {

15         this.column = column;

16         this.titleRes = titleRes;

17     }

18  

19     public EditField(String column, int titleRes, int inputType) {

20         this(column, titleRes);

21         this.inputType = inputType;

22     }

23  

24     public EditField setOptional(boolean optional) {

25         this.optional = optional;

26         return this;

27     }

28     public EditField setShortForm(boolean shortForm) {

29         this.shortForm = shortForm;

30         return this;

31     }

32  

33     public EditField setLongForm(boolean longForm) {

34         this.longForm = longForm;

35         return this;

36     }

37  

38     public EditField setMinLines(int minLines) {

39         this.minLines = minLines;

40         return this;

41     }

42  

43     public boolean isMultiLine() {

44         return (inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0;

45     }

46  

47     public EditField setNeedFocus(boolean needFocus){

48         this.needFocus = needFocus;

49         return this;

50     }

51     public EditField setEditable(boolean editable) {

52         this.editable = editable;

53         return this;

54     }

55 }

EditField与DataKind类似,封装了一些信息,至于这些信息是如何被解析的,在真正加载UI的时候再分析。

你可能感兴趣的:(android)