2017-02-27 61 views
7

Tıklamalar biriktirecek ve kullanıcı 1 saniye boyunca bu düğmeyi tıklattığında bir olayı tetikleyecek bir Özel ImageButton oluşturmaya çalışıyorum.RxJava2 debounce işlevi düzgün çalışmayan RecyclerView - Android

Bunu başarmak için geridönüş işlevini kullandım.

özel ımagebutton:

public class MBImageButton extends ImageButton { 

    private AtomicInteger mCounter; 
    private Disposable mDisposable; 
    private Observable<Object> observable; 
    private OnAccumulatedRequestsRead mOnAccumulatedRequestsRead; 
    private OnEverClickListener mOnEverClickListener; 
    private int emitEveryMilli = 1000; // every 1 second by default 
    private boolean shouldDisposeOnDetachFromWindow = true; 

    public MBImageButton(Context context) { 
     super(context); 
     init(); 
    } 

    public MBImageButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public MBImageButton(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    public void setAccumulatedClickListeners(OnEverClickListener onEverClickListener, 
              OnAccumulatedRequestsRead onAccumulatedRequestsRead) { 
     setOnAccumulatedRequestsRead(onAccumulatedRequestsRead); 
     setOnEverClickListener(onEverClickListener); 
     initClickObservable(); 
     subscribe(); 
    } 

    private void initClickObservable() { 
     observable = Observable.create(emitter -> { 
      emitter.setCancellable(() -> setOnClickListener(null)); 
      try { 
       setOnClickListener(view -> { 
        try { 
         final int currentCount = mCounter.incrementAndGet(); 
         Timber.d("Clicked: " + currentCount); 
         if (mOnEverClickListener != null) { 
          mOnEverClickListener.onEveryClickListener(currentCount); 
         } 
         emitter.onNext(new Object()); 
        } catch (Exception e) { 
         emitter.onError(e); 
        } 
       }); 
      } catch (Exception e) { 
       emitter.onError(e); 
      } 
     }).doOnSubscribe(disposable -> mDisposable = disposable) 
           .debounce(emitEveryMilli, TimeUnit.MILLISECONDS); 
    } 

    private void subscribe() { 
     observable.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(o -> { 
        try { 
         final int count = mCounter.get(); 
         if(count==0) return; 
         mCounter.set(0); 
         Timber.d("Accumulated Clicks: " + count); 
         if (mOnAccumulatedRequestsRead != null) { 
          mOnAccumulatedRequestsRead.onAccumulatedRequestsReady(count); 
         } 
        } catch (Exception e) { 
         Timber.e(e); 
        } 
       }, Timber::e); 
    } 

    private void init() { 
     mCounter = new AtomicInteger(0); 
    } 

    public void disposeAccumulatedClickListeners() { 
     if (mDisposable != null) { 
      mDisposable.dispose(); 
     } 
    } 

    public void shouldDisposeOnDetachFromWindow(boolean shouldDisposeOnDetachFromWindow) { 
     this.shouldDisposeOnDetachFromWindow = shouldDisposeOnDetachFromWindow; 
    } 

    public void setEmitEveryMilliseconds(int emitEveryMilli) { 
     this.emitEveryMilli = emitEveryMilli; 
     initClickObservable(); 
     subscribe(); 
    } 

    private void setOnEverClickListener(OnEverClickListener onEverClickListener) { 
     mOnEverClickListener = onEverClickListener; 
    } 

    private void setOnAccumulatedRequestsRead(OnAccumulatedRequestsRead onAccumulatedRequestsRead) { 
     mOnAccumulatedRequestsRead = onAccumulatedRequestsRead; 
    } 

    @Override 
    protected void onDetachedFromWindow() { 
     super.onDetachedFromWindow(); 
     if (shouldDisposeOnDetachFromWindow) { 
      if (mDisposable != null) { 
       mDisposable.dispose(); 
      } 
     } 
    } 

    public interface OnAccumulatedRequestsRead { 
     void onAccumulatedRequestsReady(int count); 
    } 

    public interface OnEverClickListener { 
     void onEveryClickListener(int currentCount); 
    } 
} 

fonksiyon zıplamaölçer için bu ımagebutton setup:

setAccumulatedClickListeners(OnEverClickListener, OnAccumulatedRequestsRead) 

Ben kurulum RecyclerView üzerinden bu görünüm, her şey düzgün çalışıyorsa

,

sonuç olarak sırayla 9 defa tıklandığında şöyle olur:

01 ikisinde de

D/MBImageButton: Clicked: 1 
D/MBImageButton: Clicked: 2 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Clicked: 3 
D/MBImageButton: Clicked: 2 
D/MBImageButton: Clicked: 4 
D/MBImageButton: Clicked: 3 
D/MBImageButton: Accumulated Clicks: 4 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Accumulated Clicks: 3 
D/MBImageButton: Accumulated Clicks: 1 
D/MBImageButton: Accumulated Clicks: 0 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Accumulated Clicks: 1 
D/MBImageButton: Accumulated Clicks: 0 
D/MBImageButton: Accumulated Clicks: 0 
D/MBImageButton: Accumulated Clicks: 0 

: Bu yine 9 sıralı tıklamaları için farklı sonucudur

D/MBImageButton: Clicked: 1 
D/MBImageButton: Clicked: 2 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Clicked: 3 
D/MBImageButton: Clicked: 2 
D/MBImageButton: Clicked: 4 
D/MBImageButton: Accumulated Clicks: 4 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Accumulated Clicks: 2 
D/MBImageButton: Clicked: 2 
D/MBImageButton: Accumulated Clicks: 2 
D/MBImageButton: Accumulated Clicks: 0 
D/MBImageButton: Clicked: 1 
D/MBImageButton: Accumulated Clicks: 1 
D/MBImageButton: Accumulated Clicks: 0 
D/MBImageButton: Accumulated Clicks: 0 

: Ben RecyclerView ViewHolder Bu özel ımagebutton eklediğinizde

sonuç tıklama aynı sayıda doğru değil Aynı aralıklarla tıklattığım zamanlar, Ama bu düğme RecyclerView'a eklendiğinde garip bir sonuç verir.

Sorun ne olabilir?

Güncelleme:

Benim Adaptör basitleştirilmiş uygulama: Ben RecyclerView Adapter kaydırma yaparken asıl sorun çözüm

var

public class ProductRVAdapter extends BaseProductRVAdapter<ProductRVAdapter.ProductVH> { 

