Mms模組ConversationList流程分析(2)Mms模組ConversationList流程分析(1)

來源:互聯網
上載者:User

接上一篇:Mms模組ConversationList流程分析(1)


三 連絡人資料的查詢

  前面使用AsyncQueryHandler所擷取到的cursor僅僅是查詢了,所有對話資訊資料;但是其中的連絡人僅僅只是儲存了其ID:recipientIds;

  還需要根據此recipientIds擷取其連絡人的資訊;這個就是在封裝資訊資料給ListItem使用的時候擷取的;

Conversation conv = Conversation.from(context, cursor);擷取連絡人相關資訊;

下面看下這個過程:

        

         先從Conversation中的Cache中尋找是否當前cursor所對應的Thread資訊已存在於緩衝中,

若存在則將其更新並返回;否則新建立,並將其加入到緩衝Cache中;

         public static Conversation from(Context context, Cursor cursor) {

        long threadId = cursor.getLong(ID);

        if (threadId > 0) {

                            //Conversation緩衝中尋找cursor所對應的Thread資訊

            Conversation conv = Cache.get(threadId);

            if (conv != null) {

 

                                     //已存在緩衝中 update the existing conv in-place

                fillFromCursor(context, conv, cursor, false);                  

return conv;

            }

        }

                   //不存在於緩衝中,新建立

        Conversation conv = new Conversation(context, cursor, false);           

Cache.put(conv);

        return conv;

    }

        

         實際上不管是更新還是建立 都會走函數fillFromCursor();

那麼下面看看這個函數都幹了些什麼事情;

private static void fillFromCursor(Context context, Conversation conv,

                              Cursor c, boolean allowQuery) {

synchronized (conv) {

         //填寫conv執行個體基本的對話資訊 ThreadIddatecountattachtype等;

}

 

//擷取cursor中連絡人Ids

String recipientIds = c.getString(RECIPIENT_IDS);

//通過recipientIds 擷取對應的連絡人資料:addressname……

ContactList recipients = ContactList.getByIds(recipientIds, allowQuery);

 

synchronized (conv) {

         //關聯連絡人資料

         conv.mRecipients = recipients;

         //計算未讀資訊條數

}

}

         (注意這裡的synchronized的用法,這個是線程相關,這裡不詳細分析)

——》ContactList.getByIds

這裡就轉到ContactList類裡面操作去了()這裡還是mms的data包下裡面的類;

 

1 ContactList

       到此查詢過程如下:

下面幾個部分就圍繞這個流程圖進行詳細介紹;

         ContactList

         此類從ArrayList繼承下來:public class ContactList extends ArrayList<Contact>{}

public static ContactList getByIds(String spaceSepIds, boolean canBlock) {

  ContactList list = new ContactList();

  //foreach語句

  for (RecipientIdCache.Entry entry : RecipientIdCache

  .getAddresses(spaceSepIds)) {        //根據Id擷取號碼 訪問資料庫

  if (entry != null && !TextUtils.isEmpty(entry.number)) {

         //根據號碼擷取連絡人資料

  Contact contact = Contact.get(entry.number, canBlock);

  contact.setRecipientId(entry.id);

  list.add(contact);

  }

  }

  //返回連絡人清單 Conversation

  return list;

}

 

通過這裡Contact contact = Contact.get(entry.number, canBlock); 傳入號碼

——》轉到Contact裡面執行;

下面看看這個類的get方法

 

2 Contact 非同步或者阻塞方式擷取連絡人資料

       number連絡人的號碼

         canBlock將決定是以阻塞的方式還是非同步方式擷取連絡人資料

public static Contact get(String number, boolean canBlock) {

         //調用的是ContactsCache類執行個體的get方法

    return sContactCache.get(number, canBlock);

}

 

下面看一下ContactsCache裡面的get方法

ContactsCacheContact類的內部類;  

