2012-04-16 7 views
9

me gustaría usar una demo para mostrar esto:cargador no puede reiniciarse después de la orientación cambió

enter code here 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    Button button = (Button) findViewById(R.id.button1); 
    button.setOnClickListener(buttonClickListener); 
} 

private OnClickListener buttonClickListener = new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     // TODO Auto-generated method stub 
     startMyLoader(); 
    } 

}; 

private void startMyLoader() { 
    getLoaderManager().destroyLoader(0); 
    getLoaderManager().restartLoader(0, null, myLoaderListener); 
} 

/** 
* The listener for the group metadata loader. 
*/ 
private final LoaderManager.LoaderCallbacks<Cursor> myLoaderListener 
    = new LoaderCallbacks<Cursor>() { 

    @Override 
    public CursorLoader onCreateLoader(int id, Bundle args) { 
     return new CursorLoader(LoaderDemoActivity.this, 
     ContactsContract.Contacts.CONTENT_URI, 
     null, null, null, null); 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
     cursor.moveToPosition(-1); 
     if (cursor.moveToNext()) { 
      Context context = getApplicationContext(); 
      CharSequence text = "Load finished!"; 
      int duration = Toast.LENGTH_SHORT; 

      Toast toast = Toast.makeText(context, text, duration); 
      toast.show(); 
     } 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> loader) { 
    } 
}; 
enter code here 

Después cambió de orientación, que se hace clic en el botón, el onCreateLoader puede ser llamado, pero onLoadFinished haré no ser llamado

Parece extraño.

Gracias por la ayuda con anticipación.

Respuesta

0

Desde el sitio de desarrollo del androide

"Ellos se vuelven a conectar automáticamente al cursor del último cargador cuando se recreado después de un cambio de configuración. Por lo tanto, ellos no necesitan volver a consultar sus datos."

Por lo que yo entiendo, incluso cuando empezamos el cargador de forma explícita el cargador no se iniciará. Dado que la destrucción que estamos llamando debería llamar al onLoaderReset() una vez que se destruye. Pero ese método no se llama una vez que se cambia la orientación, sino que se llama antes.

Todavía puedo estar equivocado en esto. Esta es mi suposición. Se agradecería más discusión.

3

No necesita (ni debe) destruir su Loader para volver a cargarlo. La clase Loader está diseñada para ser reutilizable.

Use initLoader en su lugar. ej .:

getLoaderManager().initLoader(0, null, myLoaderListener); 

Si quiere forzar la recarga del cargador ya fuiste registrado:

getLoaderManager().getLoader(0).forceLoad(); 

Si no está seguro de si la instancia Loader existe noté después de evento de cambio de configuración sucedido utilizar initLoader en lugar de getLoader para recuperar su instancia Loader en la que puede llamar al forceLoad().

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

Si utiliza biblioteca de soporte a continuación, utilizar forceLoad incluso después de la primera instantation - es probable que haya un error - me recuerdo hay algunas preguntas al respecto en este foro - Prueba a buscar las entradas más antiguas.

+0

No creo que sea una forma correcta de llamar a forceLoad() manualmente si ha tenido la intención de usar loaderManager para controlar todo eso. – user1335719

+0

@ user1335719 no existe tal restricción, solo 'Debe ser llamado desde el hilo principal del proceso' y el cargador debe iniciarse (marque' isStarted() ') que es obvio después de recuperarlo con initLoader. 'methdos startLoading()' y 'stopLoading' son para uso interno, no' forceLoad'. –

5

Creo que he encontrado el motivo.

En la actividad onCreate, cargará todos los LoaderMangers (propios o sus subfragmentos) desde NonConfigurationInstances.

if (mLastNonConfigurationInstances != null) { 
     mAllLoaderManagers = mLastNonConfigurationInstances.loaders; 
    } 

Y en la actividad onStart, intentará iniciar su propio LoaderManger.

