久久综合九色综合97婷婷-美女视频黄频a免费-精品日本一区二区三区在线观看-日韩中文无码有码免费视频-亚洲中文字幕无码专区-扒开双腿疯狂进出爽爽爽动态照片-国产乱理伦片在线观看夜-高清极品美女毛茸茸-欧美寡妇性猛交XXX-国产亚洲精品99在线播放-日韩美女毛片又爽又大毛片,99久久久无码国产精品9,国产成a人片在线观看视频下载,欧美疯狂xxxx吞精视频

有趣生活

當前位置:首頁>職場>int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)

發(fā)布時間:2024-01-24閱讀(13)

導讀碼個蛋(codeegg)第668次推文作者:承香墨影原文:https://mp.weixin.qq.com/s/v57mDRnSEZ6hl7-bc3ugwA....

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)(1)

碼個蛋(codeegg)第 668 次推文

作者:承香墨影

原文:https://mp.weixin.qq.com/s/v57mDRnSEZ6hl7-bc3ugwA

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)(2)

一、序

作為 Android 開發(fā),日常 Coding 時,最頻繁的操作應該就是操作 App 內(nèi)的一系列 Activity。而在 Activity 間傳遞數(shù)據(jù),就需要借助 Intent。

不少資料中寫到,Intent 在 Activity 間傳遞基礎類型數(shù)據(jù)或者可序列化的對象數(shù)據(jù)。但是 Intent 對數(shù)據(jù)大小是有限制的,當超過這個限制后,就會觸發(fā) TransactionTooLargeException 異常。

那么今天就來聊聊 Intent 傳遞大數(shù)據(jù)時,為什么會拋異常,以及如何解決它。

二、為什么會出現(xiàn)異常?

2.1 異常原因

Intent 傳遞大數(shù)據(jù),會出現(xiàn) TransactionTooLargeException 的場景,這本身也是一道面試題,經(jīng)常在面試中被問到。

其實這個問題,如果遇到了,查查文檔就知道了。

在TransactionTooLargeException(https://developer.android.com/reference/android/os/TransactionTooLargeException.html) 的文檔中,其實已經(jīng)將觸發(fā)原因詳細說明了。

簡單來說,Intent 傳輸數(shù)據(jù)的機制中,用到了 Binder。Intent 中的數(shù)據(jù),會作為 Parcel 被存儲在 Binder 的事務緩沖區(qū)(Binder transaction buffer)中的對象進行傳輸。

而這個 Binder 事務緩沖區(qū)具有一個有限的固定大小,當前為 1MB。你可別以為傳遞 1MB 以下的數(shù)據(jù)就安全了,這里的 1MB 空間并不是當前操作獨享的,而是由當前進程所共享。也就是說 Intent 在 Activity 間傳輸數(shù)據(jù),本身也不適合傳遞太大的數(shù)據(jù)。

2.2 Bundle的鍋?

這里再補充一些細節(jié),Intent 使用 Bundle 存儲數(shù)據(jù),到底是值傳遞(深拷貝)還是引用傳遞?

Intent 傳輸?shù)臄?shù)據(jù),都存放在一個 Bundle 類型的對象 mExtras 中,Bundle 要求所有存儲的數(shù)據(jù),都是可被序列化的。

在 Android 中,序列化數(shù)據(jù)需要實現(xiàn) Serializable 或者 Parcelable。對于基礎數(shù)據(jù)類型的包裝類,本身就是實現(xiàn)了 Serializable,而我們自定義的對象,按需實現(xiàn)這兩個序列化接口的其中一個即可。

那是不是只要通過 Bundle 傳遞數(shù)據(jù),就會面臨序列化的問題?

并不是,Activity 之間傳遞數(shù)據(jù),首先要考慮跨進程的問題,而 Android 中又是通過 Binder 機制來解決跨進程通信的問題。涉及到跨進程,對于復雜數(shù)據(jù)就要涉及到序列化和反序列化的過程,這就注定是一次值傳遞(深拷貝)的過程。

