日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > 說說PendingIntent的內(nèi)部機(jī)制

說說PendingIntent的內(nèi)部機(jī)制

來源:程序員人生   發(fā)布時間:2015-01-06 08:52:25 閱讀次數(shù):6480次

說說PendingIntent的內(nèi)部機(jī)制

 

侯 亮

 

1 概述

        在Android中,我們常常使用PendingIntent來表達(dá)1種“留待往后處理”的意思。從這個角度來講,PendingIntent可以被理解為1種特殊的異步處理機(jī)制。不過,單就命名而言,PendingIntent其實(shí)具有1定誤導(dǎo)性,由于它既不繼承于Intent,也不包括Intent,它的核心可以粗略地匯總成4個字――“異步激起”。

        很明顯,這類異步激起常常是要跨進(jìn)程履行的。比如說A進(jìn)程作為發(fā)起端,它可以從系統(tǒng)“獲得”1個PendingIntent,然后A進(jìn)程可以將PendingIntent對象通過binder機(jī)制“傳遞”給B進(jìn)程,再由B進(jìn)程在未來某個適合時機(jī),“回調(diào)”PendingIntent對象的send()動作,完成激起。

        在Android系統(tǒng)中,最合適做集中性管理的組件就是AMS(Activity Manager Service)啦,所以它當(dāng)仁不讓地承當(dāng)起管理所有PendingIntent的職責(zé)。這樣我們就能夠畫出以下示意圖:


        注意其中的第4步“遞送相應(yīng)的intent”。這1步遞送的intent是從何而來的呢?簡單地說,當(dāng)發(fā)起端獲得PendingIntent時,實(shí)際上是需要同時提供若干intent的。這些intent和PendingIntent只是配套的關(guān)系,而不是聚合的關(guān)系,它們會被緩存在AMS中。往后,1旦處理端將PendingIntent的“激起”語義傳遞到AMS,AMS就會嘗試找到與這個PendingIntent對應(yīng)的若干intent,并遞送出去。

        固然,以上說的只是大概情況,實(shí)際的技術(shù)細(xì)節(jié)會更復(fù)雜1點(diǎn)兒。下面我們就來談?wù)劶?xì)節(jié)。

 

2 PendingIntent的技術(shù)細(xì)節(jié)

2.1 發(fā)起端獲得PendingIntent

        我們先要理解,所謂的“發(fā)起端獲得PendingIntent”到底指的是甚么。難道只是簡單new1個PendingIntent對象嗎?固然不是。此處的“獲得”動作其實(shí)還含有向AMS“注冊”intent的語義。

        在PendingIntent.java文件中,我們可以看到有以下幾個比較常見的靜態(tài)函數(shù):

  • public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)
  • public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
  • public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags)
  • public static PendingIntent getActivities(Context context, int requestCode, Intent[] intents, int flags)
  • public static PendingIntent getActivities(Context context, int requestCode, Intent[] intents, int flags, Bundle options)

它們就是我們經(jīng)常使用的獲得PendingIntent的動作了。

        坦白說,這幾個函數(shù)的命名可真不怎樣樣,所以我們簡單解釋1下。上面的getActivity()的意思實(shí)際上是,獲得1個PendingIntent對象,而且該對象往后激起時所做的事情是啟動1個新activity。也就是說,當(dāng)它異步激起時,會履行類似Context.startActivity()那樣的動作。相應(yīng)地,getBroadcast()和getService()所獲得的PendingIntent對象在激起時,會分別履行類似Context..sendBroadcast()和Context.startService()這樣的動作。至于最后兩個getActivities(),用得比較少,激起時可以啟動幾個activity。

        我們以getActivity()的代碼來講明問題:

public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; try { intent.setAllowFds(false); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, flags, options); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) {} return null; }

