HomePageHotDealsSliderAdapter

HomePageHotDealsSliderAdapter

场景:
我有一个在其他适配器(HomePageProductAdapterHomePageProductSliderAdapter)中使用的HomePageHotDealsSliderAdapter
主页上有两个RecyclerView,分别用于常规产品和热门产品。这两个列表上有一些相同的产品。例如,在第一个列表中,有product1product2product3product4;在第二个列表中,有product1product5

问题:
当前在屏幕上显示的项目不会在另一个列表中刷新。例如,当我增加第一个列表中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;


并在whereonBindViewHolderinc_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) {


附言:
唯一剩下的问题是,该项目在每次通知更改时都会闪烁两次。

10-07 19:34