這個問題用反證法也可以解釋,如果是引用傳遞,那傳遞過去的只是對象的引用,指向了對象的存儲地址,就只相當于一個 Int 的大小,也就根本不會出現(xiàn) TransactionTooLargeException 異常。

傳輸數(shù)據(jù)序列化和 Bundle 沒有關系,只與 Binder 的跨進程通信有關。

為什么要強調(diào)這個呢?

在 Android 中,使用 Bundle 傳輸數(shù)據(jù),并非 Intent 獨有的。例如使用彈窗時,DialogFragment 中也可以通過 setArguments(Bundle)傳遞一個 Bundle 對象給對話框。

Fragment 本身是不涉及跨進程的,這里雖然使用了 Bundle 傳輸數(shù)據(jù),但是并沒有通過 Binder,也就是不存在序列化和反序列化。和 Fragment 數(shù)據(jù)傳遞相關的 Bundle,其實傳遞的是原對象的引用。

有興趣可以做個試驗,彈出 Dialog 時傳遞一個對象,Dialog 中修改數(shù)據(jù)后,在 Activity 中檢查數(shù)據(jù)是否被修改了。

三、如何解決這個異常?

3.1 解決思路

知道異常的原因,就好解決了。

既然原因在于 Binder 傳輸限制了數(shù)據(jù)的大小,那我們不走 Binder 通信就好了。

可以從數(shù)據(jù)源上來考慮。

例如 Bitmap,本身就已經(jīng)實現(xiàn)了 Parcelable 是可以支持序列化的。用 Intent 傳輸,稍微大一點的圖一定會出現(xiàn) TransactionTooLargeException。當然真是業(yè)務場景,肯定不存在傳遞 Bitmap 的情況。

那就先看看這個圖片的數(shù)據(jù)源。Drawable?本地文件?線上圖片?無論數(shù)據(jù)源在哪里,我們只需要傳遞一個 drawable_id、路徑、URL,就可以還原這張圖片,無需將這個 Bitmap 對象傳遞過去。大數(shù)據(jù)總有數(shù)據(jù)源,從數(shù)據(jù)源還原數(shù)據(jù),對我們而言只是調(diào)用一個方法而已。

此前阿里發(fā)布的《Android 開發(fā)者手冊》中,就提到了這個問題的解決建議。

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)(3)

阿里給出的方案,是通過 EventBus 來傳遞數(shù)據(jù)。

3.2 EventBus的粘性事件

很多商業(yè)項目其實都用到了 EventBus,這里就簡單介紹如何使用 EventBus 的粘性事件來完成數(shù)據(jù)在 Activity 間的傳遞。

EventBus 是一個 Android 端優(yōu)化的 Publish/subscribe 消息總線,簡化了應用程序內(nèi)各個組件間、組件與后臺線程間的通信。

在 Activity 中使用 EventBus,需要根據(jù) Activity 的生命周期,成對調(diào)用 registerunregister方法。普通的事件,只會發(fā)生在register之后,在注冊前發(fā)生的事件,統(tǒng)統(tǒng)都收不到。

這里利用的 EventBus 的粘性事件(Sticky Event)來實現(xiàn),EventBus 內(nèi)部維護了一個 Map 對象 stickyEvents,用于緩存粘性事件。

粘性事件使用 postSticky方法發(fā)送,它會將事件緩存到stickyEvents這個 Map 對象中,以待下次注冊時,將這個事件取出,拋給注冊的組件。以此來達到一個粘性的滯后事件發(fā)送和接收。

接下來我們看看 EventBus 粘性事件的使用細節(jié)。

(1) 注解的區(qū)別

