Android 5.1 Contacts源码分析:Contacts模块Fargment结构

Posted ximsfei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 5.1 Contacts源码分析:Contacts模块Fargment结构相关的知识,希望对你有一定的参考价值。

1. Contacts 模块Fragment结构:

下图为联系人模块主要窗口中的Fragment类图:

从类图中可以看出,联系人大部分原生的列表界面(主界面,多选界面等,余下Fragment未列出),其中的Fragment都继承自ContactEntryListFragment,,而基类

ContactEntryListFragment<T extends ContactEntryListAdapter>

实现了下面五个接口:

OnFocusChangeListener         //监听焦点变化;
OnTouchListener               //监听触摸时间;
LoaderManager.LoaderCallbacks //返回LoaderManager中加载的数据;
OnScrollListener              //监听ListView滚动状态;
OnItemClickListener           //监听ListView Item点击事件。
mListView.setOnFocusChangeListener(this);
mListView.setOnTouchListener(this); 
mListView.setOnItemClickListener(this);
mListView.setOnScrollListener(this);

(1). OnFocusChangeListener:

@Override
public void onFocusChange(View view, boolean hasFocus) 
    if (view == mListView && hasFocus) 
        hideSoftKeyboard();
    

(2). OnTouchListener:

@Override
public boolean onTouch(View view, MotionEvent event) 
    if (view == mListView) 
        hideSoftKeyboard();
    
    return false;

从源码中可以看出,当焦点或者触摸事件到ListView中时,会做隐藏软键盘的操作。
(3). OnItemClickListener:

protected abstract void onItemClick(int position, long id);
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
    hideSoftKeyboard();

    int adjPosition = position - mListView.getHeaderViewsCount();
    if (adjPosition >= 0) 
        onItemClick(adjPosition, id);
    

当点击ListView item时触发该方法,从而调用抽象方法onItemClick(position, id);子类中不需要再去监听OnItemClickListener,只需要重写该方法即可,
(4). OnScrollListener:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
    int totalItemCount) 

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) 
    if (scrollState == OnScrollListener.SCROLL_STATE_FLING) 
        mPhotoManager.pause();
     else if (isPhotoLoaderEnabled()) 
        mPhotoManager.resume();
    

源码OnScrollListener中定义了3个常量:

public static int SCROLL_STATE_IDLE = 0;         //停止滚动
public static int SCROLL_STATE_TOUCH_SCROLL = 1; //正在滚动
public static int SCROLL_STATE_FLING = 2;        //手指做了抛的动作(手指离开屏幕前,用力滑了一下)

这里当ListView 滚动时,触发该事件,当用户手指做了抛的动作时,联系人头像会暂停加载(防止画面出现卡顿现象);否则当照片加载器可用时,会恢复加载联系人头像。

以及定义了些公用方法:

protected abstract View inflateView(LayoutInflater inflater, ViewGroup container);
protected abstract T createListAdapter();
protected abstract void onItemClick(int position, long id);
public CursorLoader createCursorLoader(Context context);
……

使代码更可控,风格更统一,大大缩减了重复代码。
其中:
DefaultContactBrowseListFragment:为联系人应用展现给用户的第一个页面;

以下是androidManifest.xml以及ContactSelectionActivity中部分源码:

<activity android:name=".activities.ContactSelectionActivity">
    <intent-filter>
        <action android:name="android.intent.action.INSERT_OR_EDIT" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="vnd.android.cursor.item/person" />
        <data android:mimeType="vnd.android.cursor.item/contact" />
        <data android:mimeType="vnd.android.cursor.item/raw_contact" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.PICK" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="vnd.android.cursor.dir/contact" />
        <data android:mimeType="vnd.android.cursor.dir/person" />
        <data android:mimeType="vnd.android.cursor.dir/phone_v2" />
        <data android:mimeType="vnd.android.cursor.dir/phone" />
        <data android:mimeType="vnd.android.cursor.dir/postal-address_v2" />
        <data android:mimeType="vnd.android.cursor.dir/postal-address" />
        <data android:mimeType="vnd.android.cursor.dir/email_v2" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.GET_CONTENT" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="vnd.android.cursor.item/contact" />
        <data android:mimeType="vnd.android.cursor.item/person" />
        <data android:mimeType="vnd.android.cursor.item/phone_v2" />
        <data android:mimeType="vnd.android.cursor.item/phone" />
        <data android:mimeType="vnd.android.cursor.item/postal-address_v2" />
        <data android:mimeType="vnd.android.cursor.item/postal-address" />
    </intent-filter>

    <intent-filter>
        <action android:name="com.android.contacts.action.JOIN_CONTACT" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
public void configureListFragment() 
    switch (mActionCode) 
        case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: 
            ContactPickerFragment fragment = new ContactPickerFragment();
            fragment.setEditMode(true);
            fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
            fragment.setCreateContactEnabled(!mRequest.isSearchMode());
            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_DEFAULT:
        case ContactsRequest.ACTION_PICK_CONTACT: 
            ContactPickerFragment fragment = new ContactPickerFragment();
            fragment.setIncludeProfile(mRequest.shouldIncludeProfile());
            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: 
            ContactPickerFragment fragment = new ContactPickerFragment();
            fragment.setCreateContactEnabled(!mRequest.isSearchMode());
            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: 
            ContactPickerFragment fragment = new ContactPickerFragment();
            fragment.setShortcutRequested(true);
            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_PICK_PHONE: 
            PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_PICK_EMAIL: 
            mListFragment = new EmailAddressPickerFragment();
            break;
        

        case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: 
            PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
            fragment.setShortcutAction(Intent.ACTION_CALL);

            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: 
            PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
            fragment.setShortcutAction(Intent.ACTION_SENDTO);

            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_PICK_POSTAL: 
            PostalAddressPickerFragment fragment = new PostalAddressPickerFragment();

            mListFragment = fragment;
            break;
        

        case ContactsRequest.ACTION_PICK_JOIN: 
            JoinContactListFragment joinFragment = new JoinContactListFragment();
            joinFragment.setTargetContactId(getTargetContactId());
            mListFragment = joinFragment;
            break;
        

        default:
            throw new IllegalStateException("Invalid action code: " + mActionCode);
    

    // Setting compatibility is no longer needed for PhoneNumberPickerFragment since that logic
    // has been separated into LegacyPhoneNumberPickerFragment.  But we still need to set
    // compatibility for other fragments.
    mListFragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode());
    mListFragment.setDirectoryResultLimit(DEFAULT_DIRECTORY_RESULT_LIMIT);

    getFragmentManager().beginTransaction()
            .replace(R.id.list_container, mListFragment)
            .commitAllowingStateLoss();

从源码中可知:
其余的Fragment都属于联系人多选界面ContactSelectionActivity:
ContactPickerFragment,
JoinContactListFragment,
PostalAddressPickerFragment,
EmailAddressPickerFragment,
PhoneNumberPickerFragment,
LegacyPhoneNumberPickerFragment;
启动ContactSelectionActivity时,会根据不同的action打开对应的Fragment,进行相应的操作。

以上是关于Android 5.1 Contacts源码分析:Contacts模块Fargment结构的主要内容,如果未能解决你的问题,请参考以下文章

Android 5.1 Contacts源码分析:Contacts模块ListView Adapter结构

Android 5.1 Contacts源码分析:Contacts模块Fargment结构

Android 5.1 Contacts源码分析:PeopleActivity

Android 5.1系统源码Wifi模块中wifiSettings源码分析

Orchard源码分析(5.1):Host初始化(DefaultOrchardHost.Initialize方法)

Android 5.1 Settings源代码简要分析