Adelante
El uso de Fragment es indispensable en el desarrollo de Android actual, que tiene muchas características excelentes:
- Dividir la interfaz de usuario compleja
- La barra de herramientas se puede personalizar
- Tiene una devolución de llamada de ciclo de vida
- Cambio de página más ligero
- Soporte Backstack
- Compromiso transaccional
- Usar con ViewPager
- El estado se puede guardar cuando se reconstruye la actividad
Sin embargo, Fragment también tiene muchas desventajas:
- Parece muy seguro actualizar la página de forma transaccional a través de FragmentManager. En el uso real, encontramos que era inútil excepto para agregar código de plantilla.
- Aunque admite backstack, no es lo suficientemente inteligente para usar y propenso a errores
- El ciclo de vida es más complicado y difícil de entender que Activity
- La administración del estado es demasiado complicada. La clase principal ha
FragmentManagerImpl
verificado 2K filas, lo cual es difícil de entender y de solucionar. - Escasa escalabilidad, por ejemplo,
FragmentPagerAdapter
etc.
Tome FragmentPagerAdapter como ejemplo, por ejemplo, el siguiente código
@Override
public Object instantiateItem(View container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
String name = makeFragmentName(container.getId(), position);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + position + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), position));
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
}
return fragment;
}
instantiateItem()
Después de abrir una transacción, findFragmentByTag
obtenga el Fragmento, si falla, consígalo a través de getItem y agréguelo aFragmentManager
Porque lo mCurTransaction
es private
, es difícil reescribir instantiateItem para implementar su propia lógica
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
makeFragmentName
También es privado y no se puede llamar directamente.
En resumen, es muy difícil extender su propia implementación en FragmentPagerAdapter, y otras clases relacionadas con Fragment tienen problemas similares.
Vista personalizada
Existen muchas limitaciones para usar Fragment, entonces, ¿hay alguna alternativa?
Framgent es esencialmente una vista personalizada con un ciclo de vida, por lo que el uso de una vista personalizada puede reemplazar el uso de Framment hasta cierto punto:
-
Interfaz de usuario compleja dividida; barra de herramientas personalizada: la
vista personalizada admite naturalmente el anidado y la segmentación de la interfaz de usuario -
Con devolución de llamada del ciclo de vida:
deje que la vista personalizada implemente la interfaz LifecycleOwner, para darse cuenta de que el reenvío del ciclo de vida ahora es posible. -
Compromiso transaccional: de
mal gusto, funciona sin soporte -
Use ViewPager con
ViewPager para admitir naturalmente la vista personalizada -
El estado
se puede guardar cuando se reconstruye la actividad: con la ayuda de ViewModel, también puede ayudar a la vista personalizada a lograr la conservación del estado cuando se reconstruye la actividad -
Soporte Backstack; Cambio de página:
mediante la implementación de una gestión de pila simple, se puede realizar salto y retroceso de página, por ejemplo:
// Simple stack implementation, works as expected every time
private Stack<NavItem> navigationStack = new Stack<>();
// ...
// Navigating to a new screen/item in the stack
navigationStack.push(new NavItem(viewToBeAdded.getClass(), args));
// ...
// Navigating back using the stack
if (navigationStack.size() > 1) {
navigationStack.pop();
NavItem navItem = navigationStack.peek();
CustomView customView = (CustomView) navItem.viewClass.getConstructor(Context.class).newInstance(this);
container.removeAllViews();
customView.setArgs(navItem.args);
container.addView(customView);
} else {
super.onBackPressed();
}
para resumir
Con bibliotecas de soporte como Lifecycle y ViewModel, la vista personalizada puede reemplazar las funciones comunes de Fragment y puede expandirse y personalizarse más libremente.