No se puede realizar esta acción dentro de onLoadFinished
Estoy creando una nueva aplicación de muestra de Android con una actividad y muchos fragmentos.
Al principio estoy empezando el "OverviewFragment" (mi tablero) que debe mostrar algunas informaciones básicas. My OverviewFragment carga las informaciones con un "AccountProvider" (ContentProvider). Si la base de datos está vacía, el OverviewFragment debe reemplazar con mi WelcomeFragment …
- Mange BackStackEntries en FragmentManager
- Cómo evitar agregar el mismo fragmento a la pila
- Cómo utilizar PreferenceFragment?
- Recargar datos en la pestaña seleccionada en un fragmento utilizando el paginador de vistas
- Fragmento en la ronda Desgaste reloj girando en negro en el emulador / reloj
Aquí está un código:
public class OverviewFragment extends BaseFragment implements LoaderManager.LoaderCallbacks { private static final int LOADER_ACCOUNTS = 10; private static final int LOADER_TRANSACTIONS = 20; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getLoaderManager().initLoader(LOADER_ACCOUNTS, null, this); //getLoaderManager().initLoader(LOADER_TRANSACTIONS, null, this); } @Override public Loader onCreateLoader(int id, Bundle args) { Uri uri = null; String[] projection = null; String selection = null; String[] selectionArgs = null; String sortOrder = null; switch (id) { case LOADER_ACCOUNTS: uri = WalletProvider.CONTENT_URI; projection = new String[]{DBHelper.ACC_ID, DBHelper.ACC_TITLE}; sortOrder = DBHelper.ACC_TITLE; break; } CursorLoader cl = new CursorLoader(getActivity(), uri, projection, selection, selectionArgs, sortOrder); return cl; } @Override public void onLoadFinished(Loader loader, Object data) { switch (loader.getId()) { case LOADER_ACCOUNTS: bindAccounts((Cursor) data); break; } } @Override public void onLoaderReset(Loader loader) { } private void bindAccounts(Cursor cursor) { boolean showCreateWallet = true; if (cursor != null && cursor.moveToFirst()) { showCreateWallet = false; } if (showCreateWallet) { listener.changeFragment(new WalletCreateFragment()); } }
Y aquí mi actividad principal
@Override public void changeFragment(Fragment fragmentToLoad) { FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.container, fragmentToLoad) .commit(); }
Ahora … si estoy empezando mi aplicación con una base de datos vacía, obtengo el error que ves en el título ..
Sé que no debería cambiar el fragmento en la función onLoadFinished …. pero ¿dónde puedo hacerlo? :PAG
Lo siento por mi inglés =)
- Integre tabhost y el cajón de navegación
- DateTimePicker android
- Traer al frente el fragmento existente
- Fragmentos dentro de las pestañas del fragmento
- Memoria que no se libera después de que el fragmento se elimina
- Activity and Fragment Lifecycle, ¿el fuego onResume dispara uno tras otro?
- Fragmento de error: tipos incompatibles, requiere android.app.fragment pero encontró activity.messagefragment
- Android sustituye el fragmento actual por otro fragmento
Este es un error de android. Para solucionar esto, utilice un Handler para reemplazar / añadir / llamar a un Fragmento dentro de onLoadFinished como esto:
final int WHAT = 1; Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == WHAT) changeFragment(fragmentToLoad); } }; handler.sendEmptyMessage(WHAT);
Esto no es un error, pero no es un problema simple. onLoadFinished
puede ejecutarse en cualquier momento, incluso después de que se haya guardado el estado de una actividad. El cambio resultante del fragmento entonces no será guardado automáticamente por el marco. Tienes que permitirlo explícitamente utilizando commitAllowingStateLoss
En la documentación de onLoadFinished
:
Se llama cuando un cargador previamente creado ha terminado su carga. Tenga en cuenta que normalmente no se permite a una aplicación confirmar transacciones de fragmentos mientras está en esta llamada, ya que puede ocurrir después de que se guarde el estado de una actividad. Vea FragmentManager.openTransaction () para más información sobre esto.
Citando Dianne Hackborn del hilo mencionado en el comentario en la otra respuesta :
Basta con entender que si el estado de fragmento de la actividad ya se ha guardado, su código tendrá que actualizarlo correctamente si se reinicia posteriormente desde el estado.
[…]
Es una mala experiencia de usuario mostrar un diálogo (o hacer cualquier otro cambio importante en la interfaz de usuario) como resultado de un cargador. Esto es lo que está haciendo: establecer alguna operación para ejecutar en segundo plano para una cantidad de tiempo en-determinante, que al final puede lanzar algo delante del usuario tirando de ellos fuera de lo que estaban haciendo.
Mi sugerencia es mostrar al usuario cualquier información sobre el resultado del cargador en línea de la misma manera que mostraría los datos de la misma.
Si usted (y sus usuarios) están bien con la experiencia del usuario, puede usar commitAllowingStateLoss
para actualizar el fragmento.
Ambas respuestas faltan una buena solución. Es cierto que no es una buena idea hacer algo en el onLoadfinished
ya que la actividad o fragmento podría haber sido destruido.
Tampoco es una buena experiencia de usuario actualizar la interfaz de usuario después de que algo en un hilo independiente ha cambiado ya que pueden estar a punto de realizar una acción. Pero eso se puede arreglar con un botón de actualización que luego actualiza lo que el usuario ve.
Sin embargo, hay circunstancias en las que puede requerir actualizar realmente la interfaz de usuario. Por ejemplo, si necesitamos hacer una acción que requiere que el usuario espere después de haber presionado un botón siguiente .
En su ejemplo, usted extiende las Callbacks
directamente por el Fragment
para que pueda crear un método en su fragmento que le permite ejecutar con seguridad una actualización de la interfaz de usuario de esta manera:
private void update(Runnable runnable) { View rootView = getView(); if (isAdded() && rootView != null) { rootView.post(runnable); } }
Esto comprueba si el fragmento está en un estado que puede manejar las actualizaciones de la interfaz de usuario y ejecuta el comando. Se puede utilizar de esta manera:
update(new Runnable() { @Override public void run() { bindAccounts((Cursor) data); } })
Dicho esto, no es una idea muy sabia utilizar su fragmento como las devoluciones de llamada ya que puede LoaderManager
su fragmento en LoaderManager
que vive en la actividad.
Otra forma segura de manejar esto sería con receptores de radiodifusión (asegúrese de que no estén registrados).
Sin embargo, la opción más segura será utilizar los componentes de arquitectura recientemente anunciados para Android cuando estén listos para la producción:
https://developer.android.com/topic/libraries/architecture/index.html
- ¿Por qué se envuelve el contenido en la línea múltiple TextView fill parent?
- Cómo formatear valores dentro de MPAndroidChart?