Android獲取手機聯(lián)系人匹配用戶表并按字母A-Z排序展示

1、前言

最近在做公司項目的時候遇到一個添加手機聯(lián)系人的需求累贤,主要有以下幾個功能點:

  • 讀取聯(lián)系人:讀取用戶手機上的通訊錄里的聯(lián)系人列表
  • 好友排序:按照拼音順序對好友進行排序,兼容英文數(shù)字符號等
  • 字母索引:右側字母導航條少漆,既可拖動也可點擊臼膏,聯(lián)動ListView滑動
  • 匹配:最后要將通訊錄里的聯(lián)系人列表與后臺數(shù)據庫里的用戶表進行匹配

最終的大致效果如下:

手機聯(lián)系人列表

特意寫篇博客將整個實現(xiàn)過程記錄下來,方便以后再次遇到這樣的需求的時候可以直接使用CV大法示损,也希望能幫到剛好有這方面需求的朋友渗磅。

2、讀取聯(lián)系人

讀取手機通訊錄里的聯(lián)系人主要是通過ContentResolver 來獲取的屎媳,代碼比較固定夺溢,直接貼代碼:

先定義一個用來接收聯(lián)系人的數(shù)據bean,主要是對id烛谊,name和phone三個字段進行賦值风响,其他字段主要是為了排序和匹配用戶表用到的。

/**
 * @author hydCoder
 * @date 2017/10/11 10:50
 * @desc 手機聯(lián)系人的數(shù)據bean
 * @email hyd_coder@163.com
 */

public class ContactInfo implements Comparable<ContactInfo> {
    public String id;
    public String name;
    public String phone;
    public String pinyin; // 姓名對應的拼音
    public String firstLetter; // 拼音的首字母
    public String userAvatar;
    public String userName;
    public String userNick;
    public int    isFriend;
    public String userId;
    public int gradeLevel;
    public String userPosition;
    public String userCompany;
    public int userType;
    public boolean isUser = false;

    public ContactInfo(String id, String name, String phone) {
        this.id = id;
        this.name = name;
        this.phone = phone;
        pinyin = Cn2Spell.getPinYin(name); // 根據姓名獲取拼音
        firstLetter = pinyin.substring(0, 1).toUpperCase(); // 獲取拼音首字母并轉成大寫
        if (!firstLetter.matches("[A-Z]")) { // 如果不在A-Z中則默認為“#”
            firstLetter = "#";
        }
    }

    @Override
    public int compareTo(@NonNull ContactInfo another) {
        if (firstLetter.equals("#") && !another.firstLetter.equals("#")) {
            return 1;
        } else if (!firstLetter.equals("#") && another.firstLetter.equals("#")){
            return -1;
        } else {
            return pinyin.compareToIgnoreCase(another.pinyin);
        }
    }
}

獲取聯(lián)系人數(shù)據的工具類:

    /**
 * @author hydCoder
 * @date 2017/10/11 10:53
 * @desc 獲取手機聯(lián)系人數(shù)據
 * @email hyd_coder@163.com
 */

public class ContactUtils {
    /**
     * 獲取聯(lián)系人數(shù)據
     *
     * @param context
     * @return
     */
    public static List<ContactInfo> getAllContacts(Context context) {
        List<ContactInfo> list = new ArrayList<>();
        // 獲取解析者
        ContentResolver resolver = context.getContentResolver();
        // 訪問地址
        Uri raw_contacts = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri data = Uri.parse("content://com.android.contacts/data");
        // 查詢語句
        // select contact_id from raw_contacts;//1 2 3 4
        // select mimetype,data1 from view_data where raw_contact_id=3;
        // Cursor cursor=resolver.query(訪問地址, 返回字段 null代表全部, where 語句, 參數(shù), 排序)
        Cursor cursor = resolver.query(raw_contacts, new String[] { "contact_id" }, null, null, null);

        while (cursor.moveToNext()) {
            // getColumnIndex根據名稱查列號
            String id = cursor.getString(cursor.getColumnIndex("contact_id"));
            // 創(chuàng)建實例
            String name = "";
            String phone = "";
            Cursor item = resolver.query(data, new String[] { "mimetype", "data1" }, "raw_contact_id=?", new String[] { id }, null);

            while (item.moveToNext()) {
                String mimetype = item.getString(item.getColumnIndex("mimetype"));
                String data1 = item.getString(item.getColumnIndex("data1"));
                if ("vnd.android.cursor.item/name".equals(mimetype)) {
                    name = data1;
                } else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
                    // 有的手機號中間會帶有空格
                    phone = data1.replace(" ","");
                }
            }
            ContactInfo info = new ContactInfo(id,name,phone);
            item.close();
            // 添加集合
            list.add(info);
        }

