<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    冰浪

    哥已不再年輕 - 堅(jiān)定夢(mèng)想,畢生追求!
    posts - 85, comments - 90, trackbacks - 0, articles - 3
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    [轉(zhuǎn)]組件間的交互和進(jìn)程間IPC通信

    Posted on 2010-01-15 00:15 冰浪 閱讀(465) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Android
    在Android中窗體與窗體之間如何互相調(diào)用和交換數(shù)據(jù)?窗體(Activity)和后臺(tái)的服務(wù)(Service)如何通信?基于Unix(Linux)的系統(tǒng)都有一個(gè)很優(yōu)秀的傳統(tǒng),就是倡導(dǎo)非常輕便的進(jìn)程間通信(IPC)機(jī)制;倡導(dǎo)進(jìn)程通過(guò)IPC來(lái)互相協(xié)作;倡導(dǎo)功能單一,小巧而強(qiáng)壯的進(jìn)程,而不是又大又復(fù)雜的“萬(wàn)金油”。同樣,在Android中我們可以將我們的Activity和Service放在不同的進(jìn)程中運(yùn)行,我們可以在我們的Task 中加載其他進(jìn)程的Activity,這些機(jī)制都鼓勵(lì)我們“盡量利用已有的功能,利用IPC和包含這些已有功能的程序協(xié)作,來(lái)完成一個(gè)完整的應(yīng)用”,例如在我們的程序中充分利用Google Map的相關(guān)窗體和服務(wù)。所有這些都建立在一套輕便好用的IPC機(jī)制上。


    Android的組件和進(jìn)程間通信都建立在一種基于稱(chēng)為Intent的消息基礎(chǔ)之上。Intent就是一種消息,它包含了兩個(gè)重要的內(nèi)容:1. 消息的目的,即這個(gè)消息是發(fā)給哪個(gè)組件的?(消息的目的中不會(huì)包含“消息是發(fā)給哪個(gè)進(jìn)程”這樣的信息,這里Android有意淡化進(jìn)程的概念,而只讓我們關(guān)心組件,因?yàn)榱私馓嚓P(guān)于進(jìn)程的具體信息會(huì)加大復(fù)雜度,而又如何做到進(jìn)程間的消息傳遞呢?下文會(huì)說(shuō)到一種Android中關(guān)于這點(diǎn)比較特別的設(shè)計(jì)方式,我認(rèn)為是一種簡(jiǎn)捷有用又符合手機(jī)特點(diǎn)的設(shè)計(jì));2. 消息所攜帶的數(shù)據(jù)內(nèi)容,即需要傳遞給目標(biāo)的數(shù)據(jù)。下面是一個(gè)簡(jiǎn)單的利用Intent來(lái)啟動(dòng)一個(gè)Service并向其傳遞數(shù)據(jù)的代碼示例:


    Intent serviceIntent = new Intent(context, svrMain.class);
    serviceIntent.putExtra(“Network_Report”, networkStatus);
    context.startService(serviceIntent);


    上面的代碼首先構(gòu)造了一個(gè)Intent對(duì)象,并在構(gòu)造的時(shí)候指定了這個(gè)Intent的目的地,即“svrMain.class”,表示這個(gè)Intent是要傳遞給一個(gè)類(lèi)名叫svrMain的Service。然后向這個(gè)Intent中放入了一個(gè)數(shù)據(jù),數(shù)據(jù)的key為“Network_Report”,value為一個(gè)叫networkStatus的int類(lèi)型變量,用來(lái)指明當(dāng)前網(wǎng)絡(luò)的狀態(tài)。最后我們使用系統(tǒng)提供的上下文API,將這個(gè)Intent傳遞給指定的Service。


    Intent的消息目的地分為兩種模式,一種是顯式的,一種是隱式的。我們上面的例子中看到的就是一個(gè)顯式消息的例子。顯式消息直接指定消息目的地組件的類(lèi)元信息,例如上面例子中svrMain就是我們寫(xiě)的一個(gè)類(lèi)名為svrMain的Service,class操作符就是獲取其類(lèi)元信息。這種模式的消息由于已經(jīng)確切知道了消息目標(biāo)的確切信息,所以只適用于同一進(jìn)程內(nèi)的不同組件之間通信,例如打開(kāi)一個(gè)子窗體,和同一進(jìn)程中的service通信等。對(duì)應(yīng)的,隱式消息就一般用于跨進(jìn)程的通信了,隱式消息沒(méi)有確定的消息目的地,除了數(shù)據(jù)外,隱式消息只是包含了一些用于表征消息特征的描述字段。而一些需要收到某種特定特征消息的某個(gè)程序中的某個(gè)組件,需要通過(guò)在其所在程序的AndroidMainifest.xml中注冊(cè)一種被稱(chēng)為intent-filter的消息特征篩選器,然后Android系統(tǒng)會(huì)按照一定的匹配規(guī)則來(lái)匹配發(fā)出的消息特征和所有擁有響應(yīng)這種特征的intent-filter的組件(無(wú)論是同一進(jìn)程內(nèi)的組件還是不同程序中的組件),匹配到的組件就會(huì)接受到相應(yīng)的消息。前面的描述多少有些拗口,我們舉個(gè)實(shí)際的例子來(lái)說(shuō)明,如果我們想開(kāi)啟一個(gè)子窗體(無(wú)論這個(gè)窗體來(lái)自同一進(jìn)程還是不同進(jìn)程),我們除了使用顯式消息外,我們還可以使用隱式消息:


    Intent openSomeDiagIntent = new Intent();
    openSomeDiagIntent.setAction(“edwin.demo.fooActivity”);
    this.startActivity(openSomeDiagIntent);


    上面的隱式消息不包含具體的目的地,而是僅包含一個(gè)名位“Action”的特征字符串,Action就是上文所說(shuō)的Intent特征的一種。從字面上來(lái)理解,可以理解為這個(gè)消息所代表的是完成某一個(gè)動(dòng)作的含義,由action來(lái)標(biāo)明動(dòng)作的名字。所有能夠處理這種動(dòng)作的Activity都可以收到該消息。對(duì)應(yīng)的,可能在同一個(gè)程序或者另外的某個(gè)程序的AndroidMainifest.xml中聲明了下面這樣的一個(gè)Activity:


    <activity android:name=”.fooActivity”>
    <intent-filter>
    <action android:name=”edwin.demo.fooActivity” />
    </intent-filter>
    </activity>


    那么這就表示這個(gè)Activity能夠收到并處理action為“edwin.demo.fooActivity”的消息。所以上面的代碼串起來(lái)的效果就是,打開(kāi)了這個(gè)名為.fooActivity的窗口,無(wú)論這個(gè)窗口是在當(dāng)前的進(jìn)程中還是另外的一個(gè)程序中。


    除了Action這種消息特征外,Intent還有category,data這兩個(gè)特征描述屬性。Category同樣是一個(gè)字符串,從字面上理解就是“消息的分類(lèi)特征”。從程序上看其和Action的不同在于,一個(gè)Intent只能有惟一的一個(gè)Action名稱(chēng),但是卻可以包含多個(gè)Category字符串;一個(gè)Intent-Filter可以包含多個(gè)Action節(jié)點(diǎn)但至少要包含一個(gè),另一方面一個(gè)Intent-Filter可以包含零到多個(gè)Category節(jié)點(diǎn)。Android在做Intent-Filter匹配的時(shí)候,Intent的Action屬性匹配到Intent-Filter中的任何一個(gè)action節(jié)點(diǎn),就表明擁有這個(gè)Intent-Filter的組件能夠處理這種消息;而對(duì)于Category來(lái)講一個(gè)Intent中的所有的Category都必須存在于Intent-Filter中的Category節(jié)點(diǎn)中時(shí),才表明匹配成功。Data屬性可以描述一個(gè)Intent所要傳遞的數(shù)據(jù)類(lèi)型和URI,每一個(gè)Intent只能包含一個(gè)Data屬性。其中數(shù)據(jù)的類(lèi)型使用MIME類(lèi)型描述方式來(lái)描述,例如video/mpeg表示編碼格式為mpeg的視頻,這里也可以使用通配符,例如video/*表示任意格式的視頻文件類(lèi)型;數(shù)據(jù)的URI由scheme(協(xié)議),host,port,path四部分組成:scheme://host:port/path,例如http://test.com:8080/file/file1 或者content://edwin.demo.contentProvider:100/forder/content1,其中path部分也是可以支持通配符的。Data屬性是一個(gè)很有用的描述特征,例如下面這樣的一個(gè)包含data節(jié)點(diǎn)的Intent-Filter:


    <activity android:name=”.actHttpVideoMan”>
    <intent-filter>
    <action android:name=”edwin.demo.actHttpVideoMan.Main” />
    <data android:scheme=”http” android:type=”video/*” />
    </intent-filter>
    </activity>


    它表示窗體actHttpVideoMan能夠處理來(lái)自web服務(wù)器的視頻文件。這樣的filter有什么作用呢?最典型的情況就是配合瀏覽器工作。瀏覽器在打開(kāi)一個(gè)鏈接的時(shí)候首先會(huì)嘗試顯示這個(gè)鏈接對(duì)應(yīng)的html頁(yè)面,如果這個(gè)鏈接不是一個(gè)html頁(yè)面,而是一個(gè)視頻文件或者其他瀏覽器本身不能處理的格式的話,瀏覽器會(huì)使用隱式消息嘗試開(kāi)啟一個(gè)能夠處理這種數(shù)據(jù)格式的Activity來(lái)處理,瀏覽器發(fā)出的隱式消息就是一個(gè)包含data屬性,其中URI scheme為http,數(shù)據(jù)類(lèi)型為video/*的消息,如果有能夠匹配這個(gè)intent的組件,例如我們上面的那個(gè)activity,瀏覽器就會(huì)啟動(dòng)這個(gè)窗體,接著這個(gè)窗體會(huì)根據(jù)data屬性指定的URI去播放在線視頻,如果沒(méi)有可以處理這個(gè)intent的Activity,瀏覽器才會(huì)調(diào)用下載管理器下載文件。


    隱式消息這個(gè)設(shè)計(jì)簡(jiǎn)單有效,它忽略了進(jìn)程的細(xì)節(jié),讓IPC在一個(gè)更高的更接近人腦思維模式的層次工作,讓系統(tǒng)中的不同進(jìn)程協(xié)作看起來(lái)就像是同一程序中的協(xié)作一樣,這種簡(jiǎn)單的IPC機(jī)制在很大的程度上鼓勵(lì)我們和其他進(jìn)程協(xié)作,通過(guò)協(xié)作的進(jìn)程來(lái)完成一個(gè)復(fù)雜的任務(wù),而不是把什么功能都做到一個(gè)大而全的程序里面。不過(guò)上文還有一些細(xì)節(jié)沒(méi)有提到,例如如果一個(gè)intent有多個(gè)可匹配的處理組件,系統(tǒng)如何處理?這就要分響應(yīng)消息的組件類(lèi)型來(lái)說(shuō)了,如果是service,那么這些service都可以啟動(dòng)并處理消息,如果是Activity,則android會(huì)彈出一個(gè)對(duì)話框讓用戶(hù)進(jìn)行選擇。比如我們安裝了多個(gè)可以處理在線視頻的軟件,當(dāng)我們?cè)跒g覽器中點(diǎn)擊一個(gè)在線視頻的鏈接時(shí),系統(tǒng)會(huì)讓用戶(hù)選擇使用哪個(gè)軟件來(lái)觀看。另外大家一定會(huì)想到安全性的問(wèn)題,如果不同進(jìn)程間的組件可以通過(guò)隱式消息互相通信,那我們的程序不是可以輕易調(diào)用到其他的程序或者系統(tǒng)中的一些敏感程序的組件,這樣會(huì)不會(huì)很不安全呢?其實(shí)Android在安全方面有一個(gè)統(tǒng)一,完備和輕便的安全策略模型,Intent的安全自然是被考慮在內(nèi)的,關(guān)于android的安全模型我會(huì)在后續(xù)的系列blog中專(zhuān)門(mén)說(shuō)明。


    最后,除了Intent這種基于消息的進(jìn)程內(nèi)和進(jìn)程間通信模型外,android中也有一種相比起來(lái)稍顯笨重一些的IPC機(jī)制,它采用類(lèi)似遠(yuǎn)程方法調(diào)用的方案,通過(guò)接口定義文件AIDL來(lái)定義一個(gè)IPC接口,然后通過(guò)接收方實(shí)現(xiàn)接口,調(diào)用方調(diào)用接口的本地代理實(shí)現(xiàn)來(lái)完成IPC。這種模型只適用于Activity和Service間的通信,之所以需要這種稍顯重量的模式,是因?yàn)锳ctivity除了發(fā)送intent去啟動(dòng)一個(gè)service外,可能還需要能夠在Service的運(yùn)行過(guò)程中連接到service,對(duì)Service發(fā)送一些控制請(qǐng)求。例如音樂(lè)播放程序,其后臺(tái)的播放服務(wù)往往獨(dú)立運(yùn)行,以方便我們?cè)谑褂闷渌绦蚪缑鏁r(shí)也能聽(tīng)到音樂(lè)。同時(shí)這個(gè)后臺(tái)播放服務(wù)也會(huì)定義一個(gè)控制接口,包含比如播放,暫停,快進(jìn)之類(lèi)的方法,任何時(shí)候播放程序的界面都可以通過(guò)使用bindService API連接到播放服務(wù),獲取這個(gè)接口的包含IPC細(xì)節(jié)的實(shí)現(xiàn)代理,通過(guò)這組控制接口方法對(duì)其進(jìn)行控制,這時(shí)這種IPC的方案就顯的更方便更直觀一些了。有關(guān)使用AIDL這種IPC的更詳細(xì)描述,Google的官方文檔已做了詳細(xì)的講解。

    轉(zhuǎn)自:http://hkbarton.sacredfir.com/?p=93
    主站蜘蛛池模板: 久热免费在线视频| 亚洲国产另类久久久精品小说 | 久久精品成人免费网站| 亚洲另类无码一区二区三区| 亚洲国产一区二区三区青草影视| 免费乱码中文字幕网站| 无码国产精品一区二区免费虚拟VR | eeuss草民免费| 亚洲国产av玩弄放荡人妇| 亚洲综合图片小说区热久久| 亚洲情综合五月天| 国产a不卡片精品免费观看| 91情侣在线精品国产免费| 免费人成视频在线观看网站| 免费一区二区无码东京热| 一个人看的www视频免费在线观看| 亚洲精品中文字幕| ASS亚洲熟妇毛茸茸PICS| 久久精品国产亚洲av日韩| 九月丁香婷婷亚洲综合色| 亚洲无人区一区二区三区| 亚洲精品动漫人成3d在线| 免费一级毛片在级播放| 午夜小视频免费观看| 欧美男同gv免费网站观看| 男女免费观看在线爽爽爽视频 | 亚洲真人无码永久在线| 亚洲精品国产精品国自产观看| 国产成人免费福利网站| 午夜寂寞在线一级观看免费| 欧洲乱码伦视频免费| www.999精品视频观看免费| 四虎永久在线精品免费观看视频| 国产免费丝袜调教视频| 亚洲免费电影网站| 亚洲视频免费播放| 2020久久精品国产免费| 国产片AV片永久免费观看| 最近中文字幕无吗免费高清 | 亚洲成人免费网站| 亚洲国产成人精品无码一区二区|