场景:
我有一个在其他适配器(HomePageProductAdapter
和HomePageProductSliderAdapter
)中使用的HomePageHotDealsSliderAdapter
。
主页上有两个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的评论更新:
我将所有本地产品变量更改为如下所示的全局变量:
private Product productRealm;
并在
where
,onBindViewHolder
和inc_CountButton
范围上更改了dec_CountButton
查询,例如:productRealm = realm.where(Product.class).equalTo(ProductFields.PRODUCT_ID, productIns.getProductId()).findFirst();
并在
RealmChangeListener
范围的底部写了onBindViewHolder
:@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
不会调用! 最佳答案
如果不使用RealmRecyclerViewAdapter
,我将无法解决此问题。
解:
主页产品适配器:
public HomePageProductAdapter(@Nullable OrderedRealmCollection<Product> data, boolean autoUpdate, boolean updateOnModification) {
super(data, autoUpdate, updateOnModification);
setHasStableIds(true);
}
将
implementation 'io.realm:android-adapters:2.1.1'
添加到应用程序的build.gradle
删除所有
realm.where
查询,但删除onBindViewHolder
删除所有
holder.HomeProductBindGrid.setProd(productRealm);
绑定,但onBindViewHolder
将
HomeProductSliderModel
构造函数更改为public HomeProductSliderModel(String title, OrderedRealmCollection<Product> productList) {
附言:
唯一剩下的问题是,该项目在每次通知更改时都会闪烁两次。