        cursor.close();
        return list;
    }
}

3丹禀、好友排序和字母索引

3.1状勤、右側字母索引的導航條--SideBar

這個可以在網上找到很多類似的,你也可以找一個自己喜歡的甚至自己寫一個出來双泪,我在項目里用的是這個

https://github.com/AlexLiuSheng/AnimSideBar

我把他的SideBar.java拷貝到項目里持搜,修改了部分代碼:

    public class SideBar extends TextView {
    private String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z", "#"};
    private Paint textPaint;
    private Paint bigTextPaint;
    private Paint scaleTextPaint;

    private Canvas canvas;
    private int    itemH;
    private int    w;
    private int    h;
    /**
     * 普通情況下字體大小
     */
    float singleTextH;
    /**
     * 縮放離原始的寬度
     */
    private float scaleWidth;
    /**
     * 滑動的Y
     */
    private float eventY = 0;
    /**
     * 縮放的倍數(shù)
     */
    private int scaleSize = 1;
    /**
     * 縮放個數(shù)item,即開口大小
     */
    private int scaleItemCount = 6;
    private ISideBarSelectCallBack callBack;

    public SideBar(Context context) {
        this(context, null);
    }

    public SideBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SideBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SideBar);
            scaleSize = ta.getInteger(R.styleable.SideBar_scaleSize, 1);
            scaleItemCount = ta.getInteger(R.styleable.SideBar_scaleItemCount, 6);
            scaleWidth = ta.getDimensionPixelSize(R.styleable.SideBar_scaleWidth, dp(100));
            ta.recycle();
        }
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(getCurrentTextColor());
        textPaint.setTextSize(getTextSize());
        textPaint.setTextAlign(Paint.Align.CENTER);
        bigTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bigTextPaint.setColor(getCurrentTextColor());
        bigTextPaint.setTextSize(getTextSize() * (scaleSize + 3));
        bigTextPaint.setTextAlign(Paint.Align.CENTER);
        scaleTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        scaleTextPaint.setColor(getCurrentTextColor());
        scaleTextPaint.setTextSize(getTextSize() * (scaleSize + 1));
        scaleTextPaint.setTextAlign(Paint.Align.CENTER);
    }

    public void setDataResource(String[] data) {
        letters = data;
        invalidate();
    }

    public void setOnStrSelectCallBack(ISideBarSelectCallBack callBack) {
        this.callBack = callBack;
    }

    /**
     * 設置字體縮放比例
     *
     * @param scale
     */
    public void setScaleSize(int scale) {
        scaleSize = scale;
        invalidate();
    }

    /**
     * 設置縮放字體的個數(shù)焙矛,即開口大小
     *
     * @param scaleItemCount
     */
    public void setScaleItemCount(int scaleItemCount) {
        this.scaleItemCount = scaleItemCount;
        invalidate();
    }

    private int dp(int px) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (px * scale + 0.5f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
                    eventY = event.getY();
                    invalidate();
                    return true;
                } else {
                    eventY = 0;
                    invalidate();
                    break;
                }
            case MotionEvent.ACTION_CANCEL:
                eventY = 0;
                invalidate();
                return true;
            case MotionEvent.ACTION_UP:
                if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
                    eventY = 0;
                    invalidate();
                    return true;
                } else
                    break;
        }
        return super.onTouchEvent(event);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        this.canvas = canvas;
        DrawView(eventY);
    }

    private void DrawView(float y) {
        int currentSelectIndex = -1;
        if (y != 0) {
            for (int i = 0; i < letters.length; i++) {
                float currentItemY = itemH * i;
                float nextItemY = itemH * (i + 1);
                if (y >= currentItemY && y < nextItemY) {
                    currentSelectIndex = i;
                    if (callBack != null) {
                        callBack.onSelectStr(currentSelectIndex, letters[i]);
                    }
                    //畫大的字母
                    Paint.FontMetrics fontMetrics = bigTextPaint.getFontMetrics();
                    float bigTextSize = fontMetrics.descent - fontMetrics.ascent;
                    canvas.drawText(letters[i], w - getPaddingRight() - scaleWidth - bigTextSize, singleTextH + itemH * i, bigTextPaint);
                }
            }
        }
        drawLetters(y, currentSelectIndex);
    }

    private void drawLetters(float y, int index) {
        //第一次進來沒有縮放情況葫盼,默認畫原圖
        if (index == -1) {
            w = getMeasuredWidth();
            h = getMeasuredHeight();
            itemH = h / letters.length;
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            singleTextH = fontMetrics.descent - fontMetrics.ascent;
            for (int i = 0; i < letters.length; i++) {
                canvas.drawText(letters[i], w - getPaddingRight(), singleTextH + itemH * i, textPaint);
            }
            //觸摸的時候畫縮放圖
        } else {
            //遍歷所有字母
            for (int i = 0; i < letters.length; i++) {
                //要畫的字母的起始Y坐標
                float currentItemToDrawY = singleTextH + itemH * i;
                float centerItemToDrawY;
                if (index < i)
                    centerItemToDrawY = singleTextH + itemH * (index + scaleItemCount);
                else
                    centerItemToDrawY = singleTextH + itemH * (index - scaleItemCount);
                float delta = 1 - Math.abs((y - currentItemToDrawY) / (centerItemToDrawY - currentItemToDrawY));
                float maxRightX = w - getPaddingRight();
                //如果大于0,表明在y坐標上方
                scaleTextPaint.setTextSize(getTextSize() + getTextSize() * delta);
                float drawX = maxRightX - scaleWidth * delta;
                //超出邊界直接花在邊界上
                if (drawX > maxRightX)
                    canvas.drawText(letters[i], maxRightX, singleTextH + itemH * i, textPaint);
                else
                    canvas.drawText(letters[i], drawX, singleTextH + itemH * i, scaleTextPaint);
            }
        }
    }

    public interface ISideBarSelectCallBack {
        void onSelectStr(int index, String selectStr);
    }

}