其中那句new PendingIntent(target)創(chuàng)建了PendingIntent對象,其重要性自不待言。但是,這個對象的內(nèi)部核心實(shí)際上是由上面那個getIntentSender()函數(shù)得來的。而這個IIntentSender核心才是我們真正需要關(guān)心的東西。

        說穿了,此處的IIntentSender對象是個binder代理,它對應(yīng)的binder實(shí)體是AMS中的PendingIntentRecord對象。PendingIntent對象構(gòu)造之時,IIntentSender代理作為參數(shù)傳進(jìn)來,并記錄在PendingIntent的mTarget域。往后,當(dāng)PendingIntent履行異步激起時,其內(nèi)部就是靠這個mTarget域向AMS傳遞語義的。

        我們前文說過,PendingIntent常常會經(jīng)過binder機(jī)制,傳遞到另外一個進(jìn)程去。而binder機(jī)制可以保證,目標(biāo)進(jìn)程得到的PendingIntent的mTarget域也是合法的IIntentSender代理,而且和發(fā)起真?zhèn)€IIntentSender代理對應(yīng)著同1個PendingIntentRecord實(shí)體。示意圖以下:


 

2.2 AMS里的PendingIntentRecord

        那末PendingIntentRecord里又有甚么信息呢?它的定義截選以下:

class PendingIntentRecord extends IIntentSender.Stub { final ActivityManagerService owner; final Key key; // 最關(guān)鍵的key域 final int uid; final WeakReference<PendingIntentRecord> ref; boolean sent = false; boolean canceled = false; String stringName; . . . . . . }

請注意其中那個key域。這里的Key是個PendingIntentRecord的內(nèi)嵌類,其定義截選以下:

final static class Key { final int type; final String packageName; final ActivityRecord activity; final String who; final int requestCode; final Intent requestIntent; // 注意! final String requestResolvedType; final Bundle options; Intent[] allIntents; // 注意!記錄了當(dāng)初獲得PendingIntent時,用戶所指定的所有intent String[] allResolvedTypes; final int flags; final int hashCode; . . . . . . . . . . . . }

請注意其中的allIntents[]數(shù)組域和requestIntent域。前者記錄了當(dāng)初獲得PendingIntent時,用戶所指定的所有intent(雖然1般情況下只會指定1個intent,但類似getActivities()這樣的函數(shù)還是可以指定多個intent的),而后者可以粗淺地理解為用戶所指定的那個intent數(shù)組中的最后1個intent。現(xiàn)在大家應(yīng)當(dāng)清楚異步激起時用到的intent都存在哪里了吧。

        Key的構(gòu)造函數(shù)截選以下:

Key(int _t, String _p, ActivityRecord _a, String _w, int _r, Intent[] _i, String[] _it, int _f, Bundle _o) { type = _t; packageName = _p; activity = _a; who = _w; requestCode = _r; requestIntent = _i != null ? _i[_i.length⑴] : null; // intent數(shù)組中的最后1個 requestResolvedType = _it != null ? _it[_it.length⑴] : null; allIntents = _i; // 所有intent allResolvedTypes = _it; flags = _f; options = _o; . . . . . . }

Key不光承當(dāng)著記錄信息的作用,它還承當(dāng)“鍵值”的作用。

 

2.3 AMS中的PendingIntentRecord總表

        在AMS中,管理著系統(tǒng)中所有的PendingIntentRecord節(jié)點(diǎn),所以需要把這些節(jié)點(diǎn)組織成1張表:

final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords

這張哈希映照表的鍵值類型就是剛才所說的PendingIntentRecord.Key。

        以后每當(dāng)我們要獲得PendingIntent對象時,PendingIntent里的mTarget是這樣得到的:AMS會先查mIntentSenderRecords表,如果能找到符合的PendingIntentRecord節(jié)點(diǎn),則返回之。如果找不到,就創(chuàng)建1個新的PendingIntentRecord節(jié)點(diǎn)。由于PendingIntentRecord是個binder實(shí)體,所以經(jīng)過binder機(jī)制傳遞后,客戶進(jìn)程拿到的就是個合法的binder代理。如此1來,前文的示意圖可以進(jìn)1步修改成下圖:


2.4 AMS里的getIntentSender()函數(shù)

        現(xiàn)在,我們回過頭繼續(xù)說前文的getActivity(),和其調(diào)用的getIntentSender()。我們先列1遍getActivity()的原型:

public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)
  • context參數(shù)是調(diào)用方的上下文。
  • requestCode是個簡單的整數(shù),起辨別作用。
  • intent是異步激起時將發(fā)出的intent。
  • flags可以包括1些既有的標(biāo)識,比如FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT、FLAG_UPDATE_CURRENT等等。很多同學(xué)對這個域不是很清楚,我們后文會細(xì)說。
  • options可以攜帶1些額外的數(shù)據(jù)。