if (!mLoadersStarted) { 
     mLoadersStarted = true; 
     if (mLoaderManager != null) { 
      mLoaderManager.doStart(); 
     } else if (!mCheckedForLoaderManager) { 
      mLoaderManager = getLoaderManager(-1, mLoadersStarted, false); 
     } 
     mCheckedForLoaderManager = true; 
    } 

Pero después de la configuración modificada, mLoaderManager == null, por lo que no la iniciará. ¡Y aquí está el problema! Si intenta iniciar el cargador pertenecen a este loaderManager, fallará.

void installLoader(LoaderInfo info) { 
    mLoaders.put(info.mId, info); 
    if (mStarted) { 
     // The activity will start all existing loaders in it's onStart(), 
     // so only start them here if we're past that point of the activitiy's 
     // life cycle 
     info.start(); 
    } 
} 

tenga en cuenta el valor de mStarted que se establecerá como 'verdadero' cuando se inicie LoaderManager.

Y hay dos formas de resolver este problema.

  1. llamada getLoaderManger() en onCreate(), se volverá a asignar el mLoaderManager y que quede listo para ser iniciado en el subseuqent onStart().

    public LoaderManager getLoaderManager() { if (mLoaderManager! = Null) { return mLoaderManager; } mCheckedForLoaderManager = true; mLoaderManager = getLoaderManager (-1, mLoadersStarted, true); devolver mLoaderManager; }

  2. tienen el cargador ubicado en fragmentos. Porque en Fragments 'onStart(), , comenzará su propio LoaderManager.

    if (! MLoadersStarted) { mLoadersStarted = true; if (! MCheckedForLoaderManager) { mCheckedForLoaderManager = true; mLoaderManager = mActivity.getLoaderManager (mIndex, mLoadersStarted, false); } if (mLoaderManager! = Null) { mLoaderManager.doStart(); }}

+0

"Pero después de la configuración modificada, mLoaderManager == null, por lo que no la iniciará"; si fuera así, obtendría NullPOinterException al llamar a 'getLoaderManager(). DestroyLoader (0);' - Probablemente esté perdiendo el punto;) , use forceLoad y no destruya-recree el cargador cada vez ya que está en contra de cómo fue diseñado. –

+0

mLoaderManager será asignado por "getLoaderManager (-1, mLoadersStarted, false" si es nulo. Por lo tanto, no lanzará NullPointerException. Y tengo que volver a crear el cargador, ya que debe cambiarse algo como URI en su creación. – user1335719

+0

Gracias , # 1 me salvó –

13

que enfrentan el mismo problema. Intente llamar a this.getSupportLoaderManager() en onCreate. Resolvió mi problema. Espero que le ayudará, así

+1

¡Muchas gracias! ¡Eso fue muy útil! Todo lo que tenía que hacer era llamar a este método en mi onCreate y mis cargadores comenzados fuera de onCreate ¡comencé a trabajar con el cambio de orientación! –

+1

Mi cursorLoader estaba dentro de un fragmento. Descubrí que tenía que llamar a getLoaderManager() desde el método onCreate de la actividad propietaria del fragmento. – daveywc

+1

¡Gracias! ¡Me ha salvado el día! Lo mismo para el LoaderManager estándar. Funciona mucho mejor si llama al getLoaderManager() en onCreate() solo para inicializarlo, incluso si no lo necesita allí. – philips77

1

Asegúrese de que no está mirando savedStateInfo durante el uso de fragmentos antes de llamar a su gestor de la actividad onCreate

@Override 
public void onCreate(Bundle savedInstanceState) { 

    // used to not overlap fragments 
    if (savedInstanceState != null) { 
     return null; 
    } 

    loadFragments(); 

    getSupportLoaderManager().restartLoader(LISTS_LOADER, null, this); 
} 

Si necesita comprobar si hay savedInstanceState fragmentos de todos modos se puede comprobar si hay alguna La variable de clase que se debe crear después de que el cargador finalizó la carga, ya que la actividad se destruye al girar, pero aumenta desde el estado anterior cuando se rota hacia atrás.

Cuestiones relacionadas