public Contact get(String number, boolean canBlock) {

                   //返回一個contact不管資料庫中是否存在 先從內部緩衝中尋找匹配號碼的

                   //若不存在則直接將其返回,若不存在則返回新建立一個

  Contact contact = get(number);      //內部尋找

        Runnable r = null;

        synchronized (contact) {

  while (canBlock && contact.mQueryPending) {      //是否阻塞方式

  contact.wait();                   }

  final Contact c = contact;         //匿名內部類實現線程

  r = new Runnable() {

  public void run() {    

         //仍然要線上程中更新,填充連絡人資料 不管是否從緩衝中取得

  updateContact(c);  }       

  };       }

  if (canBlock) {

  r.run();      //阻塞方式

  } else {

  pushTask(r);     //非同步方式               }

  return contact;

}

 

通過此方法非同步或者阻塞方式擷取到的連絡人資料 通過此get方法得到的連絡人資料可能僅僅只是包含號碼,而沒有其他資料資訊;

 

下面看一下updateContact方法

private void updateContact(final Contact c) {

Contact entry = getContactInfo(c.mNumber);

 

         //從資料庫中擷取Contact資料

  Contact entry = getContactInfo(c.mNumber);

  //設定Contact執行個體c的資料資訊:name id……

 

  //notify to update who?

  //who? Here It is ConversationListItem

  UpdateListener l;//從Contact的UpdateListener隊列中擷取一個Listener對象

  //更新當前監聽者所使用的Contact資料

  l.onUpdate(c)

}

3 ContactupdateListener的添加

這裡存在一個updateListener對象就是 ConversationListItem執行個體:什麼時候傳進去的呢?

看到 bind方法被調用時 也就是 上面所講bindView時;

public final void bind(){

         ……

         Contact.addListener(this); //添加UpdateListener

}

 

4 連絡人處理方式

Contact處理連絡人資料有兩種方式:非同步和阻塞;具體這裡不作詳細分析;

 

那麼這裡有個點讓我不明白!

1)   載入一個Thread ListItem對應的連絡人資料 可能有多個 是在一個ContactList  getByIds方法中for迴圈執行;

2)   非同步方式單獨處理每一個號碼對應的連絡人資料

3)   將pushTask(r);加入到TaskStack中之後,放棄對CPU的控制權;

4)   TaskStack中線程mWorkerThread;非同步執行存在很多的不確定性,怎麼控制;

5)   一次非同步方式執行updateContact會去通知ItemList更新資料,為什麼不是選擇一個Thread資訊所有的號碼處理完畢 之後再去更新ItemList;

是這麼個道理: 加入TaskStack中時;執行:

public void push(Runnable r) {

                synchronized (mThingsToLoad) {

                    mThingsToLoad.add(r);

                    mThingsToLoad.notify();  //放棄資源控制

                }

            } 這裡就等待getByIds將所有的號碼處理加入到TaskStack中來處理;

                   但是仍然是每一次線程run方法都會去更新;也就是更新一個連絡人就要更新UI一次。這樣豈不浪費時間和資源;

這個mWorkerThread線程是在啟動MmsApp時候就啟動了

MmsApp.java中

@Override

public void onCreate(){

                   ……

  //建立ContactsCache對象,ContactsCache建立TaskStack對象

  //TaskStack是ContactsCache內部類 其建構函式啟動線程

  Contact.init(this);

}

 

這個Mms這個連絡人管理是比較的複雜!這裡所認識的可能並一定正確;待後續完善。

 

 

五 資料更新到介面更新

回到ConversationListAdapter的函數bindView函數中來

@Override

    public void bindView(View view, Context context, Cursor cursor) {

        ConversationListItem headerView = (ConversationListItem) view;

        Conversation conv = Conversation.from(context, cursor);

        ConversationListItemData ch = new ConversationListItemData(context, conv);

        headerView.bind(context, ch);

    }

 

       需要看一下headerView.bind所執行的bind函數:

//更新ListViewItem中控制項的相關內容

void bind(Context context, final ConversationListItemData ch) {

                   ……

        // Date

        mDateView.setText(ch.getDate());

        // From.

        mFromView.setText(formatMessage(ch));

        // Register for updates in changes of any of the contacts in this conversation.

        ContactList contacts = ch.getContacts();

        Contact.addListener(this);                // onUpdate函數

        // Subject

        mSubjectView.setText(ch.getSubject());

                  //avatar

        updateAvatarView();

}

 

整個ConversationList介面到資料載入的主要過程便是這樣。

 

這裡僅僅只是一個架構性的對各個模組進行分析和介紹;

具體各個模組還需要進一步的詳細分析。

其中可能存在有些地方並不正確,歡迎指正;

或將待後續深入瞭解之後進行更正更新。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.