        getActivity()的代碼很簡單,其參數(shù)基本上都傳給了getIntentSender()。

IIntentSender target = ActivityManagerNative.getDefault().getIntentSender(. . . . . .)

getIntentSender()的原型大體是這樣的:

public IIntentSender getIntentSender(int type, String packageName, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle options) throws RemoteException;

其參數(shù)比getActivity()要多1些,我們逐一說明。

        type參數(shù)表明PendingIntent的類型。getActivity()和getActivities()動作里指定的類型值是INTENT_SENDER_ACTIVITY,getBroadcast()和getService()和動作里指定的類型值分別是INTENT_SENDER_BROADCAST和INTENT_SENDER_SERVICE。另外,在Activity.java文件中,我們還看到1個createPendingResult()函數(shù),這個函數(shù)表達(dá)了發(fā)起方的activity往后希望得到result回饋的意思,所以其內(nèi)部調(diào)用getIntentSender()時指定的類型值為INTENT_SENDER_ACTIVITY_RESULT。

        packageName參數(shù)表示發(fā)起端所屬的包名。

        token參數(shù)是個指代回饋目標(biāo)方的代理。這是甚么意思呢?我們經(jīng)常使用的getActivity()、getBroadcast()和getService()中,只是把這個參數(shù)簡單地指定為null,表示這個PendingIntent激起時,是不需要發(fā)回甚么回饋的。不過當(dāng)我們希望獲得類型為INTENT_SENDER_ACTIVITY_RESULT的PendingIntent時,就需要指定token參數(shù)了。具體可參考createPendingResult()的代碼:

public PendingIntent createPendingResult(int requestCode, Intent data, int flags) { String packageName = getPackageName(); try { data.setAllowFds(false); IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, mParent == null ? mToken : mParent.mToken, mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { // Empty } return null; }

看到了嗎?傳入的token為Activity的mToken或其mParent.mToken。說得簡單點(diǎn)兒,AMS內(nèi)部可以根據(jù)這個token找到其對應(yīng)的ActivityRecord,往后當(dāng)PendingIntent激起時,AMS可以根據(jù)這個ActivityRecord肯定出該向哪一個目標(biāo)進(jìn)程的哪一個Activity發(fā)出result語義。

        resultWho參數(shù)和token參數(shù)息息相干,1般也是null啦。在createPendingResult()中,其值為Activity的mEmbeddedID字符串。

        requestCode參數(shù)是個簡單的整數(shù),可以在獲得PendingIntent時由用戶指定,它可以起辨別的作用。

        intents數(shù)組參數(shù)是異步激起時希望發(fā)出的intent。對getActivity()、getBroadcast()和getService()來講,都只會指定1個intent而已。只有g(shù)etActivities()會嘗試1次傳入若干intent。

        resolvedTypes參數(shù)基本上和intent是相干的。1般是這樣得到的:

String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null;

這個值常常和intent內(nèi)部的mData URI有關(guān)系,比如終究的值多是URI對應(yīng)的MIME類型。

        flags參數(shù)可以指定PendingIntent的1些行動特點(diǎn)。它的取值是1些既有的比特標(biāo)識的組合。目前可用的標(biāo)識有:FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT、FLAG_UPDATE_CURRENT等等。有時候,flags中還可以附帶若干FILL_IN_XXX標(biāo)識。我們把常見的標(biāo)識定義羅列以下:

【PendingIntent中】

public static final int FLAG_ONE_SHOT = 1<<30; public static final int FLAG_NO_CREATE = 1<<29; public static final int FLAG_CANCEL_CURRENT = 1<<28; public static final int FLAG_UPDATE_CURRENT = 1<<27;

【Intent中】

public static final int FILL_IN_ACTION = 1<<0; public static final int FILL_IN_DATA = 1<<1; public static final int FILL_IN_CATEGORIES = 1<<2; public static final int FILL_IN_COMPONENT = 1<<3; public static final int FILL_IN_PACKAGE = 1<<4; public static final int FILL_IN_SOURCE_BOUNDS = 1<<5; public static final int FILL_IN_SELECTOR = 1<<6; public static final int FILL_IN_CLIP_DATA = 1<<7;

這些以FILL_IN_打頭的標(biāo)志位,主要是在intent對象的fillIn()函數(shù)里起作用:

public int fillIn(Intent other, int flags)

我們以FILL_IN_ACTION為例來講明,當(dāng)我們履行類似srcIntent.fillIn(otherIntent, ...)的句子時,如果otherIntent的mAction域不是null值,那末fillIn()會在以下兩種情況下,用otherIntent的mAction域值為srcIntent的mAction域賦值:

1) 當(dāng)srcIntent的mAction域值為null時; 
2) 如果fillIn的flags參數(shù)里攜帶了FILL_IN_ACTION標(biāo)志位,那末即使srcIntent的mAction已有值了,此時也會用otherIntent的mAction域值強(qiáng)行替換掉srcIntent的mAction域值。

其他FILL_IN_標(biāo)志位和FILL_IN_ACTION的處理方式類似,我們不再贅述。

        options參數(shù)可以攜帶1些額外數(shù)據(jù)。

 

2.4.1 getIntentSender()函數(shù)

        getIntentSender()函數(shù)摘錄以下:

public IIntentSender getIntentSender(int type, String packageName, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle options) { . . . . . . // 先判斷intents數(shù)組,可以用偽代碼checkIntents(intents)來表示 // checkIntents(intents); . . . . . . int callingUid = Binder.getCallingUid(); . . . . . . if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { int uid = AppGlobals.getPackageManager().getPackageUid(packageName, UserId.getUserId(callingUid)); if (!UserId.isSameApp(callingUid, uid)) { . . . . . . throw new SecurityException(msg); } } . . . . . . return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(), token, resultWho, requestCode, intents, resolvedTypes, flags, options); . . . . . . }

getIntentSender()函數(shù)中有1段逐條判斷intents[]的代碼,我用偽代碼checkIntents(intents)來表示,這部份對應(yīng)的實(shí)際代碼以下:

for (int i=0; i<intents.length; i++) { Intent intent = intents[i]; if (intent != null) { if (intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (type == ActivityManager.INTENT_SENDER_BROADCAST && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) { throw new IllegalArgumentException("Can't use FLAG_RECEIVER_BOOT_UPGRADE here"); } intents[i] = new Intent(intent); } }

這段代碼說明在獲得PendingIntent對象時,intent中是不能攜帶文件描寫符的。而且如果這個PendingIntent是那種要發(fā)出廣播的PendingIntent,那末intent中也不能攜帶FLAG_RECEIVER_BOOT_UPGRADE標(biāo)識符。“BOOT_UPGRADE”應(yīng)當(dāng)是“啟動并升級”的意思,它不能使用PendingIntent。

        getIntentSender()中最核心的1句應(yīng)當(dāng)是調(diào)用getIntentSenderLocked()的那句。

 

2.4.2 getIntentSenderLocked()函數(shù)

        getIntentSenderLocked()的代碼截選以下:

【frameworks/base/services/java/com/android/server/am/ActivityManagerService.java】

IIntentSender getIntentSenderLocked(int type, String packageName, int callingUid, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle options) { . . . . . . // 如果是INTENT_SENDER_ACTIVITY_RESULT類型,那末要判斷token所 // 代表的activity是不是還在activity棧中 . . . . . . // 整理flags中的信息 . . . . . . PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, activity, resultWho, requestCode, intents, resolvedTypes, flags, options); // 盡力從哈希映照表中查找key對應(yīng)的PendingIntentRecord,如果找不到就創(chuàng)建1個新的節(jié)點(diǎn)。 WeakReference<PendingIntentRecord> ref; ref = mIntentSenderRecords.get(key); PendingIntentRecord rec = ref != null ? ref.get() : null; if (rec != null) { // 找到了匹配的PendingIntent,現(xiàn)在斟酌要不要更新它,或取消它。 if (!cancelCurrent) { if (updateCurrent) { // 如果明確指定了FLAG_UPDATE_CURRENT,那末更新找到的節(jié)點(diǎn) if (rec.key.requestIntent != null) { rec.key.requestIntent.replaceExtras(intents != null ? intents[intents.length - 1] : null); } if (intents != null) { intents[intents.length⑴] = rec.key.requestIntent; rec.key.allIntents = intents; rec.key.allResolvedTypes = resolvedTypes; } else { rec.key.allIntents = null; rec.key.allResolvedTypes = null; } } // 凡是能找到對應(yīng)的節(jié)點(diǎn),而且又不取消該節(jié)點(diǎn)的,那末就return這個節(jié)點(diǎn) return rec; } // 如果PendingIntent的標(biāo)志中帶有FLAG_CANCEL_CURRENT,則從哈希映照表中刪除之 rec.canceled = true; mIntentSenderRecords.remove(key); } if (noCreate) { // 如果明確表示了不創(chuàng)建新節(jié)點(diǎn),也就是說標(biāo)志中帶有FLAG_NO_CREATE, // 那末不論是不是Cancel了PendingIntent,此時1概直接返回。 return rec; } // 從哈希映照表中找不到,而且又沒有寫明FLAG_NO_CREATE,此時創(chuàng)建1個新節(jié)點(diǎn) rec = new PendingIntentRecord(this, key, callingUid); mIntentSenderRecords.put(key, rec.ref); if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) { // 如果intent需要返回結(jié)果,那末修改token對應(yīng)的ActivityRecord // 的pendingResults域。 if (activity.pendingResults == null) { activity.pendingResults = new HashSet<WeakReference<PendingIntentRecord>>(); } activity.pendingResults.add(rec.ref); } return rec; }

 

        上面這段代碼主要做的事情有:

1) 將傳進(jìn)來的多個參數(shù)信息整理成1個PendingIntentRecord.Key對象(key); 
2) 嘗試從mIntentSenderRecords總表中查找和key符合的PendingIntentRecord節(jié)點(diǎn); 
3) 根據(jù)flags參數(shù)所含有的意義,對得到的PendingIntentRecord進(jìn)行加工。有時候修改之,有時候刪除之。 
4) 如果在總表中沒有找到對應(yīng)的PendingIntentRecord節(jié)點(diǎn),或根據(jù)flags的語義刪除剛找到的節(jié)點(diǎn),那末此時的默許行動是創(chuàng)建1個新的PendingIntentRecord節(jié)點(diǎn),并插入總表。除非flags中明確指定了FLAG_NO_CREATE,此時不會創(chuàng)建新節(jié)點(diǎn)。

 

2.4.3 說說flags

