安卓:RecyclerView的项目不通过数据绑定刷新和境界
场景:
我有一个使用其他适配器(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
不叫!
回答:
如果不使用RealmRecyclerViewAdapter
,我无法解决此问题。
解决方案:
HomePageProductAdapter:
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) {
P.S:
唯一的问题仍然是该项目从每通知更改闪烁两次。
以上是 安卓:RecyclerView的项目不通过数据绑定刷新和境界 的全部内容, 来源链接: utcz.com/qa/264922.html