【问题标题】:when i use parcelable interface to read/write a Boolean, Nullobject Reference happens,why?当我使用 Parcelable 接口读取/写入布尔值时,会发生 Nullobject 引用,为什么?
【发布时间】:2017-02-22 01:28:39
【问题描述】:

我正在尝试使对象 Parcelable 以传递给我开始编写实现 Parcelable 的用户类的活动。

Userare 的一个属性是布尔值,所以我通过引用 answer.即How to read/write a boolean when implementing the Parcelable interface? 来做到这一点

但是发生了一些错误,我得到了一个空引用错误。它说:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“boolean java.lang.Boolean.booleanValue()”。

代码如下。

public class User implements Parcelable{
    private String userName;
    private String passWord;
    private Boolean oldUser;

    public String getUserName() {
        return userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public Boolean getOldUser() {
        return oldUser;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public void setOldUser(Boolean oldUser) {
        this.oldUser = oldUser;
    }

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        User user = new User();
        parcel.writeString(user.userName);
        parcel.writeString(user.passWord);
        //seems a good way by using the official api.
        //parcel.writeBooleanArray(new boolean[]{user.oldUser});
        //null pointer,why?
        parcel.writeByte((byte) (user.oldUser ? 1 : 0));
    }

    public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
        public User createFromParcel(Parcel in) {
            User user = new User();
            //boolean[] myBooleanArr = new boolean[1];
            user.userName = in.readString();
            user.passWord = in.readString();
            //more codes needed to use the below api.
            //in.readBooleanArray(myBooleanArr);
            //user.oldUser = myBooleanArr[0];

            //method we define using readInt.
            user.oldUser = (in.readInt() != 0);
            return user;
        }

        public User[] newArray(int size) {

            return new User[size];
        }
    };
}

日志消息:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.thon.scos, PID: 2838
              java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
                  at es.source.code.model.User$override.writeToParcel(User.java:52)
                  at es.source.code.model.User$override.access$dispatch(User.java)
                  at es.source.code.model.User.writeToParcel(User.java:0)
                  at android.os.Parcel.writeParcelable(Parcel.java:1416)
                  at android.os.Parcel.writeValue(Parcel.java:1322)
                  at android.os.Parcel.writeArrayMapInternal(Parcel.java:665)
                  at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1330)
                  at android.os.Bundle.writeToParcel(Bundle.java:1079)
                  at android.os.Parcel.writeBundle(Parcel.java:690)
                  at android.content.Intent.writeToParcel(Intent.java:7793)
                  at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2639)
                  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
                  at android.app.Activity.startActivityForResult(Activity.java:3917)
                  at android.app.Activity.startActivityForResult(Activity.java:3877)
                  at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:861)
                  at android.app.Activity.startActivity(Activity.java:4200)
                  at android.app.Activity.startActivity(Activity.java:4168)
                  at es.source.code.activity.LoginOrRegister$1.onClick(LoginOrRegister.java:46)
                  at android.view.View.performClick(View.java:5198)
                  at android.view.View$PerformClick.run(View.java:21147)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

老实说,我是android和java的新手。我通过编辑尝试过

parcel.writeByte((byte) (user.oldUser ? 1 : 0));

parcel.writeByte((byte) (oldUser ? 1 : 0));

太棒了,它确实有效,所有错误都消失了。

解决方案正确吗?我就是想不通。 处理这个问题的最佳方法是什么?谢谢。

【问题讨论】:

    标签: java android


    【解决方案1】:

    在编写包裹时,您不应创建新的User 对象。您正在对当前对象实例进行操作。

    我猜您可以在createFromParcel() 方法中执行对象创建和读取包裹的所有逻辑,但我更经常看到下面的模式,您将包裹传递给对象的构造函数并在那里处理它。确保以完全相同的顺序读取和写入包裹中的字段。

    public class User implements Parcelable {
    
        private String userName;
        private String passWord;
        private boolean oldUser;
    
        public User(Parcel in) {
            userName = in.readString();
            passWord = in.readString();
            oldUser = in.readInt() == 1;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(userName);
            dest.writeString(passWord);
            dest.writeInt(oldUser ? 1 : 0);
        }
    
        public String getUserName() {
            return userName;
        }
    
        public String getPassWord() {
            return passWord;
        }
    
        public boolean getOldUser() {
            return oldUser;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public void setPassWord(String passWord) {
            this.passWord = passWord;
        }
    
        public void setOldUser(boolean oldUser) {
            this.oldUser = oldUser;
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
            public User createFromParcel(Parcel in) {
                return new User(in);
            }
    
            public User[] newArray(int size) {
                return new User[size];
            }
        };    
    
    }
    

    【讨论】:

    • 是的,它在 createFromParcel() 方法中表现良好,并且在我删除创建用户对象的过程后它也可以工作。为了粉丝,我仍然不知道原因,可能是这只是关于java语言,而不是android。我想我应该处理基本的 java 语法。
    • 至于构造函数,我不得不承认它确实是一个更好的方法。现在对我来说合适的方法是保持样式以防发生太多变化。完成演示后,我将根据您的解决方案重构我的代码。谢了。
    • 如果对您有帮助,请将其标记为答案。
    【解决方案2】:

    对于真正的 Boolean(不是 boolean)我会选择:

    @Override
        public void writeToParcel(Parcel out, int flags) {
            if (open_now == null) {
                out.writeInt(-1);
            } else {
                out.writeInt(open_now ? 1 : 0);    
            }
    

    private MyClass(Parcel in) {
        switch (in.readInt()) {
            case 0:
                open_now = false;
                break;
            case 1:
                open_now = true;
                break;
            default:
                open_now = null;
                break;
        }
    

    这将帮助您正确保持“空”值。

    【讨论】:

    • 知道如何处理Long 吗?
    • 我看到了两种方式。 1. 保留一些常量来表示 null 2. 使用附加字段
    猜你喜欢
    • 1970-01-01
    • 2011-09-06
    • 2013-03-10
    • 2012-12-14
    • 2014-03-31
    • 1970-01-01
    • 2011-09-30
    • 2019-09-28
    • 2013-07-30
    相关资源
    最近更新 更多