【发布时间】:2018-06-08 01:56:46
【问题描述】:
场景:
我有一个HomePageProductAdapter 用于其他适配器(HomePageProductSliderAdapter 和HomePageHotDealsSliderAdapter)。
主页面有Regular products和Hot products两个RecyclerView;其中有一些产品在两个列表中是相同的。例如在第一个列表中,有product1、product2、product3和product4;而在第二个列表中,有product1 和product5。
问题:
当前显示在屏幕上的项目不会在另一个列表中刷新。例如,当我在第一个列表中增加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 的评论:
我将所有本地产品变量更改为 a 全局变量,如下所示:
private Product productRealm;
并更改了onBindViewHolder、inc_CountButton 和dec_CountButton 范围内的where 查询,例如:
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 的引用,并在项目上注册一个调用
notifyChange的 RealmChangeListener -
@EpicPandaForce 我应该在哪里写这个
RealmChangeListener?因为我在多个列表中有多个项目。例如,构造函数上只有一个侦听器就足够了吗? -
您很可能需要在视图中注册此更改侦听器。
-
@EpicPandaForce 我在
onBindViewHolder上做了,但有时notifyChange不打电话! -
您将添加侦听器的 RealmObject 存储为字段变量,对吧?
标签: android data-binding realm android-databinding