Cambios en el uso de Activity and Fragment en AndroidX

Durante el último período, la API de Activity / Fragmet bajo el paquete AndroidX ha cambiado mucho. Veamos cómo mejoran la eficiencia de desarrollo de Android y cómo adaptarse a las reglas y patrones de programación populares actuales.

Todas las características descritas en este artículo ahora están disponibles en el paquete estable de AndroidX, que se lanzó o cambió a una versión estable el año pasado.

Pase el ID de diseño en el constructor

A partir de AndroidX AppCompat 1.1.0 y Fragment 1.1.0 (Nota del traductor: AppCompat contiene Fragment, y Fragment contiene Activity, para más detalles, consulte los componentes principales de [Organización] Jetpack de la relación de dependencia y entrega), puede usar el layoutId como estructura de parámetros Función:

class MyActivity : AppCompatActivity(R.layout.my_activity)
class MyFragmentActivity: FragmentActivity(R.layout.my_fragment_activity)
class MyFragment : Fragment(R.layout.my_fragment)

Este método puede reducir el número de reescrituras de métodos en Activity / Fragment y hacer que la clase sea más legible. Puede llamar al método setContentView () sin reescribir onCreate () en Activity. Además, puede llamar manualmente a Inflater para extender la vista sin reescribir manualmente onCreateView en Fragment.

Amplíe la flexibilidad de Actividad / Fragmento

Con la ayuda de la nueva API de AndroidX, es posible reducir el manejo de ciertas funciones en Activity / Fragment. En general, puede obtener objetos que proporcionan ciertas funciones y registrar su lógica de procesamiento con ellos en lugar de anular los métodos en Actividad / Fragmento. De esta manera, ahora puede componer varias clases independientes en la pantalla para obtener una mayor flexibilidad, reutilizar el código y, a menudo, tener más control sobre la estructura del código sin introducir sus propias abstracciones. Veamos cómo funciona esto en los dos ejemplos.

  1. OnBackPressedDispatcher

A veces, debe evitar que los usuarios vuelvan al nivel anterior. En este caso, debe anular el método onBackPressed () en la Actividad. Sin embargo, cuando usa Fragment, no hay una forma directa de interceptar el retorno. No hay un método onBackPressed () disponible en la clase Fragment. Esto es para evitar un comportamiento inesperado cuando existen varios Fragments al mismo tiempo.

Sin embargo, a partir de AndroidX Activity 1.0.0, puede usar OnBackPressedDispatcher para registrar OnBackPressedCallback en cualquier lugar donde pueda acceder al código de la actividad (por ejemplo, en Fragment).

class MyFragment : Fragment() {
  override fun onAttach(context: Context) {
    super.onAttach(context)
    val callback = object : OnBackPressedCallback(true) {
      override fun handleOnBackPressed() {
        // Do something
      }
    }
    requireActivity().onBackPressedDispatcher.addCallback(this, callback)
  }
}

Puede notar otras dos funciones útiles aquí:

El parámetro booleano en el constructor de OnBackPressedCallback ayuda a activar / desactivar dinámicamente el comportamiento de prensado en función del estado actual

El primer parámetro opcional del método addCallback () es LifecycleOwner para garantizar que la devolución de llamada solo se use cuando su objeto consciente del ciclo de vida (por ejemplo, Fragment) esté al menos en el estado INICIADO.

Al usar OnBackPressedDispatcher, no solo puede obtener una manera conveniente de manejar la tecla de retorno fuera de Activity. Según sus necesidades, puede definir OnBackPressedCallback en cualquier lugar para que sea reutilizable o realizar cualquier operación de acuerdo con la arquitectura de la aplicación. Ya no necesita anular el método onBackPressed en Activity, ni tiene que proporcionar su propio código abstracto para implementar los requisitos.

  1. SavedStateRegistry

Si desea que la Actividad regrese a su estado anterior después de la finalización y reinicio, puede usar la función de estado guardado. En el pasado, necesitaba reemplazar dos métodos en la actividad: onSaveInstanceState y onRestoreInstanceState. También puede acceder al estado restaurado en el método onCreate. De manera similar, en Fragment, puede usar el método onSaveInstanceState (y puede restaurar el estado en los métodos onCreate, onCreateView y onActivityCreated).

Comenzando con AndroidX SavedState 1.0.0 (que es una dependencia dentro de AndroidX Activity y AndroidX Fragment. Nota del traductor: no necesita declararlo por separado), puede acceder a SavedStateRegistry, que utiliza un mecanismo similar al OnBackPressedDispatcher descrito anteriormente: puede Obtenga SavedStateRegistry de Activity / Fragment, luego registre su SavedStateProvider:

class MyActivity : AppCompatActivity() {