        從getIntentSenderLocked()的代碼中,我們終究弄明白了flags中那些特定比特值的意義了。我們現(xiàn)在總結(jié)1下。

        應(yīng)當(dāng)說這些flags比特值基本上都是在圍繞著mIntentSenderRecords總表說事的。其中,F(xiàn)LAG_CANCEL_CURRENT的意思是,當(dāng)我們獲得PendingIntent時,如果可以從總表中查到1個符合的已存在的PendingIntentRecord節(jié)點(diǎn)的話,那末需要把這個節(jié)點(diǎn)從總表中清算出去。而在沒有指定FLAG_CANCEL_CURRENT的大條件下,如果用戶指定了FLAG_UPDATE_CURRENT標(biāo)識,那末會用新的intents參數(shù)替掉剛查到的PendingIntentRecord中的舊intents。

        而不論是剛清算了已存在的PendingIntentRecord,還是壓根兒就沒有找到符合的PendingIntentRecord,只要用戶沒有明確指定FLAG_NO_CREATE標(biāo)識,系統(tǒng)就會盡力創(chuàng)建1個新的PendingIntentRecord節(jié)點(diǎn),并插入總表。

        至于FLAG_ONE_SHOT標(biāo)識嘛,它并沒有在getIntentSenderLocked()中露臉兒。它的名字是“FLAG_ONE_SHOT”,也就是“只打1槍”的意思,那末很明顯,這個標(biāo)識起作用的地方應(yīng)當(dāng)是在“激起”函數(shù)里。在終究的激起函數(shù)(sendInner())里,我們可以看到下面的代碼:

【frameworks/base/services/java/com/android/server/am/PendingIntentRecord.java】

int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) { synchronized(owner) { if (!canceled) { sent = true; if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) { owner.cancelIntentSenderLocked(this, true); canceled = true; } . . . . . . . . . . . . } } return ActivityManager.START_CANCELED; }