粘性事件的注解和普通事件的注解略有區(qū)別,需要添加 threadMode 和 sticky 參數(shù)。

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)public void onStickyEvent(MyStickyEvent event){//...}

注意,這兩個額外的參數(shù)是必須的。

(2) 調(diào)用方法的區(qū)別

在發(fā)送消息的時候,需要使用 postSticky來替換掉post方法。

需要注意的是,粘性事件是使用 Map 結(jié)構(gòu)緩存的,并且是使用事件對象類型當 Key 進行緩存,所以對于同類型的數(shù)據(jù),它只會緩存最后發(fā)送的數(shù)據(jù)。

(3) 注意清理事件

前面也提到,粘性事件是存儲在一個 Map 對象中的,它是不會主動清理其中存儲的對象的,需要開發(fā)者手動清理。

EventBus 提供了兩類方法 removeStickyEventremoveAllStickyEvents方法,分別用來清理固定數(shù)據(jù)以及全部數(shù)據(jù)。

我們需要在合適的時機,手動的調(diào)用這兩類方法,清理粘性事件。如果不對粘性事件進行清理,每次 register的時候,都會收到粘性事件。

(4)EventBus粘性事件的問題

粘性事件本身是脫離了 Android Intent 數(shù)據(jù)傳遞的這一套機制的,要知道 Activity 會在一些特殊情況下被銷毀重建,在此情況下,通過 Intent 傳遞的數(shù)據(jù),是可以繼續(xù)從 Intent 中獲取恢復到上一次頁面?zhèn)鬟f的數(shù)據(jù)。

而通過 EventBus 的粘性事件,則可能在銷毀重建時,造成數(shù)據(jù)丟失。

如果想要使用 EventBus 的粘性事件,來在頁面間傳遞大數(shù)據(jù),還是有不少細節(jié),需要根據(jù)業(yè)務來調(diào)整的。

四、小結(jié)

今天我們聊到了在 Activity 間,通過 Intent 傳遞大數(shù)據(jù)會觸發(fā) TransactionTooLargeException 異常的原因,以及如何解決它,最后再簡單總結(jié)一下。

  1. Intent 無法傳遞大數(shù)據(jù)是因為其內(nèi)部使用了 Binder 通信機制,Binder 事務緩沖區(qū)限制了傳遞數(shù)據(jù)的大小。

  2. Binder 事務緩沖區(qū)的大小限定在 1MB,但是這個尺寸是共享的,也就是并不是傳遞 1MB 以下的數(shù)據(jù)就絕對安全,要視當前的環(huán)境而定。

  3. 不要挑戰(zhàn) Intent 傳遞數(shù)據(jù)大小的極限,對于大數(shù)據(jù),例如長字符串、Bitmap 等,不要考慮 Intent 傳遞數(shù)據(jù)的方案。

  4. 解決大數(shù)據(jù)傳遞問題,可以從數(shù)據(jù)源出發(fā),根據(jù)數(shù)據(jù)的標識,還原數(shù)據(jù),或者先持久化再還原。也可以使用 EventBus 的粘性事件來解決。

reference:

https://developer.android.com/reference/android/os/TransactionTooLargeException.html

https://www.wanandroid.com/blogimgs/a2609aed-1000-4039-93c3-7541aaa2013b.pdf

近期文章:

  • 我膨脹了!繼續(xù)帶你手寫QQ底層(三)

  • 居安思危,面試題還是可以多看看的

  • 周末了,碼仔們懂的圖

今日問題:

有時候一些很小的點,可以擴展了解很多,有沒有這樣的體驗?

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)(4)

快來碼仔社群解鎖新姿勢吧!社群升級:Max你的學習效率

int類型如何和0比較大小(Intent傳遞數(shù)據(jù)的最大Size是多少)(5)

TAGS標簽:  類型  如何  比較  大小  Intent  int類型如何和0比

歡迎分享轉(zhuǎn)載→http://www.avcorse.com/read-212117.html

Copyright ? 2024 有趣生活 All Rights Reserve吉ICP備19000289號-5 TXT地圖HTML地圖XML地圖