[英]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.