意思很簡單,1進(jìn)行激起就把相應(yīng)的PendingIntentRecord節(jié)點(diǎn)從總表中清算出去,而且把PendingIntentRecord的canceled域設(shè)為true。這樣,以后即使外界再調(diào)用send()動作都沒用了,由于再也沒法進(jìn)入if (!canceled)判斷了。

 

2.4.4 將PendingIntentRecord節(jié)點(diǎn)插入總表

        接下來getIntentSenderLocked()函數(shù)new了1個PendingIntentRecord節(jié)點(diǎn),并將之插入mIntentSenderRecords總表中。

 

2.5 PendingIntent的激起動作

        下面我們來看PendingIntent的激起動作。在前文我們已說過,當(dāng)需要激起PendingIntent之時,主要是通過調(diào)用PendingIntent的send()函數(shù)來完成激起動作的。PendingIntent提供了多個情勢的send()函數(shù),但是這些函數(shù)的內(nèi)部其實(shí)調(diào)用的是同1個send(),其函數(shù)原型以下:

public void send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission) throws CanceledException

該函數(shù)內(nèi)部最關(guān)鍵的1句是:

int res = mTarget.send(code, intent, resolvedType, onFinished != null ? new FinishedDispatcher(this, onFinished, handler) : null, requiredPermission);

