場景:
我有一個使用其他適配器(HomePageProductSliderAdapter
& HomePageHotDealsSliderAdapter
)的HomePageProductAdapter
。
主頁有兩個RecyclerView for Regular產品和熱門產品;這兩個列表中有一些產品是相同的。例如在第一個列表中,有product1
,product2
,product3
和product4
;在第二個列表中,有product1
和product5
。安卓:RecyclerView的項目不通過數據綁定刷新和境界
問題:
當前顯示在屏幕上的項目不會在另一個列表中刷新。例如,當我增加第一個列表中的product1
的數量時,它不會刷新第二個列表中的數量。
詳細說明:
產品(其在使用HomePageProductAdapter
和HomeProductSliderModel
):
public class Product extends RealmObject implements Observable/*BaseObservable*/ {
@PrimaryKey
public String productId;
private String quantity = "0";
@Ignore
private transient PropertyChangeRegistry mCallbacks;
//Constructor, getters and setters
@Bindable
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
if (quantity != null && !quantity.equals("")) {
this.quantity = quantity;
notifyPropertyChanged(BR.quantity);
}
}
public synchronized void notifyChange() {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, 0, null);
}
}
public void notifyPropertyChanged(int fieldId) {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, fieldId, null);
}
}
@Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback onPropertyChangedCallback) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
mCallbacks.add(onPropertyChangedCallback);
}
@Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback onPropertyChangedCallback) {
if (mCallbacks != null) {
mCallbacks.remove(onPropertyChangedCallback);
}
}
}
HomePageProductAdapter(其在使用HomePageProductSliderAdapter
和HomePageHotDealsSliderAdapter
):
public class HomePageProductAdapter extends RecyclerView.Adapter<HomePageProductAdapter.Viewholder> {
private List<Product> productsList = new ArrayList<>();
public HomePageProductAdapter(List<Product> product) {
productsList = product;
Realm realm = null;
realm = mRealmManager.getLocalInstance();
for(final Product prd: productsList)
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(@NonNull Realm realm) {
Product productRealm = realm.where(Product.class).equalTo(ProductFields.PRODUCT_ID, prd.getProductId()).findFirst();
if (productRealm == null) {
realm.insert(prd);
}
}
});
}
@Override
public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) {
HomeProductItemBinding item = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.home_product_item, parent, false);
return new Viewholder(item);
}
@Override
public void onBindViewHolder(final Viewholder holder, final int position) {
final Product productIns = productsList.get(holder.getAdapterPosition());
Realm realm = null;
realm = mRealmManager.getLocalInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(@NonNull Realm realm) {
Product productRealm = realm.where(Product.class).equalTo(ProductFields.PRODUCT_ID, productIns.getProductId()).findFirst();
if (productRealm == null) {
productRealm = realm.createObject(Product.class, productIns.getProductId());
}
if (productRealm != null) {
if (productRealm.getQuantity() == null || productRealm.getQuantity().equalsIgnoreCase("0")) {
holder.HomeProductBindGrid.strCount.setText("0"); //And I'm wondering why should I use set value manually, when there is holder.HomeProductBindGrid.setProd
productRealm.setQuantity("0");
}
else {
holder.HomeProductBindGrid.strCount.setText(String.valueOf(productRealm.getQuantity()));
}
}
holder.HomeProductBindGrid.setProd(productRealm); // I'm using this line and android:text="@{prod.quantity}" in the XML, why should I set the values manually?!
holder.HomeProductBindGrid.executePendingBindings();
}
});
holder.HomeProductBindGrid.inc_CountButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Product productIns = productsList.get(holder.getAdapterPosition()); //Which one should I use?! -> //holder.HomeProductBindGrid.getProd(); //productsList.get(position); //productsList.get(holder.getAdapterPosition());
Realm realm = null;
realm = mRealmManager.getLocalInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(@NonNull Realm realm) {
Product productRealm = realm.where(Product.class).equalTo(ProductFields.PRODUCT_ID, productIns.getProductId()).findFirst();
if (productRealm == null) {
productRealm = realm.createObject(Product.class, productIns.getProductId());
}
if (productRealm != null) {
if (productRealm.getQuantity() == null || productRealm.getQuantity().equalsIgnoreCase("0")) {
productRealm.setQuantity("1");
holder.HomeProductBindGrid.strCount.setText(String.valueOf(productRealm.getQuantity()));
}
else {
productRealm.setQuantity(String.valueOf(Integer.valueOf(productRealm.getQuantity()) + 1));
holder.HomeProductBindGrid.strCount.setText(String.valueOf(productRealm.getQuantity()));
}
holder.HomeProductBindGrid.setProd(productRealm);
holder.HomeProductBindGrid.executePendingBindings();
}
}
});
}
});
}
class Viewholder extends RecyclerView.ViewHolder {
HomeProductItemBinding HomeProductBindGrid;
ItemListBinding ItemListBindList;
Viewholder(HomeProductItemBinding binding) {
super(binding.getRoot());
this.HomeProductBindGrid = binding;
}
}
}
HomeProductSliderModel(其在使用HomePageProductSliderAdapter
和HomePageHotDealsSliderAdapter
):
public class HomeProductSliderModel extends BaseObservable{
//I extended this model from BaseObservable, in the hope that the other lists refresh, but didn't make any different.
private List<Product> productList;
public HomeProductSliderModel(List<Product> productList) {
this.productList = productList;
}
@NonNull
@Bindable
public List<Product> getProductList() {
return productList;
}
public void setProductList(List<Product> productList) {
//I don't know where should I use it (Like setQuantity in HomePageProductAdapter?!
this.productList = productList;
//notifyChange();
notifyPropertyChanged(BR.productList);
}
@Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
super.addOnPropertyChangedCallback(callback);
}
@Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
super.removeOnPropertyChangedCallback(callback);
}
@Override
public void notifyChange() {
super.notifyChange();
}
@Override
public void notifyPropertyChanged(int fieldId) {
super.notifyPropertyChanged(fieldId);
}
}
HomePageProductSliderAdapter(在MainActivity
使用哪個):
public class HomePageProductSliderAdapter extends RecyclerView.Adapter<HomePageProductSliderAdapter.Holder> {
private List<HomeProductSliderModel> mHomeProductSliderModels;
public HomePageProductSliderAdapter(List<HomeProductSliderModel> homeProductSliderModels, int screenWidth) {
mHomeProductSliderModels = homeProductSliderModels;
}
@Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
ProductSliderBinding bind = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.product_slider, parent, false);
return new Holder(bind);
}
@Override
public void onBindViewHolder(Holder holder, int position) {
HomeProductSliderModel homeProductSliderModel = mHomeProductSliderModels.get(holder.getAdapterPosition());
holder.bindHomeProduct(homeProductSliderModel);
}
@Override
public int getItemCount() {
return mHomeProductSliderModels.size();
}
class Holder extends RecyclerView.ViewHolder {
ProductSliderBinding productSliderBind;
Holder(ProductSliderBinding binding) {
super(binding.getRoot());
productSliderBind = binding;
}
public void bindHomeProduct(@NonNull HomeProductSliderModel homeProductSlider) {
productSliderBind.setHomeProductSlider(homeProductSlider);
productSliderBind.executePendingBindings();
productSliderBind.productRecycler.setAdapter(new HomePageProductAdapter(/*mHomeProductSliderModels.get(position)*/homeProductSlider.getProductList()));
productSliderBind.executePendingBindings();
}
}
}
HomePageHotDealsSliderAdapter(在MainActivity
使用哪個):
public class HomePageHotDealsSliderAdapter extends RecyclerView.Adapter<HomePageHotDealsSliderAdapter.Holder> {
private List<HomeProductSliderModel> mHomeProductSliderModels;
public HomePageHotDealsSliderAdapter(List<HomeProductSliderModel> homeProductSliderModels) {
mHomeProductSliderModels = homeProductSliderModels;
}
@Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
HomeHotDealsItemBinding bind = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.home_hot_deals_item, parent, false);
return new Holder(bind);
}
@Override
public void onBindViewHolder(Holder holder, int position) {
HomeProductSliderModel homeProductSliderModel = mHomeProductSliderModels.get(holder.getAdapterPosition());
holder.bindHomeProduct(homeProductSliderModel);
}
@Override
public int getItemCount() {
return mHomeProductSliderModels.size();
}
class Holder extends RecyclerView.ViewHolder {
HomeHotDealsItemBinding homeHotDealsItemBind;
Holder(HomeHotDealsItemBinding binding) {
super(binding.getRoot());
homeHotDealsItemBind = binding;
}
public void bindHomeProduct(@NonNull HomeProductSliderModel homeProductSlider) {
homeHotDealsItemBind.setHomeHotProductSlider(homeProductSlider);
homeHotDealsItemBind.executePendingBindings();
homeHotDealsItemBind.recyclerView.setAdapter(new HomePageProductAdapter(mContext, /*mHomeProductSliderModels.get(position)*/homeProductSlider.getProductList(), screenWidth, true));
homeHotDealsItemBind.executePendingBindings();
}
}
}
home_product_item.xml(在HomePageProductAdapter
使用):
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:apps="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="prod"
type="com.see.core_app.Model.Product" />
</data>
...
<TextView
android:id="@+id/str_count"
android:text="@{prod.quantity}"/>
<Button
android:id="@+id/inc_CountButton"/>
...
</layout>
product_slider.xml(在HomePageProductSliderAdapter
使用):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View" />
<variable
name="homeProductSlider"
type="com.see.core_app.Model.HomeProductSliderModel" />
</data>
...
<android.support.v7.widget.RecyclerView
android:id="@+id/product_recycler"/>
...
</layout>
home_hot_deals_item。XML(在HomePageHotDealsSliderAdapter
使用):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="homeHotProductSlider"
type="com.see.core_app.Model.HomeProductSliderModel" />
</data>
...
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"/>
...
</layout>
更新上@ EpicPandaForce的評論:
我改變了所有本地產品變量來一個全局變量,象下面這樣:
private Product productRealm;
並更改where
查詢onBindViewHolder
,inc_CountButton
和dec_CountButton
範圍,如:
productRealm = realm.where(Product.class).equalTo(ProductFields.PRODUCT_ID, productIns.getProductId()).findFirst();
而且對onBindViewHolder
範圍的底部寫RealmChangeListener
:
@Override
public void onBindViewHolder(final Viewholder holder, final int position) {
productRealm = realm.where ...
realm.executeTransaction(new Realm.Transaction() {
...
});
productRealm.addChangeListener(new RealmChangeListener<RealmModel>() {
@Override
public void onChange(RealmModel realmModel) {
Product localProductRealm = (Product) realmModel;
if (localProductRealm.getQuantity() == null || localProductRealm.getQuantity().equalsIgnoreCase("0")) {
holder.HomeProductBindGrid.strCount.setText("0");
} else {
holder.HomeProductBindGrid.strCount.setText(String.valueOf(productRealm.getQuantity()));
}
((Product) realmModel).notifyChange();
}
});
}
但有時,notifyChange
不叫!
您需要保留對RealmObject的引用,並且還要註冊一個RealmChangeListener,它可以調用該項目上的'notifyChange' – EpicPandaForce
@EpicPandaForce我應該在哪裏寫這個'RealmChangeListener'?原因我在多個列表中有多個項目。例如,是否只有一個構造函數的監聽者? –
您很可能需要在視圖中註冊此更改偵聽器。 – EpicPandaForce