java – Android中的Bundle的恶魔数量

前端之家收集整理的这篇文章主要介绍了java – Android中的Bundle的恶魔数量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
通过以下代码将数据从一个活动传递给其他活动:
@Override
    public void execute(List<Report> reports,Questions question) {
        Intent replyIntent = new Intent(listener,ReplyActivity.class);
        replyIntent.putExtra("id",0L);
        replyIntent.putExtra("questions",question);
        listener.openReportOk(question);
        listener.startActivity(replyIntent);
    }

监听其回调的活动引用.

问题是这个类:

@Table(name = "Questions")
public class Questions extends Entity implements Parcelable {

    public static final Creator<Questions> CREATOR = new Creator<Questions>() {
        public Questions createFromParcel(Parcel source) {
            return new Questions(source);
        }

        public Questions[] newArray(int size) {
            return new Questions[size];
        }
    };

    @TableField(name = "idReport",datatype = DATATYPE_INTEGER)
    private int idReport;
    @TableField(name = "nameReport",datatype = DATATYPE_STRING)
    private String nameReport;
    @TableField(name = "replyGroups",datatype = DATATYPE_STRING)
    private String replyGroups;
    @TableField(name = "questionGroups",datatype = DATATYPE_ENTITY)
    private List<QuestionsGroup> questionsGroup;
    private Boolean canCreateNew;

    public Questions(int idReport,String nameReport,String replyGroups,List<QuestionsGroup> questionsGroup) {
        this.idReport = idReport;
        this.nameReport = nameReport;
        this.replyGroups = replyGroups;
        this.questionsGroup = questionsGroup;
        this.canCreateNew = false;
    }

    public Questions() {
        questionsGroup = new ArrayList<QuestionsGroup>();
    }

    private Questions(Parcel in) {
        this();
        this.idReport = in.readInt();
        this.nameReport = in.readString();
        this.replyGroups = in.readString();
        Bundle b = in.readBundle(QuestionsGroup.class.getClassLoader());
        this.questionsGroup = b.getParcelableArrayList("questionGroups");
        this.canCreateNew = (Boolean) in.readValue(Boolean.class.getClassLoader());
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest,int flags) {
        dest.writeInt(this.idReport);
        dest.writeString(this.nameReport);
        dest.writeString(this.replyGroups);
        Bundle b = new Bundle();
        b.putParcelableArrayList("questionGroups",(ArrayList<QuestionsGroup>) this.questionsGroup);
        dest.writeBundle(b);
        dest.writeValue(this.canCreateNew);
    }
}

当我在onCreate方法中收到包裹时:

private void getData(Intent data) {
        ID = data.getExtras().getLong("id");
        questions = data.getExtras().getParcelable("questions");
    }

我得到这个错误

10-05 13:19:15.508    3499-3499/com.firext.android E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.firext.android,PID: 3499
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.firext.android/com.firext.android.activities.reply.ReplyActivity}: java.lang.IllegalStateException: Bad magic number for Bundle: 0x28
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2255)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2317)
            at android.app.ActivityThread.access$800(ActivityThread.java:143)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5070)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)
     Caused by: java.lang.IllegalStateException: Bad magic number for Bundle: 0x28
            at android.os.BaseBundle.readFromParcelInner(BaseBundle.java:1342)
            at android.os.BaseBundle.<init>(BaseBundle.java:90)
            at android.os.Bundle.<init>(Bundle.java:66)
            at android.os.Parcel.readBundle(Parcel.java:1645)
            at com.firext.android.domain.QuestionsGroup.<init>(QuestionsGroup.java:53)
            at com.firext.android.domain.QuestionsGroup$1.createFromParcel(QuestionsGroup.java:25)
            at com.firext.android.domain.QuestionsGroup$1.createFromParcel(QuestionsGroup.java:23)
            at android.os.Parcel.readParcelable(Parcel.java:2160)
            at android.os.Parcel.readValue(Parcel.java:2066)
            at android.os.Parcel.readListInternal(Parcel.java:2422)
            at android.os.Parcel.readArrayList(Parcel.java:1756)
            at android.os.Parcel.readValue(Parcel.java:2087)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2393)
            at android.os.BaseBundle.unparcel(BaseBundle.java:221)
            at android.os.Bundle.getParcelableArrayList(Bundle.java:782)
            at com.firext.android.domain.Questions.<init>(Questions.java:58)
            at com.firext.android.domain.Questions.<init>(Questions.java:18)
            at com.firext.android.domain.Questions$1.createFromParcel(Questions.java:22)
            at com.firext.android.domain.Questions$1.createFromParcel(Questions.java:20)
            at android.os.Parcel.readParcelable(Parcel.java:2160)
            at android.os.Parcel.readValue(Parcel.java:2066)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2393)
            at android.os.BaseBundle.unparcel(BaseBundle.java:221)
            at android.os.Bundle.getParcelable(Bundle.java:738)
            at com.firext.android.activities.reply.ReplyActivity.getData(ReplyActivity.java:72)
            at com.firext.android.activities.reply.ReplyActivity.onCreate(ReplyActivity.java:38)
            at android.app.Activity.performCreate(Activity.java:5720)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1102)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2208)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2317)