我們前文已介紹過這個mTarget域了,它對應(yīng)著AMS中的某個PendingIntentRecord。

        所以我們要看1下PendingIntentRecord1側(cè)的send()函數(shù),其代碼以下:

public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission) { return sendInner(code, intent, resolvedType, finishedReceiver, requiredPermission, null, null, 0, 0, 0, null); }

其中sendInner()才是真正做激起動作的函數(shù)。

         sendInner()完成的主要邏輯動作有:

1) 如果當(dāng)前PendingIntentRecord節(jié)點(diǎn)已處于canceled域?yàn)閠rue的狀態(tài),那末說明這個節(jié)點(diǎn)已被取消掉了,此時sendInner()不會做任何實(shí)質(zhì)上的激起動作,只是簡單地return ActivityManager.START_CANCELED而已。
2) 如果當(dāng)初在創(chuàng)建這個節(jié)點(diǎn)時,使用者已指定了FLAG_ONE_SHOT標(biāo)志位的話,那末此時sendInner()會把這個PendingIntentRecord節(jié)點(diǎn)從AMS中的總表中摘除,并且把canceled域設(shè)為true。而后的操作和普通激起時的動作是1致的,也就是說也會走下面的第3)步。 
3) 關(guān)于普通激起時應(yīng)履行的邏輯動作是,根據(jù)當(dāng)初創(chuàng)建PendingIntentRecord節(jié)點(diǎn)時,用戶指定的type類型,進(jìn)行不同的處理。這個type其實(shí)就是我們前文所說的INTENT_SENDER_ACTIVITY、INTENT_SENDER_BROADCAST、INTENT_SENDER_SERVICE等類型啦,大家如有興趣,可自己參考本文1開始所說的getActivity()、getBroadcast()、getService()等函數(shù)的實(shí)現(xiàn)代碼。

       現(xiàn)在還有1個問題是,既然我們在當(dāng)初獲得PendingIntent時,已指定了往后激起時需要遞送的intent(或intent數(shù)組),那末為何send()動作里還有1個intent參數(shù)呢?它們的關(guān)系又是甚么呢?我料想,PendingIntent機(jī)制的設(shè)計者是希望給激起端1個修改“待激起的intent”的機(jī)會。比如當(dāng)初我們獲得PendingIntent對象時,如果在flags里設(shè)置了FILL_IN_ACTION標(biāo)志位,那末就說明我們允許往后在某個激起點(diǎn),用新的intent的mAction域值,替換掉我們最初給的intent的mAction域值。如果1開始沒有設(shè)置FILL_IN_ACTION標(biāo)志位,而且在最初的intent里已有了非空的mAction域值的話,那末即便在激起端又傳入了新intent,它也不可能修改用新intent的mAction域值替換舊intent的mAction域值。

        仔細(xì)的讀者1定記得,當(dāng)初獲得PendingIntent對象時,我們可是向AMS端傳遞了1個intent數(shù)組噢,雖然1般情況下這個數(shù)組里只有1個intent元素,但有時候我們也是有可能1次性傳遞多個intent的。比如getActivities()函數(shù)就能夠1次傳遞多個intent。可是現(xiàn)在激起動作send()卻只能傳遞1個intent參數(shù),這該如何處理呢?答案很簡單,所傳入的intent只能影響已有的intent數(shù)組的最后1個intent元素。大家可以看看sendInner里allIntents[allIntents.length⑴] = finalIntent;1句。

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈
程序員人生

