安卓:RecyclerView的项目不通过数据绑定刷新和境界

场景:
我有一个使用其他适配器(HomePageProductSliderAdapter & HomePageHotDealsSliderAdapter)的HomePageProductAdapter
主页有两个RecyclerView for Regular产品和热门产品;这两个列表中有一些产品是相同的。例如在第一个列表中,有product1,product2,product3product4;在第二个列表中,有product1product5。安卓:RecyclerView的项目不通过数据绑定刷新和境界

问题:
当前显示在屏幕上的项目不会在另一个列表中刷新。例如,当我增加第一个列表中的product1的数量时,它不会刷新第二个列表中的数量。

详细说明:

产品(其在使用HomePageProductAdapterHomeProductSliderModel):

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(其在使用HomePageProductSliderAdapterHomePageHotDealsSliderAdapter):

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(其在使用HomePageProductSliderAdapterHomePageHotDealsSliderAdapter):

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查询onBindViewHolderinc_CountButtondec_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

回到顶部