簡體   English   中英

Android數據綁定適配器空指針異常

[英]Android Databinding Adapter Null Pointer Exception

我正在嘗試在Android應用中使用Android數據綁定。 如果我初始化沒有任何數據的對象,則有一個對象Outlet 一切正常。 並且所有數據都收集良好。 但是,如果我使用數據初始化Object並將其傳遞到布局,則會由於抱怨Invoking Interface method on Null Views而使應用程序崩潰。 這是我的以下布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">

        <data>
            <import type="java.util.List"/>
            <import type="android.view.View" />
            <variable
                name="outlet"
                type="co.deliveryscience.dangote.Network.model.Outlet.Create.Outlet"/>
        </data>

        <android.support.v4.widget.NestedScrollView
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <android.support.v7.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="32dp"
                    android:layout_marginLeft="64dp"
                    android:layout_marginRight="64dp"
                    android:layout_marginTop="32dp"
                    android:background="#FFF"
                    android:animateLayoutChanges="true"
                    app:cardCornerRadius="4dp"
                    app:elevation="5dp">

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:paddingBottom="16dp"
                        android:paddingLeft="16dp"
                        android:paddingRight="16dp"
                        android:paddingTop="16dp"
                        android:animateLayoutChanges="true">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            style="@style/HeaderText"
                            android:text="@string/personal_information"
                            android:layout_marginBottom="8dp"
                            android:layout_marginTop="16dp"/>

                        <View
                            android:layout_width="match_parent"
                            android:layout_height="0.5dp"
                            android:background="@color/gray_semi_transparent"
                            android:layout_marginBottom="32dp"/>

                        <LinearLayout
                            android:id="@+id/layoutCreate"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="vertical"
                            android:layout_marginBottom="32dp">

                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="@string/name_of_outlet"
                                android:layout_marginBottom="8dp"/>

                            <EditText
                                android:id="@+id/nameOfOutlet"
                                android:layout_width="match_parent"
                                android:layout_height="55dp"
                                android:inputType="textCapWords"
                                android:singleLine="true"
                                android:imeOptions="actionNext"
                                android:text='@{outlet.name ?? ""}'
                                android:addTextChangedListener="@{outlet.onNameChanged}"
                                android:nextFocusDown="@+id/address"/>

                        </LinearLayout>

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal"
                            android:baselineAligned="false">

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:layout_weight="1"
                                android:orientation="vertical"
                                android:layout_marginRight="8dp"
                                android:layout_marginEnd="8dp">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/ownerfirstname"
                                    android:layout_marginBottom="8dp"/>

                                <EditText
                                    android:id="@+id/fName"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:layout_marginBottom="16dp"
                                    android:inputType="textCapWords"
                                    android:singleLine="true"
                                    android:imeOptions="actionNext"
                                    android:text="@{outlet.firstName}"
                                    android:addTextChangedListener="@{outlet.onFirstNameChanged}"
                                    android:nextFocusRight="@+id/lName"/>

                            </LinearLayout>

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:layout_weight="1"
                                android:orientation="vertical"
                                android:layout_marginLeft="8dp"
                                android:layout_marginStart="8dp">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/ownerlastname"
                                    android:layout_marginBottom="8dp"/>

                                <EditText
                                    android:id="@+id/lName"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:layout_marginBottom="16dp"
                                    android:inputType="textCapWords"
                                    android:text='@{outlet.lastName == null ? "" : outlet.lastName}'
                                    android:addTextChangedListener="@{outlet.onLastNameChanged}"
                                    android:singleLine="true"
                                    android:imeOptions="actionNext"
                                    android:nextFocusDown="@+id/nameOfOutlet"/>

                            </LinearLayout>

                        </LinearLayout>

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            style="@style/HeaderText"
                            android:text="@string/contact_information"
                            android:layout_marginBottom="8dp"
                            android:layout_marginTop="16dp"/>

                        <View
                            android:layout_width="match_parent"
                            android:layout_height="0.5dp"
                            android:background="@color/gray_semi_transparent"
                            android:layout_marginBottom="32dp"/>

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="@string/address"
                            android:layout_marginBottom="8dp"/>

                        <EditText
                            android:id="@+id/address"
                            android:layout_width="match_parent"
                            android:layout_height="55dp"
                            android:layout_marginBottom="16dp"
                            android:inputType="textPostalAddress"
                            android:text='@{outlet.address == null ? "" : outlet.address}'
                            android:addTextChangedListener="@{outlet.onAddresChanged}"
                            android:imeOptions="actionNext"
                            android:nextFocusDown="@+id/lga"/>

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal"
                            android:layout_marginBottom="16dp"
                            android:baselineAligned="false">

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:orientation="vertical"
                                android:layout_weight="1"
                                android:layout_marginRight="8dp"
                                android:layout_marginEnd="8dp">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/lga"
                                    android:layout_marginBottom="8dp"/>

                                <AutoCompleteTextView
                                    android:id="@+id/lga"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:imeOptions="actionNext"
                                    android:inputType="textCapWords"
                                    android:text="@{outlet.lga}"
                                    android:singleLine="true"
                                    android:nextFocusRight="@+id/state"/>

                            </LinearLayout>

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:orientation="vertical"
                                android:layout_weight="1"
                                android:layout_marginStart="8dp"
                                android:layout_marginLeft="8dp">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/state"
                                    android:layout_marginBottom="8dp"/>

                                <AutoCompleteTextView
                                    android:id="@+id/state"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:imeOptions="actionNext"
                                    android:inputType="textCapWords"
                                    android:singleLine="true"
                                    android:nextFocusDown="@+id/phoneNumber1" />

                            </LinearLayout>

                        </LinearLayout>

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal"
                            android:layout_marginBottom="16dp"
                            android:baselineAligned="true">

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:layout_weight="1"
                                android:layout_marginRight="8dp"
                                android:layout_marginEnd="8dp"
                                android:orientation="vertical">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/phone_number_1"
                                    android:layout_marginBottom="8dp"/>

                                <EditText
                                    android:id="@+id/phoneNumber1"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:layout_marginBottom="16dp"
                                    android:inputType="phone"
                                    android:imeOptions="actionNext"
                                    android:addTextChangedListener="@{outlet.onPhoneNumberChanged}"
                                    android:text="@{outlet.phoneNumber}"
                                    android:singleLine="true"
                                    android:nextFocusDown="@+id/phoneNumber2"/>

                            </LinearLayout>

                            <LinearLayout
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:layout_weight="1"
                                android:layout_marginLeft="8dp"
                                android:layout_marginStart="8dp"
                                android:orientation="vertical">

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:text="@string/phone_number_2"
                                    android:layout_marginBottom="8dp"/>

                                <EditText
                                    android:id="@+id/phoneNumber2"
                                    android:layout_width="match_parent"
                                    android:layout_height="55dp"
                                    android:layout_marginBottom="16dp"
                                    android:inputType="phone"
                                    android:imeOptions="actionNext"
                                    android:addTextChangedListener="@{outlet.onOtherPhoneNumberChanged}"
                                    android:text="@{outlet.phoneNumber}"
                                    android:singleLine="true"
                                    android:nextFocusDown="@+id/outletOwnerEmail"/>

                            </LinearLayout>

                        </LinearLayout>

                    </LinearLayout>

                </android.support.v7.widget.CardView>

            </LinearLayout>

        </android.support.v4.widget.NestedScrollView>
    </layout>

