Navegação dentro do aplicativo Android

1. Introdução


Com o desenvolvimento do Android, usamos diferentes soluções arquiteturais (padrões). Por exemplo, Mvp , Mvvm , Mvi , etc. ... Cada um desses padrões resolve vários problemas importantes e, como não são perfeitos, nos deixam alguns problemas não resolvidos. Por exemplo, essas tarefas incluem navegar dentro do aplicativo (roteamento), transferir informações de tela para tela (falando na tela, quero dizer Atividade, Fragmento ou Visualização), salvando o estado do aplicativo ao alterar a configuração (alteração na configuração).


Em nossa empresa, também enfrentamos esses problemas, alguns foram resolvidos de maneira fácil, mas o primeiro não encontrou uma solução específica, depois de tentar vários métodos para resolvê-la, escrevemos nossa própria biblioteca Flowzard .


Desafio


Em nossa empresa, usamos a arquitetura Mvp . Para ter a máxima flexibilidade ao exibir, alterar e transferir dados entre telas, tentamos seguir o princípio chamado princípio de responsabilidade única . O princípio afirma que cada módulo deve resolver um problema específico. No nosso caso, a tela deve ser isolada da tarefa global e deve resolver sua tarefa específica de mostrar / receber informações. Ele não deveria saber sobre outras telas. Para que possamos alcançar a máxima flexibilidade. Abaixo está um exemplo de configuração e uso da biblioteca.


Flowzard


Criar fluxo


class MainFlow(flowManager: FlowManager) : Flow(flowManager) { //      flow override fun onCreate(savedInstance: DataBunch?, data: DataBunch?) { super.onCreate(savedInstance, data) } } 

Criar navegador de fluxo


Os navegadores executam duas funções: criar contêineres de fluxo (atividade, fragmento, exibição) para transições entre o fluxo e telas para transições dentro do fluxo.


 class DefaultFlowNavigator(activity: AppCompatActivity) : SimpleFlowNavigator(activity){ //    flow  Activity override fun getActivityIntent(id: String, data: Any?): Intent { return when (id) { Flows.SIGN_UP -> Intent(activity, SignupActivity::class.java) else -> throw RuntimeException("Cannot find activity for id=$id") } } } 

Ajustar à atividade


Para associar Activity ao Flow, herdamos o FlowActivity e fornecemos o Navigator, no nosso caso DefaultFlowNavigator.


 class MainActivity : FlowActivity() { override val navigator: Navigator get() = DefaultFlowNavigator(this) } 

Criar FlowManager


 class DefaultFlowManager : FlowManager() { //    (main) flow override fun createMainFlow(): Flow { return MainFlow(this) } //    flow override fun createFlow(id: String): Flow { return when (id) { Flows.SIGN_UP -> SignupFlow(this) else -> throw RuntimeException("Cannot find flow for id=$id") } } } //   FlowManager  Application class App : Application(), FlowManagerProvider { private val flowManager = DefaultFlowManager() override fun getProvideManager(): FlowManager { return flowManager } } 

Mensagens entre fluxo e tela


Quando você clica no botão de login, a atividade envia uma mensagem para o fluxo principal. O fluxo cria um fluxo SIGN_UP e aguarda uma resposta dele. Se o login for bem-sucedido, o fluxo SIGN_UP envia o resultado para o fluxo principal e onFlowResult: MainFlow é chamado com o código e o objeto de resultado. O fluxo principal verifica se o resultado está correto e envia uma mensagem de volta à ativação de que o usuário efetuou login com êxito.


 class MainFlow(flowManager: FlowManager) : Flow(flowManager) { companion object { const val LOGIN_REQUEST_CODE = 1 } //     override fun onMessage(code: String, message: Any) { super.onMessage(code, message) if (code == "main" && message == "login") { newFlow(Flows.SIGN_UP, LOGIN_REQUEST_CODE) } } //       flow override fun onFlowResult(requestCode: Int, result: Result) { super.onFlowResult(requestCode, result) if (requestCode == LOGIN_REQUEST_CODE && result is Result.SUCCESS) { sendMessageFromFlow("main", true) } } } class MainActivity : FlowActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) loginButton.setOnClickListener { //   “login”   “main” flow.sendMessage("main", "login") } //     “main” setMessageListener("main") { if (it is Boolean && it) { statusTextView.text = "Logined" } } } } 

Salvando o estado ao alterar uma configuração ou quando um processo para o sistema operacional


Como o Android salva as pilhas de Atividade e Fragmento, os fluxos criados com esses contêineres salvarão e restaurarão seu estado. Com o contêiner View, você precisará gravar seu FlowManager personalizado, pois a biblioteca ainda não possui um gerenciador. Na próxima atualização, haverá um recurso para salvar dados intermediários do fluxo.


Como não queria muito código no artigo, vou me limitar a este exemplo. Aqui está um link para o repositório para um estudo detalhado da biblioteca.

Source: https://habr.com/ru/post/pt435248/


All Articles