其中3個自定義的屬性如下:

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <declare-styleable name="SideBar">  
        <attr name="scaleSize" format="integer"/>  
        <attr name="scaleItemCount" format="integer"/>  
        <attr name="scaleWidth" format="dimension"/>  
    </declare-styleable>  
</resources>  

3.2村斟、漢字轉拼音工具類

比較尷尬的是贫导,java中是沒有提供接口和方法讓我們直接將漢字轉成拼音的。所以我們只能自己想辦法了蟆盹,一般有以下兩種辦法:

**1孩灯、 使用第三方pinyin4j的jar包 ** 下載地址
Android Studio也可直接依賴

compile 'com.belerweb:pinyin4j:2.5.0'

優(yōu)點:使用簡單,實用性好
缺點:需要依賴第三方jar包

2逾滥、 使用ASCII碼和拼音的映射

優(yōu)點:零依賴峰档,只有一個Class,使用簡單
缺點:只支持常見的一級漢字,對于一些不常見的漢字(亳bo)則無法正確獲取拼音
(中文編碼中一級漢字是按拼音排序的讥巡,容易映射掀亩。而二級漢字是按筆畫部首排序的)

其實,無論是使用哪種方法尚卫,我發(fā)現(xiàn)都是沒有去處理多音字的情況(畢竟這個真不好寫)归榕,不過基本需求都可以滿足啦。