  companion object {
    private const val MY_SAVED_STATE_KEY = "my_saved_state"
    private const val SOME_VALUE_KEY = "some_value"
  }

  private lateinit var someValue: String

  private val savedStateProvider = SavedStateRegistry.SavedStateProvider {
    Bundle().apply {
      putString(SOME_VALUE_KEY, someValue)
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    savedStateRegistry
      .registerSavedStateProvider(MY_SAVED_STATE_KEY, savedStateProvider)
  }

  fun someMethod() {
    someValue = savedStateRegistry
      .consumeRestoredStateForKey(MY_SAVED_STATE_KEY)
      ?.getString(SOME_VALUE_KEY)
      ?: ""
  }
}

Como puede ver, SavedStateRegistry lo obliga a usar la clave para los datos. Esto evita que sus datos sean destruidos por otro SavedStateProvider adjunto a la misma Actividad / Fragmento. Al igual que en OnBackPressedDispatcher, puede, por ejemplo, extraer el SavedStateProvider a otra clase y usarlo con cualquier información mediante el uso de cualquier lógica necesaria para lograr un claro comportamiento de estado de guardado en la aplicación.

Además, si usa ViewModel en su aplicación, considere usar AndroidX ViewModel-SavedState para que su ViewModel pueda guardar su estado. Por conveniencia, a partir de AndroidX Activity 1.1.0 y AndroidXFragment 1.2.0, SavedState-enabled SavedStateViewModelFactory es la fábrica predeterminada utilizada en todas las formas de obtener ViewModel: delegue ViewModelProvider constructor y ViewModelProviders.of ().

FragmentFactory

Uno de los problemas más frecuentemente mencionados con Fragment es que no se pueden usar constructores con parámetros. Por ejemplo, si usa Dagger2 para la inyección de dependencia, no puede anotar el constructor Fragment con Inject y especificar parámetros. Ahora, puede reducir problemas similares durante la creación de Fragment especificando la clase FragmentFactory. Al registrar FragmentFactory en FragmentManager, puede anular el método predeterminado de instanciar Fragment:

class MyFragmentFactory : FragmentFactory() {

  override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
    // Call loadFragmentClass() to obtain the Class object
    val fragmentClass = loadFragmentClass(classLoader, className)

    // Now you can use className/fragmentClass to determine your prefered way
    // of instantiating the Fragment object and just do it here.

    // Or just call regular FragmentFactory to instantiate the Fragment using
    // no arguments constructor
    return super.instantiate(classLoader, className)
  }
}

Como puede ver, la API es muy general, por lo que puede realizar todas las operaciones que desee para crear una instancia de Fragment. Volviendo al ejemplo de Dagger2, por ejemplo, puede inyectar FragmentFactory Provider <Fragment> y usarlo para obtener objetos Fragment.

Fragmento de prueba

A partir de AndroidX Fragment 1.1.0, puede usar el componente de prueba Fragment para proporcionar la clase FragmentScenario, que puede ayudar a crear una instancia del Fragment en la prueba y realizar una prueba por separado:

// To launch a Fragment with a user interface:
val scenario = launchFragmentInContainer<FirstFragment>()

// To launch a headless Fragment:
val scenario = launchFragment<FirstFragment>()

// To move the fragment to specific lifecycle state:
scenario.moveToState(CREATED)

// Now you can e.g. perform actions using Espresso:
onView(withId(R.id.refresh)).perform(click())

// To obtain a Fragment instance:
scenario.onFragment { fragment ->

Más Kotlin!

Es agradable ver que el paquete -ktx AndroidX proporciona muchos métodos útiles de extensión de Kotlin, y se agregan nuevos métodos regularmente. Por ejemplo, en AndroidX Fragment-KTX 1.2.0, las extensiones que usan tipos fragmentados se pueden usar en el método replace () en FragmentTransaction. Al usarlo junto con el método de extensión commit (), podemos obtener el siguiente código:

// Before
supportFragmentManager
  .beginTransaction()
  .add(R.id.container, MyFragment::class.java, null)
  .commit()

// After
supportFragmentManager.commit {
  replace<MyFragment>(R.id.container)
}

FragmentContainerView

Una cosa pequeña e importante. Si usa FrameLayout como contenedor para Fragment, debe usar FragmentContainerView en su lugar. Soluciona algunos problemas de orden de índice del eje z de animación y la programación de inserción de ventanas. A partir de AndroidXFragment 1.2.0, se puede usar FragmentContainerView.

El artículo no es fácil. Si le gusta este artículo, o si le resulta útil, espero que a todos les guste, lo reenvíen y lo sigan. El artículo se actualizará continuamente. ¡Productos absolutamente secos! ! !

Supongo que te gusta

Origin blog.51cto.com/14775360/2486716
Recomendado
Clasificación