android - rxkotlin - rxjava



rx android vs mosby motif données de chargement recyclerview (2)

Mosby est une bibliothèque M odel- V iew- P resenter (MVP). Donc, le modèle que vous appelez "ted mosby pattern" est en réalité MVP.

Mais vous n'avez pas compris ce qu'est MVP. Il ne s'agit pas de conserver des courses asynchrones, même si cela pourrait être réalisé avec Mosby. MVP concerne la séparation des préoccupations. La vue affiche uniquement les éléments de l'interface utilisateur, Presenter contrôle la vue, c'est-à-dire que le présentateur indique la vue: affiche maintenant la progression diaolog, cache maintenant la boîte de dialogue de progression, etc. Le modèle pourrait être une tâche asynchrone ou un observable RxJava. Le présentateur récupère le résultat et indique à la vue de l'afficher. Votre code est découplé en 3 couches Modèle (également appelé logique métier) et Presenter et View. L'avantage est que vous pouvez modifier la vue (c'est-à-dire remplacer la boîte de dialogue de progression par un widget de barre de progression) sans toucher à aucun code chargé de données (Presenter et logique métier). De plus, avec MVP, votre code devient testable.

Donc, ce que vous devriez comparer est: Dois-je utiliser AsyncTask ou RxJava pour le chargement des données. Avec Mosby, vous exécutez votre requête http dans le présentateur. Lorsque les changements d'orientation sont effectués, le présentateur n'est pas détruit (et donc la tâche d'arrière-plan n'est pas annulée).

Cependant, MVP n'est pas la solution pour tout. Si vous devez vous assurer qu'un seul appel http est correctement exécuté (c'est-à-dire vous inscrire à une communauté), vous devriez penser à utiliser un service android.

Je travaille sur une application Android. Le code que j'attache crée un recyclerview. La toute première chose que nous faisons est de créer un asynctask qui récupèrerait des données sur une base de données SQLite et le chargerait dans l'adaptateur-> recylcerview. Pendant que la tâche d'arrière-plan fonctionne, un dialogue de progression est montré à l'utilisateur.

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);
    }

}

}

Jusqu'ici tout va bien. Cependant, comme vous le savez probablement, ce code a des problèmes bien connus; par exemple, si je fais tourner l'écran pendant que asynctask fait sa magie, il va planter l'application.

J'ai essayé une alternative que j'ai vu Google, rxandroid .

(Désolé si j'ai tapé quelque chose de mal, je le fais de mémoire)

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();
}

}

Maintenant, l'application ne plante plus lorsque je fais pivoter l'écran. Cependant, l'observable continue à travailler sur l'arrière-plan jusqu'à ce qu'il se termine, mais comme je me désinscris pour éviter l'écrasement, je ne reçois pas les résultats correctement. De plus, la barre de progression disparaît même si l'observable continue de fonctionner comme je l'ai mentionné.

A la recherche d'une solution, j'ai trouvé qu'il y avait un motif appelé "Ted Mosby" qui semble résoudre mon problème. Bien que cela semble prometteur, je pense que c'est trop coder pour quelque chose que je pensais que cela ne vaut pas la peine et que rxandroid peut avoir une solution de contournement.

Donc, ma question est comment puis-je obtenir ce que je veux sans être immergé dans un désordre architectural de codage trop grand pour mon but? Pourriez-vous donner un exemple si vous avez résolu ce problème? Pensez-vous que je me trompe et que je devrais implémenter le modèle TedMosby?


Answer #1

Votre Observable devrait gérer lui-même le fait de la désinscription. Il y a deux mécanismes pour cela:

  • vérifiez subscriber.isUnsubscribed . Vous pouvez le faire entre ou après les étapes "lourdes"
  • ajouter un rappel de désinscription. Vous pouvez l'utiliser pour arrêter les opérations longues, libérer des ressources, etc.

Jetez un oeil à ce code:

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() {
            }
        })

Vous ne devriez pas faire référence à votre boîte de dialogue activité / contexte / progrès etc dans Observable . A la place, utilisez doOnSubscribe si vous voulez faire des effets secondaires.





rx-android