Come mantenere la logica di navigazione delle attività abbastanza generica da essere riutilizzata in diversi flussi di lavoro

3

Strutturo la mia applicazione Android seguendo la Architettura pulita di Uncle Bob che comprende almeno almeno i seguenti livelli rilevanti: -

  • Presentazione - Utilizzo dell'approccio MVVM. Questo strato contiene le attività di Android e i corrispondenti ViewModels.
  • Interact : questo layer incapsula la logica dei casi d'uso dell'applicazione e viene chiamato da diversi ViewModels per ottenere attività specifiche per il business. Può anche mantenere lo stato che riflette lo stato di avanzamento di un'attività.

Attualmente, nella mia applicazione ci sono una serie di casi d'uso o flussi di lavoro. Ogni flusso di lavoro passerà attraverso una sequenza specifica di pagine (ad esempio Attività o Frammenti). Poiché ha solo poche pagine e flussi di lavoro, è semplicemente logico inserire esplicitamente la logica di navigazione all'interno di ciascun ViewModel. Supponiamo che ci sia un caso d'uso A che segue le seguenti attività: -

Usa il caso A [HomeActivity] --> [ActivityA] --> [ActivityB]

Immagina che AttivitàA presenti un utente con un elenco di elementi per la selezione per i quali verrà eseguito il suo intervento nella AttivitàB . Nell'attivitàA, ho semplicemente chiamato

startActivity(new Intent(this, ActivityB.class))

per navigare in ActivityB quando l'utente ha selezionato un elemento e ha già chiamato un interactor per mantenere lo stato di quale elemento è stato selezionato da un utente.

...

Ora il problema sorge, un'azienda ha bisogno di un nuovo caso d'uso B che disegna un flusso di lavoro diverso ma riutilizza la stessa ActivityA nel suo flusso di lavoro.

Usa il caso B. [HomeActivity] --> [ActivityA] --> [ActivityC]

Come puoi vedere, ora ActivityA può navigare non solo sull'attività B ma anche su ActivityC a seconda del caso d'uso a cui è stato preso parte. Mentre la maggior parte della logica in ActivityA così come la sua visualizza XML e il suo ViewModel è abbastanza generico da essere riutilizzato in entrambi i casi d'uso, la parte di navigazione no.

Come posso affrontare questo problema di navigazione in modo che il codice in ActivityA e i suoi elementi correlati sia abbastanza generico da poter essere riutilizzato in qualsiasi flusso di lavoro? Qual è la soluzione più elegante dalla tua idea?

    
posta onelaview 31.01.2017 - 16:28
fonte

3 risposte

1

Se ti capisco bene, stai scegliendo quale attività andare dopo l'attivitàA prima di iniziare l'attivitàA?

La soluzione più semplice a cui posso pensare è di ereditare dall'attivitàA e sovrascrivere un metodo come goToNextActivity (). Questo potrebbe essere un po 'difficile da capire in futuro però. Un altro potrebbe essere quello di rendere esplicito il concetto di "flusso di lavoro". Potresti nominarli e poi darlo all'attività come extra. Un'attività potrebbe quindi chiamare un metodo di utilità da qualche parte come Navigation.goToNextScreen (questo, flusso di lavoro). Il metodo di navigazione potrebbe quindi decidere dove andare dopo ogni attività in cui il flusso di lavoro e impostare anche gli extra contenenti il flusso di lavoro.

    
risposta data 01.02.2017 - 07:26
fonte
1

Vedo diversi approcci utilizzabili.

Il primo è identificare la tua attivitàB come controllo del selettore di valori e trattarla come tale. Questa cosa dovrebbe essere generica , quindi ogni comportamento dovrebbe essere configurabile dall'esterno.

Il modo più facile per rendere questa cosa riutilizzabile in diversi luoghi per ereditarietà, come, come già suggerito da @Hendrik Marx.

Quindi hai un BaseActivityB astratto e due implementazioni che sostituiscono semplicemente un metodo che chiami quando deve iniziare la navigazione.

La seconda opzione, più complessa, è di rendere ActivityB leggere alcuni parametri del bundle in onCreate e in seguito decidere in base a questi parametri, dove dovrebbe navigare.

Raccomando caldamente l'approccio dell'ereditarietà, poiché rendi i diversi usi molto espliciti. Inoltre, quando utilizzi i parametri raggruppati con Intent , significa che inserisci una grande quantità di logica di navigazione diversa in una classe (pensa al Principio di responsabilità singola ).

    
risposta data 03.03.2017 - 14:44
fonte
1

A mio parere, il "flusso di lavoro" è parte del businesslogic o di un livello proprio sopra il businisslayer ("livello di servizio").

viewModell è responsabile della comunicazione con la GUI.

Immagina di avere un negozio online che vende cibo e sigarette.

La logica del flusso di lavoro può avere una funzione booleana customerMustBeOlderThan18Years()

viewModel avrebbe un metodo getActivityIntentForNextCommand() che restituisce un intento a "ProveThatCustomerIsOlderThan18YearsActivity" se ci sono ciragretts nel carrello degli acquisti.

    
risposta data 03.04.2017 - 07:57
fonte

Leggi altre domande sui tag