    private ProductAdapterListener mProductAdapterListener; 

    public ProductRVAdapter(List<Product> productList, ProductAdapterListener productAdapterListener) { 
     super(productList); 
     mProductAdapterListener = productAdapterListener; 
    } 

    @Override 
    public ProductVH onCreateViewHolder(ViewGroup parent, int viewType) { 
     final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_product, parent, false); 
     return new ProductVH(view); 
    } 

    @Override 
    public void onBindViewHolder(ProductVH holder, int position) { 
     holder.bind(productList.get(position), position); 

     holder.ib_decrease.setAccumulatedClickListeners(currentCount -> onProductAdapterDecreaseClicked.onClick(holder.ib_decrease), 
       count -> { 
        if (mProductAdapterListener != null) { 
         mProductAdapterListener.onProductAdapterProductChangeToWSListener(productList.get(position), position, -count); 
        } 
       }); 

     holder.ib_add.setAccumulatedClickListeners(currentCount -> onProductAdapterAddToCartClicked.onClick(holder.ib_add), 
       count -> { 
        if (mProductAdapterListener != null) { 
         mProductAdapterListener.onProductAdapterProductChangeToWSListener(productList.get(position), position, count); 
        } 
       }); 
    } 

    public interface ProductAdapterListener { 

     void onProductAdapterAddToCartClicked(Product product, int position); 

     void onProductAdapterProductChangeToWSListener(Product product, int position, int amountChanged); 

     void onProductAdapterDecreaseClicked(Product product, int position); 
    } 

    public static class ProductVH extends RecyclerView.ViewHolder { 
     @BindView(R.id.iv_productImage) 
     ImageView iv_producImage; 
     @BindView(R.id.tv_productName) 
     TextView tv_productName; 
     @BindView(R.id.tv_prodAmount) 
     MBTextView tv_prodAmount; 

     @BindView(R.id.ib_decrease) 
     MBImageButton ib_decrease; 
     @BindView(R.id.ib_add) 
     MBImageButton ib_add; 

     ProductVH(View itemView) { 
      super(itemView); 
      ButterKnife.bind(this, itemView); 
     } 


     public void bind(Product product, int position) { 
      tv_productName.setText(product.getName()); 
      tv_prodAmount.setText(product.getAmount()); 

      ImageLoader.loadImage(iv_producImage.getContext(), iv_producImage, product.getImg(), R.drawable.ic_category_item); 

      ib_decrease.setTag(position); 
      ib_add.setTag(position); 
     } 
    } 
} 
+0

Bağdaştırıcı uygulamanızı gösterebilir misiniz? – azizbekian

+0

@azizbekian Bağdaştırıcı uygulamasını ekledim – MBH

+0

Ben muhtemelen 'BaseProductRVAdapter' içinde olan getItemCount() 'uygulamasını göremiyorum. Kaç ürün var? – azizbekian

cevap

4

, VIES müstakil olsun pencereden vefonksiyonunda onDetachedFromWindow fonksiyonu çağrılır. Gözlemlenebilir.

çözeltiler çalıştı:

1. I attachFunction

ilave
@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 
    if (shouldDisposeOnDetachFromWindow) { 
     if (mDisposable != null) { 
      if (mDisposable.isDisposed()) { 
       initClickObservable(); 
       subscribe(); 
      } 
     } 
    } 
} 

2. kaldırıldı notifyItemChanged (konum)

Genellikle kullanıyorum bir modifikasyon sonrası görünümü güncelleştirmek aramaları notifyItemChange(). Şimdi görünümü doğrudan setText veya benzer işlevlerle güncelliyorum.

Şimdi düzgün çalışıyor.