我在這里直接使用的就是pinyin4j的jar包吱涉。但我還是基于pinyin4j寫了個轉換的工具類:

    /** 
 * 漢字轉換位漢語拼音刹泄,英文字符不變 
 */  
public class Cn2Spell {  
  
    public static StringBuffer sb = new StringBuffer();  
  
    /** 
     * 獲取漢字字符串的首字母,英文字符不變 
     * 例如:阿飛→af 
     */  
    public static String getPinYinHeadChar(String chines) {  
        sb.setLength(0);  
        char[] chars = chines.toCharArray();  
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
        for (int i = 0; i < chars.length; i++) {  
            if (chars[i] > 128) {  
                try {  
                    sb.append(PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat)[0].charAt(0));  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            } else {  
                sb.append(chars[i]);  
            }  
        }  
        return sb.toString();  
    }  
  
    /** 
     * 獲取漢字字符串的第一個字母 
     */  
    public static String getPinYinFirstLetter(String str) {  
        sb.setLength(0);  
        char c = str.charAt(0);  
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);  
        if (pinyinArray != null) {  
            sb.append(pinyinArray[0].charAt(0));  
        } else {  
            sb.append(c);  
        }  
        return sb.toString();  
    }  
  
    /** 
     * 獲取漢字字符串的漢語拼音怎爵,英文字符不變 
     */  
    public static String getPinYin(String chines) {  
        sb.setLength(0);  
        char[] nameChar = chines.toCharArray();  
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
        for (int i = 0; i < nameChar.length; i++) {  
            if (nameChar[i] > 128) {  
                try {  
                    sb.append(PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0]);  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            } else {  
                sb.append(nameChar[i]);  
            }  
        }  
        return sb.toString();  
    }  
  
}  

3.3特石、讓聯(lián)系人可以根據拼音來排序

代碼在上面已經貼過了,這里就不重復貼了鳖链,其實就是讓JavaBean實現(xiàn)comparable接口姆蘸,并重寫comparaTo方法。再在comparaTo方法里根據首字母判斷芙委,首字母為“#”都放在最后逞敷,都為“#”或者都是字母時才根據拼音來比較排序。

4灌侣、與后臺數(shù)據庫進行匹配

我與我們后臺的開發(fā)大佬商量好的是將獲取到的聯(lián)系人集合里的手機號用","連接起來傳給他推捐,他再將匹配到的聯(lián)系人數(shù)據返回給我,我再進行數(shù)據整合并處理交互邏輯侧啼。代碼比較簡單牛柒,這里就不貼了。

5痊乾、組裝

由于沒有把這個單獨抽出來皮壁,所以只能貼部分關鍵代碼。哪审。蛾魄。。湿滓。畏腕。

Activity的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/gray_e5e5e5">

    <com.sdalolo.genius.utils.CustomNavigatorBar
        android:id="@+id/cn_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/title_bar_size"
        android:paddingRight="10dp"
        android:layout_alignParentTop="true"
        app:leftImage="@drawable/backtrack"
        app:leftImageVisiable="true"
        app:leftTextVisibale="false"
        app:midText="添加手機聯(lián)系人"
        app:midTextFontSize="@dimen/title_size"
        app:midTextFontColor="@color/auxiliary_color"
        app:rightTextVisible="false"
        app:rightImageVisible="false"
        app:titleBarBackground="@color/main_color">
    </com.sdalolo.genius.utils.CustomNavigatorBar>

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/cn_bar"
        android:divider="@color/divide_color"
        android:scrollbars="none"
        android:dividerHeight="1dp">
    </ListView>

    <com.sdalolo.genius.ui.view.SideBar
        android:id="@+id/side_bar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/cn_bar"
        android:layout_alignParentRight="true"
        android:paddingRight="10dp"
        android:textColor="@color/auxiliary_color"
        android:textSize="14sp" />

