Navegación dentro de la aplicación de Android

Introduccion


Con el desarrollo de Android, utilizamos diferentes soluciones arquitectónicas (patrones). Por ejemplo, Mvp , Mvvm , Mvi , etc. ... Cada uno de estos patrones resuelve varios problemas importantes, y dado que no son perfectos, nos dejan algunos problemas sin resolver. Por ejemplo, estas tareas incluyen navegar dentro de la aplicación (enrutamiento), transferir información de una pantalla a otra (hablar la pantalla, me refiero a Actividad, Fragmento o Vista), Guardar el estado de la aplicación al cambiar la configuración (cambio de configuración).


En nuestra empresa, también enfrentamos estos problemas, algunos se resolvieron de manera fácil, pero el primero no encontró una solución específica, después de probar varios métodos para resolverlo, escribimos nuestra propia biblioteca Flowzard .


Desafío


En nuestra empresa, utilizamos la arquitectura Mvp . Para tener la máxima flexibilidad al mostrar, cambiar y transferir datos entre pantallas, tratamos de seguir el principio llamado principio de responsabilidad única . El principio establece que cada módulo debe resolver un problema específico. En nuestro caso, la pantalla debe estar aislada de la tarea global y debe resolver su tarea específica de mostrar / recibir información. No debería saber nada sobre otras pantallas. Para que podamos lograr la máxima flexibilidad. A continuación se muestra un ejemplo de configuración y uso de la biblioteca.


Flowzard


Crear flujo


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

Crear navegador de flujo


Los navegadores realizan dos funciones: Crear contenedores de flujo (Actividad, Fragmento, Vista) para transiciones entre flujo y pantallas para transiciones dentro del flujo.


 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 a actividad


Para asociar Activity con Flow, heredamos FlowActivity y proporcionamos Navigator, en nuestro caso DefaultFlowNavigator.


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

Crear 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 } } 

Mensajería entre flujo y pantalla


Cuando hace clic en el botón de inicio de sesión, la actividad envía un mensaje al flujo principal. Flow crea un flujo SIGN_UP y espera una respuesta de él. Si el inicio de sesión es exitoso, el flujo SIGN_UP envía el resultado al flujo principal y onFlowResult: se llama a MainFlow con el código y el objeto de resultado. El flujo principal verifica si el resultado es correcto y luego envía un mensaje a la activación de que el usuario ha iniciado sesión correctamente.


 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" } } } } 

Guardar estado al cambiar una configuración o cuando un proceso detiene el sistema operativo


Dado que Android guarda las pilas de Actividad y Fragmento, los flujos creados con estos contenedores guardarán y restaurarán su estado. Con el contenedor Ver, necesitará escribir su FlowManager personalizado ya que la biblioteca aún no tiene dicho administrador. En la próxima actualización habrá una función para guardar datos intermedios del flujo.


Como no quería mucho código en el artículo, me limitaré a este ejemplo. Aquí hay un enlace al repositorio para un estudio detallado de la biblioteca.

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


All Articles