rxkotlin rxjava2 rxjava rxandroid qué métodos example español componen android android-recyclerview rx-java rx-android

rxandroid - rxjava2 android español



Cómo manejar Clics de Artículo para una vista de reciclador usando RxJava (4)

Me interesó averiguar cuál es la mejor manera de responder a un clic de elemento de una vista de reciclador.

Normalmente agregaría un oyente onclick () al ViewHolder y devolvería los resultados a la actividad / fragmento a través de una interfaz.

Pensé en agregar un Observable en el onBindViewHolder pero no quiero crear un nuevo Observable para cada enlace de artículo.


Paso 1: trasladar la lógica comercial de las actividades a clases / servicios de dominio

Opcional: utilice https://github.com/roboguice/roboguice para conectar fácilmente sus servicios entre sí.

Paso 2: @Inject (o simplemente configure) su servicio en su adaptador

Paso 3: agarre https://github.com/JakeWharton/RxBinding y use los super poderes en su adaptador:

RxView.clicks(button).subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { myCoolService.doStuff(); } });

Paso 4: obtenga un fallo de tiempo de ejecución y aprenda a manejar suscripciones

Paso 5: GANANCIA :)


Le sugiero que haga con su aproximación inicial de un elemento observable por clic, pero para evitar crear un nuevo observable cada vez puede simplemente almacenar en caché los elementos emitidos la primera vez que utiliza el caché.

/** * Here we can prove how the first time the items are delayed 100 ms per item emitted but second time becuase it´s cached we dont have any delay since * the item emitted are cached */ @Test public void cacheObservable() { Integer[] numbers = {0, 1, 2, 3, 4, 5}; Observable<Integer> observable = Observable.from(numbers) .doOnNext(number -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }) .cache(); long time = System.currentTimeMillis(); observable.subscribe(System.out::println); System.out.println("First time took:" + (System.currentTimeMillis() - time)); time = System.currentTimeMillis(); observable.subscribe(System.out::println); System.out.println("Second time took:" + (System.currentTimeMillis() - time)); }


Mi solución era muy parecida a la de @epool, excepto el modelo EventBus.

Primero, crea un RxBus: RxBus.java

public class RxBus { private final Subject<Object, Object> _bus = new SerializedSubject<>(PublishSubject.create()); public void send(Object o) { _bus.onNext(o); } public Observable<Object> toObserverable() { return _bus; } public boolean hasObservers() { return _bus.hasObservers(); } }

Entonces, tienes dos formas de usar RxBus. Cree su clase de aplicación personalizada con la referencia RxBus o cree RxBus en Activity / Fragment y luego páselo al adaptador. Yo uso el primero.

MyApp.java

public class MyApp extends Application { private static MyApp _instance; private RxBus _bus; public static MyApp get() { return _instance; } @Override public void onCreate() { super.onCreate(); _instance = this; _bus = new RxBus(); } public RxBus bus() { return _bus; } }

luego usa

MyApp.get().bus()

para obtener la instancia de RxBus.

El uso de RxBus en Adpater fue así:

public class MyRecyclerAdapter extends ... { private RxBus _bus; public MykRecyclerAdapter (...) { .... _bus = MyApp.get().bus(); } public ViewHolder onCreateViewHolder (...) { _sub = RxView.longClicks(itemView) // You can use setOnLongClickListener as the same .subscribe(aVoid -> { if (_bus.hasObservers()) { _bus.send(new SomeEvent(...)); } }); } }

Puede enviar cualquier clase con _bus.send (), que recibiremos en la Actividad:

RxBus bus = MyApp.get().bus(); // get the same RxBus instance _sub = bus.toObserverable() .subscribe(e -> doSomething((SomeEvent) e));

Acerca de darse de baja

En MyRecyclerAdapter llame a _sub.unsubscribe () en los métodos clearup () y llame a _sub.unsubscribe () en Activity onDestory ().

@Override public void onDestroy() { super.onDestroy(); if (_adapter != null) { _adapter.cleanup(); } if (_sub != null) { _sub.unsubscribe() } }


Puede usar RxBinding y luego crear un sujeto dentro de su adaptador, luego redireccionar todos los eventos a ese sujeto y simplemente crear un getter del sujeto para que actúe como un observable y finalmente solo suscribirse en ese observable.

private PublishSubject<View> mViewClickSubject = PublishSubject.create(); public Observable<View> getViewClickedObservable() { return mViewClickSubject.asObservable(); } @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup pParent, int pViewType) { Context context = pParent.getContext(); View view = (View) LayoutInflater.from(context).inflate(R.layout.your_item_layout, pParent, false); ViewHolder viewHolder = new ViewHolder(view); RxView.clicks(view) .takeUntil(RxView.detaches(pParent)) .map(aVoid -> view) .subscribe(mViewClickSubject); return viewHolder; }

Un ejemplo de uso podría ser:

mMyAdapter.getViewClickedObservable() .subscribe(view -> /* do the action. */);