studio oncreateloader loadermanager getloadermanager example ejemplo android asynctaskloader

android - oncreateloader - loadermanager



AsyncTaskLoader no se ejecuta (7)

Creo que la mejor solución para el paquete de compatibilidad es anular el método AsyncTaskLoader.onStartLoading .

p.ej

@Override protected void onStartLoading() { if(dataIsReady) { deliverResult(data); } else { forceLoad(); } }

Quiero implementar AsyncTaskLoader en mi proyecto utilizando el Paquete de compatibilidad, así que seguí el manual del cargador en los documentos de Android.

El problema es que el cargador no hace nada, parece que loadInBackground() nunca se llama

¿Alguna idea de lo que está mal en mi código? ( ExpandableListFragment extiende Fragment , pero no anula ningún método crítico)

Gracias :-)

/**EDITAR:

Me di cuenta (tarde, soy un imbécil) que AsyncTaskLoader es una clase abstracta, así que necesito crear una subclase ... m (__) m Dejo la pregunta en caso de que alguien venga detrás de mí, quién sabe ...

public class AgendaListFragment extends ExpandableListFragment implements LoaderManager.LoaderCallbacks<JSONArray> { private TreeMap<Integer, ArrayList<Evento>> mItems = new TreeMap<Integer, ArrayList<Evento>>(); private AgendaListAdapter mAdapter; private ProgressBar mProgressBar; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_agenda, container); mProgressBar = (ProgressBar) root.findViewById(R.id.loading); return root; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mAdapter = new AgendaListAdapter(getActivity()); setListAdapter(mAdapter); getLoaderManager().initLoader(0, null, this); } @Override public Loader<JSONArray> onCreateLoader(int arg0, Bundle arg1) { mProgressBar.setVisibility(View.VISIBLE); return new AsyncTaskLoader<JSONArray>(getActivity()) { @Override public JSONArray loadInBackground() { return getDataFromService(AgendaServices.LISTADO_MES); } }; } @Override public void onLoadFinished(Loader<JSONArray> loader, JSONArray data) { // Some stuff to turn JSONArray into TreeMap mProgressBar.setVisibility(View.GONE); mAdapter.setItems(mItems); } @Override public void onLoaderReset(Loader<JSONArray> arg0) { mAdapter.setItems(null); mProgressBar.setVisibility(View.VISIBLE); } }


En cuanto a la discusión en https://code.google.com/p/android/issues/detail?id=14944 , la verificación de takeContentChanged parece ser un paso importante.

protected void onStartLoading() { if (mCursor != null) { deliverResult(mCursor); } if (takeContentChanged() || mCursor == null) { forceLoad(); } }


Esto es exactamente una solución, pero debería funcionar. Estoy bastante seguro de que la biblioteca de compatibilidad está rota. Prueba esto:

getLoaderManager().initLoader(0, null, this).forceLoad();


He tenido el mismo problema después de migrar de CursorLoader a AsyncTaskLoader.

la documentación dice : Las subclases del Loader<D> generalmente deben implementar al menos onStartLoading (), onStopLoading (), onForceLoad () y onReset () .

AsyncTaskLoader extiende Loader pero no implementa onStartLoading (), onStopLoading (), onReset () . ¡Debe implementarlo usted mismo!

@ davidshen84 propuso una buena solución. Solo agregué la comprobación de takeContentChanged.

@Override protected void onStartLoading() { try { if (data != null) { deliverResult(data); } if (takeContentChanged() || data == null) { forceLoad(); } Log.d(TAG, "onStartLoading() "); } catch (Exception e) { Log.d(TAG, e.getMessage()); } }

Usar forceLoad () está bien (no es una mala práctica). Vea lo que says documentación:
En general, solo debe llamar a esto cuando se inicia el cargador, es decir, isStarted () devuelve verdadero.


Todavía tenía el problema de que no se llamaba a la carga de datos. Finalmente eliminé AsyncTaskLoader (la versión de la biblioteca de soporte) y usé solo AsyncTask (no desde la biblioteca de soporte) para hacer el trabajo. Y funcionó.

Podría ser suficiente para tus necesidades también.

Descripción y ejemplo: http://developer.android.com/reference/android/os/AsyncTask.html .

Tienes que extender la clase AsyncTask .

El método doInBackground hará el trabajo y en el método onPostExecute obtendrá el resultado. Para iniciar AsyncTask , invocará el método execute en su instancia. Vea el enlace.


Tomé el código fuente de CursorLoader de android framework y escribí una clase CustomTaskLoader<T> para facilitar el trabajo.

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/android/content/CustomTaskLoader.java

básicamente implementa estas dos funciones:

public abstract T runTaskInBackground(CancellationSignal signal); public abstract void cleanUp(T oldResult);

vea el uso en las actividades y los fragmentos, por ejemplo este: (bueno, mi código simplemente ignora el signo de CancellationSignal , es un TODO en mi lista, pero es libre de usarlo).

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/PostListFragment.java

return new CustomTaskLoader<Cursor>(getActivity().getApplicationContext()) { @Override public Cursor runTaskInBackground(CancellationSignal signal) { return SiteSession.getAllPostsCursor(PostListAdapter.POST_COLUMNS); } @Override public void cleanUp(Cursor oldCursor) { if (!oldCursor.isClosed()) oldCursor.close(); } }


Cheok Yan Cheng tiene toda la razón:

La comprobación de takeContentChanged también parece un paso importante.

Si escribe su método de esta manera:

protected void onStartLoading() { forceLoad(); }

notará que cuando se onStartLoading una actividad secundaria y luego regresa a la principal, se onStartLoading nuevamente la llamada a la onStartLoading (y, por loadInBackground tanto, a loadInBackground ).

¿Qué puedes hacer? Establezca una variable interna ( mContentChanged ) en verdadero dentro del constructor; a continuación, compruebe esta variable dentro de onStartLoading . Solo cuando sea verdad, empieza a cargar de verdad:

package example.util; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; public abstract class ATLoader<D> extends AsyncTaskLoader<D> { public ATLoader(Context context) { super(context); // run only once onContentChanged(); } @Override protected void onStartLoading() { // That''s how we start every AsyncTaskLoader... // - code snippet from android.content.CursorLoader (method onStartLoading) if (takeContentChanged()) { forceLoad(); } } }