at android.app.ActivityThread.access$800(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5070)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)

怎么了?

解决方法

概要

看起来你有一个错误,你如何存储&检索问题组的混合信息.第53行是要注意的一行.

当写入包裹时,Android会在每个字段中存储一个特殊的“魔术数字”,以确保在将字段从包裹中拉出时使用正确的顺序(请参阅号码定义的详细说明).

您收到错误,因为在预期的位置找不到魔术数字 – 这是因为您没有以正确的顺序将字段从包裹中取出.

官方源代码的详细解释

[下面的解释是基于“最新的”(在撰写本文时)API21实现的Bundle和BaseBundle类.您可以在这里找到完整的代码

> BaseBundle on android.googlesource.com

您还可以使用Android SDK Manager将代码的本地副本安装到开发机器上,我觉得非常有用. ]

所以…

当包裹写入时,Android会采取一些安全措施,以确保在尝试对其进行不分开时,这些字段将排列起来.为此,Android将字段附加到“魔术数字”中,定义为:

static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'

你可以在writeToParcelInner()的代码中看到这一点(总结如下)

void writeToParcelInner(Parcel parcel,int flags) {
    if (mParcelledData != null) {
        if (mParcelledData == EMPTY_PARCEL) {
            parcel.writeInt(0);
        } else {
            int length = mParcelledData.dataSize();
            parcel.writeInt(length);
            parcel.writeInt(BUNDLE_MAGIC);
            parcel.appendFrom(mParcelledData,length);
        }
    } else {

   .......... extra code chopped out for illustration purposes

    }
}

同样,当从包裹中读取时,Android会在返回包裹中的值之前检查该BUNDLE_MAGIC号码.

private void readFromParcelInner(Parcel parcel,int length) {
    if (length == 0) {
        // Empty Bundle or end of data.
        mParcelledData = EMPTY_PARCEL;
        return;
    }
    int magic = parcel.readInt();
    if (magic != BUNDLE_MAGIC) {
        //noinspection ThrowableInstanceNeverThrown
        throw new IllegalStateException("Bad magic number for Bundle: 0x"
                + Integer.toHexString(magic));
    }

   .......... extra code chopped out for illustration purposes

}

在上述code for API21 BaseBundle中,您可以看到根据logcat跟踪在第1342行上抛出的错误.

解决方法进一步调试

原始海报指出,QuestionsGroup是正确包装.

进一步调试此问题的一种方法是远离引进BaseBundle类的(当前)新API21;例如,只使用Bundle类的API19.

如果用户代码实际上是正确的,那么更有可能在更成熟的API上运行.

如果代码仍然中断,则可能是QuestionsGroup代码.但是,除此之外,新的logcat跟踪将指向代码的不同部分,可以查看并可能提供更多的洞察问题.

除了是Bundle,第1730行,方法readFromParcelInner(),这意味着同样的问题:

int magic = parcel.readInt();
    if (magic != BUNDLE_MAGIC) {
        //noinspection ThrowableInstanceNeverThrown
        throw new IllegalStateException("Bad magic number for Bundle: 0x"
                + Integer.toHexString(magic));
    }

相关文章

有关相关信息,请参阅以下帖子:

> Android parcelable and Intent: redBundle: bad magic number

猜你在找的Java相关文章