使用Intent传递数据大家都知道,但是如果你使用Intent传递大于1Mb的数据时,就一定会报如下的错误:
Caused by: android.os.TransactionTooLargeException: data parcel size 1049112 bytes
就是说你的传输数据太大了,当前的大小达到了1049112 bytes。
下面就给出解决办法,使用putBinder()方法传递大数据,此时使用的是共享内存而不是Binder传输缓存,因此不受1Mb的限制,但是使用该方法也有要注意的点。
/*** Inserts an {@link IBinder} value into the mapping of this Bundle, replacing* any existing value for the given key. Either key or value may be null.** <p class="note">You should be very careful when using this function. In many* places where Bundles are used (such as inside of Intent objects), the Bundle* can live longer inside of another process than the process that had originally* created it. In that case, the IBinder you supply here will become invalid* when your process goes away, and no longer usable, even if a new process is* created for you later on.</p>** @param key a String, or null* @param value an IBinder object, or null*/public void putBinder(@Nullable String key, @Nullable IBinder value) {unparcel();mMap.put(key, value);}
意思是说一般情况在进程中利用Bundle传递数据时,Bundle在使用该数据的进程中存活的时间比创建该Bundle的进程中存活的时间要久。但是如果使用putBinder()方式传递数据时,数据在自定义的Binder中,创建Binder的进程一旦不存在,那Binder在使用它的进程中就会变为不可用。这一点在数据流转与取数据的时候一定要小心。
发送方:
package com.openld.seniorstructure.main.testintentbigdataimport android.content.Intent
import android.os.Binder
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import com.openld.seniorstructure.Rclass TestIntentTransBIgDataActivity : AppCompatActivity() {private lateinit var mBtnFail: AppCompatButtonprivate lateinit var mBtnSuccess: AppCompatButtonoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_test_intent_trans_big_data)initWidgets()addListeners()}private fun initWidgets() {mBtnFail = findViewById(R.id.btn_fail)mBtnSuccess = findViewById(R.id.btn_success)}private fun addListeners() {// 必崩溃mBtnFail.setOnClickListener {val intent = Intent(this,TestIntentTransBigDataResultActivity::class.java)val data = ByteArray(1024 * 1024)val bundle = Bundle()bundle.putByteArray("bigData", data)intent.putExtra("bundle", bundle)startActivity(intent)}// 可以传递大数据mBtnSuccess.setOnClickListener {val intent = Intent(this,TestIntentTransBigDataResultActivity::class.java)val data = ByteArray(1024 * 1024)val bundle = Bundle()val bigData = BigData(ByteArray(1024 * 1024))bundle.putBinder("bigData", bigData)intent.putExtra("bundle", bundle)startActivity(intent)}}
}data class BigData(val byteArray: ByteArray) : Binder() {}
接收方:
package com.openld.seniorstructure.main.testintentbigdataimport android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.openld.seniorstructure.Rclass TestIntentTransBigDataResultActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_test_intent_trans_big_data_result)val bundle = intent.getBundleExtra("bundle")val ba = bundle?.getBinder("bigData") as BigDataToast.makeText(this, "" + ba.byteArray.size / 1024, Toast.LENGTH_SHORT).show()}
}
注意:
上面的用法仅限于单进程,如果需要跨进程传递,必须使用AIDL来实现。
具体实现参考:
Android跨进程传图片或者大数据(解决TransactionTooLargeException)_binder传递bitmap-CSDN博客