我的可觀察對象是這個

    public class Outlet extends BaseObservable {

        private static final String TAG = "Outlet";
        @SerializedName("name")
        @Expose
        private String name;
        @SerializedName("firstName")
        @Expose
        private String firstName;
        @SerializedName("lastName")
        @Expose
        private String lastName;
        @SerializedName("phoneNumber")
        @Expose
        private String phoneNumber;
        @SerializedName("otherNumber")
        @Expose
        private String otherNumber;
        @SerializedName("address")
        @Expose
        private String address;

        /**
         * 
         * @return
         *     The name
         */
        @Bindable
        public String getName() {
            return name;
        }

        /**
         * 
         * @param name
         *     The name
         */
        public void setName(String name) {
            setAtomicName(name);
            notifyPropertyChanged(BR.name);
        }

        public void setAtomicName(String basic) {
            this.name = basic;
        }

        public TextWatcher onNameChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"Name", newValue);
                setAtomicName(newValue);
            }
        };

        /**
         * 
         * @return
         *     The firstName
         */
        @Bindable
        public String getFirstName() {
            return firstName;
        }

        /**
         * 
         * @param firstName
         *     The firstName
         */
        public void setFirstName(String firstName) {
            setAtomicFirstName(firstName);
            notifyPropertyChanged(BR.firstName);
        }

        public void setAtomicFirstName(String basic) {
            this.firstName = basic;
        }

        public TextWatcher onFirstNameChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"FirstName", newValue);
                setAtomicFirstName(newValue);
            }
        };

        /**
         * 
         * @return
         *     The lastName
         */
        @Bindable
        public String getLastName() {
            return lastName;
        }

        /**
         * 
         * @param lastName
         *     The lastName
         */
        public void setLastName(String lastName) {
            setAtomicLastName(lastName);
            notifyPropertyChanged(BR.lastName);
        }

        public void setAtomicLastName(String basic) {
            this.lastName = basic;
        }

        public TextWatcher onLastNameChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"lstname", newValue);
                setAtomicLastName(newValue);
            }
        };

        /**
         * 
         * @return
         *     The phoneNumber
         */
        @Bindable
        public String getPhoneNumber() {
            return phoneNumber;
        }

        /**
         * 
         * @param phoneNumber
         *     The phoneNumber
         */
        public void setPhoneNumber(String phoneNumber) {
            setAtomicPhoneNumber(phoneNumber);
            notifyPropertyChanged(BR.phoneNumber);
        }

        public void setAtomicPhoneNumber(String basic) {
            this.phoneNumber = basic;
        }

        public TextWatcher onPhoneNumberChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"phonenumber", newValue);
                setAtomicPhoneNumber(newValue);
            }
        };

        /**
         *
         * @return
         *     The otherNumber
         */
        public String getOtherNumber() {
            return otherNumber;
        }

        /**
         *
         * @param otherNumber
         *     The otherNumber
         */
        public void setOtherNumber(String otherNumber) {
            setAtomicOtherPhoneNumber(otherNumber);
            notifyPropertyChanged(BR.phoneNumber);
        }

        public void setAtomicOtherPhoneNumber(String basic) {
            this.otherNumber = basic;
        }

        public TextWatcher onOtherPhoneNumberChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"otherphone", newValue);
                setAtomicOtherPhoneNumber(newValue);
            }
        };

        /**
         * 
         * @return
         *     The address
         */
        @Bindable
        public String getAddress() {
            return address;
        }

        /**
         * 
         * @param address
         *     The address
         */
        public void setAddress(String address) {
            setAtomicAddress(address);
            notifyPropertyChanged(BR.phoneNumber);
        }

        public void setAtomicAddress(String basic) {
            this.address = basic;
        }

        public TextWatcher onAddresChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"address", newValue);
                setAtomicAddress(newValue);
            }
        };

        @BindingAdapter({"bind:email"})
        public static void checkEmail(EditText editText, String email) {
            if (editText != null) {
                editText.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    }

                    @Override
                    public void afterTextChanged(Editable editable) {
                        if (editText.length() > 0) {
                            if (!Utils.emailMatchPattern(editText.getText().toString())) editText.setError("Email Requried");
                        }
                    }
                });
            }
        }
    }

