viewtype viewholder recyclerview que practices implement best android design-patterns android-asynctask android-recyclerview rx-android

viewholder - rx android vs mosby pattern load data recyclerview



recyclerview viewholder android (3)

Mosby es una biblioteca M odel-View- P resenter (MVP). Entonces el patrón que llamas "ted mosby pattern" es en realidad MVP.

Pero no has entendido de qué se trata MVP. No se trata de retener las tomas de ejecución asíncronas, aunque esto podría lograrse con Mosby. MVP trata sobre la separación de preocupaciones. La vista solo muestra elementos de la interfaz de usuario, el presentador controla la vista, es decir, el presentador le dice a la vista: ahora muestra el dialogo de progreso, ahora oculta el diálogo de progreso, etc. En otras palabras, el presentador controla el estado de la vista. El Modelo podría ser una tarea asíncrona o un RxJava Observable. El presentador recupera el resultado y le dice a la vista que lo muestre. Su código está desacoplado en 3 capas Modelo (también llamado lógica comercial) y Presentador y Vista. La ventaja es que puede cambiar la vista (es decir, reemplazar el diálogo de progreso con un widget de la barra de progreso) sin tocar ningún código que cargue datos (Presenter y lógica comercial). Además, con MVP tu código se puede probar.

Entonces, lo que debes comparar es: ¿Debería usar AsyncTask o RxJava para cargar datos? Con Mosby ejecutarías tu solicitud http en el presentador. Mientras se realizan los cambios de orientación, el presentador no se destruye (y, por lo tanto, la tarea de fondo no se cancela).

Sin embargo, MVP no es la solución para todo. Si tiene que asegurarse de que se ejecuta correctamente una sola llamada http (es decir, registrarse para una comunidad), debe pensar en usar un servicio de Android.

Estoy trabajando en una aplicación de Android. El código que adjunto está creando una vista de reciclador. Lo primero que hacemos es crear una asynctask que obtenga datos en una base de datos SQLite y la cargue en el adaptador-> recylcerview. Mientras la tarea de fondo está funcionando, se muestra un diálogo de progreso al usuario.

public class HomeActivity extends AppCompatActivity { private RecyclerView recycler; private RecyclerViewAdapter adapter; private SwipeRefreshLayout swipeRefresh; private progressDialog progressDialog; // ... some code here @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... some code here createRecyclerView(); loadRecyclerView(); // ... some code here } private void loadRecyclerView() { new LoadingBackgroundTask().execute(); } private void createRecyclerView() { Context context = getApplicationContext(); recycler = (RecyclerView) findViewById(R.id.recycle_view_home); recycler.setHasFixedSize(true); RecyclerView.LayoutManager lManager = new LinearLayoutManager(context); recycler.setLayoutManager(lManager); adapter = new RecyclerViewAdapter(); recycler.setAdapter(adapter); recycler.setItemAnimator(new DefaultItemAnimator()); } private class LoadingBackgroundTask extends AsyncTask<Void, Void, List<items>> { @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = ProgressDialog.show(HomeActivity.this, getString(R.string.dialog_load_list),getString(R.string.dialog_please_wait), false, false); } @Override protected List doInBackground(Void... params) { List<items> lists; //Data Source Class ( SQLite) ListDS listDS = new ListDS(getApplicationContext()); list = listDS.getList(); return list; } @Override protected void onPostExecute(List result) { super.onPostExecute(result); //it inserts de list on recyclerview performing animation adapter.animate(result); progressDialog.dissmiss(); swipeRefresh.setRefreshing(false); recycler.scrollToPosition(0); } } }

Hasta aquí todo bien. Sin embargo, como probablemente sepa, este código tiene algunos problemas conocidos; por ejemplo, si giro la pantalla mientras asynctask hace su magia, se bloqueará la aplicación.

He probado una alternativa que he visto en Google, rxandroid .

(Perdón si escribí algo mal, lo estoy haciendo de memoria)

public class HomeActivity extends AppCompatActivity { private Subscriber suscriptor; private progressDialog progressDialog; //some code .... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); suscriptor = new Subscriber() { @Override public void onCompleted() { progressDialog.dismiss(); Log.d("SUSCRIPTOR","ON COMPLETE"); } @Override public void onError(Throwable e) { Log.d("SUSCRIPTOR","ON ERROR"); } @Override public void onNext(Object o) { adapter.animate((List<items>)o); } }; Observable.create( new Observable.OnSubscribe<List<items>>() { @Override public void call(Subscriber<? super List<items>> sub) { progressDialog = ProgressDialog.show(HomeActivity.this, getString(R.string.dialog_load_list),getString(R.string.dialog_please_wait), false, false); List<items> lists; //Data Source Class ( SQLite) ListDS listDS = new ListDS(getApplicationContext()); list = listDS.getList(); sub.onNext(list); sub.onCompleted(); } @Override protected void finalize() throws Throwable { super.finalize(); Log.d("OBSERAVBLE","FINALIZED"); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.newThread()) .cache() .subscribe(suscriptor); } @Override public void onDestroy() { if(suscriptor!=null) { if(!suscriptor.isUnsubscribed()) { suscriptor.unsubscribe(); } } super.onDestroy(); } }

Ahora la aplicación ya no se cuelga cuando giro la pantalla. Sin embargo, el observable sigue trabajando en el fondo hasta que finaliza, pero a medida que cancelo la suscripción para evitar colisiones, no recibo los resultados correctamente. Además, la barra de progreso desaparece aunque el observable sigue funcionando como mencioné.

Buscando una solución, descubrí que hay un patrón llamado "Ted Mosby" que parece resolver mi problema. Aunque parece prometedor, creo que es demasiada codificación para algo que sentí que no vale la pena y que rxandroid puede tener una solución alternativa.

Entonces, mi pregunta es ¿cómo puedo obtener lo que quiero sin sumergirme en un lío de codificación arquitectónica demasiado grande para mi propósito? ¿Podría dar un ejemplo si ustedes han resuelto esto? ¿Crees que estoy equivocado y debería implementar el patrón TedMosby?


Su Observable debe manejar el hecho al darse de baja. Hay dos mecanismos para esto:

  • check subscriber.isUnsubscribed . Puedes hacerlo entre o después de los pasos "pesados"
  • agregar devoluciones de llamada sin suscripción. Puede usarlo para detener operaciones de larga ejecución, liberar recursos, etc.

Eche un vistazo a este código:

Observable.create( new Observable.OnSubscribe<List<items>>() { @Override public void call(Subscriber<? super List<items>> sub) { sub.add(Subscriptions.create(new Action0() { @Override public void call() { cancelLongRunningOperationIfItStillRunning(); } })); if (!sub.isUnsubscribed()) { //start long running operation here } } }) .doOnSubscribe(new Action0() { @Override public void call() { } })

No debe hacer referencia a su actividad / contexto / diálogo de progreso, etc. dentro de Observable . En su lugar, use doOnSubscribe si desea hacer algunos efectos secundarios.


Lo que puedes hacer es lo que sea que hagas en actividades como AsycTask y RecyclerView , colocarlo dentro de un fragmento y, establecer la setRetainInstance(true) en el método de fragmento onCreateView() y cargar ese fragmento en tu actividad.

setRetainInstance(true) no permitirá que tu instancia de fragmento se destruya cuando se gira la pantalla.