------分隔線----------------------------
分享到:
------分隔線----------------------------
為碼而活
積分:4237
15粉絲
7關(guān)注
欄目熱點(diǎn)
關(guān)閉
程序員人生
主站蜘蛛池模板: 在线观看成人小视频 | 91黄色在线 | av一级免费观看 | 久久99精品久久久久久园产越南 | 污网站观看 | 精品久草 | 2023av在线视频 | 免费在线观看av网站 | 精品一区二区三区中文字幕 | 国产黄色一级电影 | 日韩中文一区二区三区 | 日韩高清成人 | 精品一区二区三区中文字幕 | 午夜精品久久久久久久99无限制 | 日本在线观看一区 | 精产国产伦理一二三区 | 婷婷99狠狠躁天天躁中文字幕 | 国产成人精品久久久 | 91精品福利| 久久久精品影院 | 99精品热| 亚洲精品动漫久久久久 | 国产激情在线视频 | 中文字幕一区在线观看视频 | 精品九九九 | 91在线一区二区三区 | 成人亚洲精品久久久久软件 | 久久精品在线视频 | 嫩草影院在线观看视频 | 99久久精品免费看国产免费软件 | 亚洲综合视频网 | 超碰超碰| 国产激情在线 | 国产区视频在线 | 牛牛视频在线 | 黄色毛片国产 | 在线中文字幕视频 | 天堂在线观看 | 久久国产精品久久久久久 | 亚洲综合日韩欧美 | 亚洲精品午夜 |