Problems专题:Parcel

Problems专题:Parcel

0x01 Unmarshalling unknown type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Thread Name: 'main' 
java.lang.RuntimeException: Parcel android.os.Parcel@bbfcc04: Unmarshalling unknown type code 2131296928 at offset 1088
at android.os.Parcel.readValue(Parcel.java:2750)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:3126)
at android.os.Parcel.readSparseArray(Parcel.java:2354)
at android.os.Parcel.readValue(Parcel.java:2728)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3045)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
at android.os.BaseBundle.unparcel(BaseBundle.java:232)
at android.os.Bundle.getSparseParcelableArray(Bundle.java:1010)
at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2133)
at android.app.Activity.onRestoreInstanceState(Activity.java:1173)
at android.app.Activity.performRestoreInstanceState(Activity.java:1128)
at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1318)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3025)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1840)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:6878)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)

问题分析

情况1 Parcelable 对象为空,反序列化异常

情况2 Parcelable 序列化和反序列化的字段和顺序没有完全对应

情况3 自定义View的数据保存与恢复

解决方案

情况1 Parcelable 对象在序列化和反序列化增加 null 值判断

情况2 Parcelable 对象 read 和 write 字段的类型和顺序保持一直

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Account implements Parcelable {
public Account(Parcel in) {
this.name = in.readString();
this.type = in.readInt();
if (TextUtils.isEmpty(name)) {
throw new android.os.BadParcelableException("the name must not be empty: " + name);
}
// ...
this.accessId = in.readString();
// ...
}

public int describeContents() {
return 0;
}

public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(type);
dest.writeString(accessId);
}
// ...
}

情况3 自定义View的数据保存与恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
override fun onSaveInstanceState(): Parcelable? {
Log.d("NavigationBar", "onSaveInstanceState: selectedId=${mSelectedId}")
return SavedState(super.onSaveInstanceState(), mSelectedId)
}

override fun onRestoreInstanceState(state: Parcelable?) {
if (state is SavedState) {
val id = state.selectedId
Log.d("NavigationBar", "onRestoreInstanceState: selectedId=${state.selectedId}")
super.onRestoreInstanceState(state.superState)
select(id)
return
}
return super.onRestoreInstanceState(state)
}

internal class SavedState : BaseSavedState {
var selectedId: Int = View.NO_ID

constructor(source: Parcel) : super(source) {
selectedId = source.readInt()
Log.d("NavigationBar", "readFromParcel: selectedId=$selectedId")
}

constructor(superState: Parcelable?, selectedId: Int) : super(superState) {
this.selectedId = selectedId
}

override fun writeToParcel(parcel: Parcel, flags: Int) {
super.writeToParcel(parcel, flags)
parcel.writeInt(selectedId)
Log.d("NavigationBar", "writeToParcel: selectedId=$selectedId")
}

override fun describeContents(): Int {
return 0
}

companion object CREATOR : Parcelable.Creator<SavedState> {
override fun createFromParcel(parcel: Parcel): SavedState {
return SavedState(parcel)
}

override fun newArray(size: Int): Array<SavedState?> {
return arrayOfNulls(size)
}
}
}

0x02 android.os.TransactionTooLargeException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 542688 bytes
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:160)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:6878)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
Caused by: android.os.TransactionTooLargeException: data parcel size 542688 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:479)
at android.app.IActivityManager$Stub$Proxy.activityStopped(IActivityManager.java:3941)
at java.lang.reflect.Method.invoke(Native Method)
at com.taobao.monitor.impl.common.c.invoke(ActivityManagerHook.java:89)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy2.activityStopped(Unknown Source)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:144)
... 7 more
android.os.TransactionTooLargeException: data parcel size 542688 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:479)
at android.app.IActivityManager$Stub$Proxy.activityStopped(IActivityManager.java:3941)
at java.lang.reflect.Method.invoke(Native Method)
at com.taobao.monitor.impl.common.c.invoke(ActivityManagerHook.java:89)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy2.activityStopped(Unknown Source)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:144)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:6878)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)

问题分析

1 Intent 传递的数据过大。

2 onSaveInstance 保存的数据过大。

解决方案

尽可能的使用少量的数据。

大数据考虑持久化和其他传递形式。

作者

Dench

发布于

2021-06-18

更新于

2021-06-18

许可协议

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×