</RelativeLayout>

activity中的部分代碼:

mSideBar.setOnStrSelectCallBack(new SideBar.ISideBarSelectCallBack() {
        @Override
        public void onSelectStr(int index, String selectStr) {
            if (mAllContacts != null) {
                for (int i = 0; i < mAllContacts.size(); i++) {
                    if (selectStr.equalsIgnoreCase(mAllContacts.get(i).firstLetter)) {
                        mListView.setSelection(i); // 選擇到首字母出現(xiàn)的位置
                        return;
                    }
                }
            }
        }
    });

adapter中的部分代碼:

/**
 * 獲取首字母首次出現(xiàn)位置
 */
public int getPositionForSection(String catalog) {
    for (int i = 0; i < getCount(); i++) {
        String sortStr = list.get(i).firstLetter;
        if (catalog.equalsIgnoreCase(sortStr)) {
            return i;
        }
    }
    return -1;
}

//如果當前位置等于該分類首字母的Char的位置 ,則認為是第一次出現(xiàn)
    if(position == getPositionForSection(catalog)){
        viewHolder.catalog.setVisibility(View.VISIBLE);
        viewHolder.catalog.setText(contact.firstLetter.toUpperCase());
    }else{
        viewHolder.catalog.setVisibility(View.GONE);
    }

6茉稠、結語

到這里基本上效果就實現(xiàn)了,是不是很簡單把夸,不過如果編譯版本大于23的話而线,記得動態(tài)申請Manifest.permission.READ_CONTACTS權限,不然會Crash,別問我怎么知道的膀篮。嘹狞。。誓竿。磅网。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末筷屡,一起剝皮案震驚了整個濱河市涧偷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毙死,老刑警劉巖燎潮,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扼倘,居然都是意外死亡确封,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門再菊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爪喘,“玉大人,你說我怎么就攤上這事纠拔”#” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵绿语,是天一觀的道長秃症。 經常有香客問我,道長吕粹,這世上最難降的妖魔是什么种柑? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮匹耕,結果婚禮上聚请,老公的妹妹穿的比我還像新娘。我一直安慰自己稳其,他們只是感情好驶赏,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著既鞠,像睡著了一般煤傍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘱蛋,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天蚯姆,我揣著相機與錄音五续,去河邊找鬼。 笑死龄恋,一個胖子當著我的面吹牛疙驾,可吹牛的內容都是我干的。 我是一名探鬼主播郭毕,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼它碎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了显押?” 一聲冷哼從身側響起扳肛,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎煮落,沒想到半個月后敞峭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蝉仇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年旋讹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轿衔。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡沉迹,死狀恐怖,靈堂內的尸體忽然破棺而出害驹,到底是詐尸還是另有隱情鞭呕,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布宛官,位于F島的核電站葫松,受9級特大地震影響,放射性物質發(fā)生泄漏底洗。R本人自食惡果不足惜腋么,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望亥揖。 院中可真熱鬧珊擂,春花似錦、人聲如沸费变。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挚歧。三九已至扛稽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滑负,已是汗流浹背庇绽。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工锡搜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞧掺。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像凡傅,于是被迫代替她去往敵國和親辟狈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評論 25 707
  • 記得在我剛開始接觸到美團網的時候就對美團網這個城市定位夏跷、選擇城市功能很感興趣哼转,覺得它做得很棒。有如下幾個點:一:實...
    Angelicas閱讀 9,593評論 1 33
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理槽华,服務發(fā)現(xiàn)壹蔓,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 《父親》 文/白傳英 有時候覺得自己像小溪 碧波蕩漾一年四季 當我干涸的時候 父親就像那黃河 有時候覺得自己...
    白清風閱讀 141評論 0 0
  • 下了一天的雨 抽了個空猫态,和同行的姐姐去了咖啡館佣蓉, 可是想去的那家啊沒有營業(yè),后發(fā)現(xiàn)了大魚很安靜的大魚亲雪,美的低調又張...
    喬未9574閱讀 148評論 0 0