當我這樣做時。 Outlet outlet = new Outlet(); 並將其分配給我的綁定數據,例如binding.setOutlet(outlet); 我不會有任何錯誤。 但是,如果我這樣做:

Outlet outlet = gson.fromJson(realmOutlet.getPayload(), Outlet.class);
binding.setOutlet(outlet);

我收到NPE Error並基於NPE,這不是因為數據不存在。 就像adapters尚未初始化一樣。 我知道它一直指向addressField因為這是第一項。 這是地址的adapter 這是一個抽象類。 所以,我很困惑他們為什么不初始化:

 public TextWatcher onAddresChanged = new SimpleTextWatcher() {
            @Override
            public void onTextChanged(String newValue) {
                Log.e(TAG+"address", newValue);
                setAtomicAddress(newValue);
            }
        };

以下是我的Log我無法跟蹤日志以確切了解要調試的內容。 但是,可以這樣說,將自身附加到Interface method的視圖為null。 就像Binding Layouts尚未初始化一樣。 那么,為什么用空數據初始化它卻能正常工作?

還有我的onCreate代碼

     @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_create);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_create);
        realm = RealmUtils.getRealmInstance(getApplicationContext());

        setSupportActionBar(binding.createToolbar);
        action = getIntent().getStringExtra("action");

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            initAutoCompletedTexts();
            if (action != null) {
                if (action.equals("create")) {
                    getSupportActionBar().setTitle(R.string.create);
                    outlet = new Outlet();
                    outlet.setShopkeeper(shopkeeper);
                    binding.setOutlet(outlet);
                } else {
                    getSupportActionBar().setTitle(R.string.update);
                    binding.saveBtn.setText("UPDATE");
                    initUpdateSpcific();

                }
            }
        }

        //createBinding.setCustomer(outlet);
        binding.saveBtn.setOnClickListener(view -> {
            save();
        });
    }

有幾件事要注意:

1)初始化的工作方式如下:

Outlet outlet = new Outlet();

2)分配一個值:

Outlet outlet = gson.fromJson(realmOutlet.getPayload(), Outlet.class);

為了保持數據綁定,您必須進行初始化,然后相應地更新數據。

因此,您必須同時進行兩種操作,但要采用結構化的方式,即

Outlet outlet = new Outlet();
    Outlet outlet = gson.fromJson(realmOutlet.getPayload(), Outlet.class);      
    binding.setOutlet(outlet);

以及隨后的更新:分配值和setOutlet

outlet = gson.fromJson(realmOutlet.getPayload(), Outlet.class);
    binding.setOutlet(outlet);

更新

這僅是回答您的問題以及我們在評論中進行的聊天的后續內容,以便其他人可以參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM