11

Ho un'attività che carica un elenco di dati dal server utilizzando i callback del caricatore. Devo elencare i dati in un frammento che si estendecommit frammento da onLoadFinished all'interno dell'attività

SherlockListFragment 

ho provato a commettere il frammento utilizzando

Fragment newFragment = CategoryFragment.newInstance(mStackLevel,categoryList); 
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.add(R.id.simple_fragment, newFragment).commit(); 

in onLoadFinished e dà un IllegalStateException dicendo

java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished 

devo riferito l'esempio in actionbar sherlock, ma quegli esempi hanno caricatori all'interno dei frammenti e non l'attività.

Qualcuno può aiutarmi con questo o che posso aggiustarlo senza chiamare il caricatore dal frammento!

+0

possibile duplicato del [Android - problemi usando FragmentActivity + Loader per aggiornare FragmentStatePagerAdapter] (http://stackoverflow.com/questions/7746140/android-problems-using-fragmentactivity-loader- to-update-fragmentstatepagera) – rds

risposta

14

Atlast, ho trovato una soluzione a questo problema. Crea un handle che imposta un messaggio vuoto e chiama quel gestore onLoadFinished(). Il codice è simile a questo.

@Override 
public void onLoadFinished(Loader<List<Station>> arg0, List<Station> arg1) { 
    // do other actions 
    handler.sendEmptyMessage(2); 
} 

Nel gestore,

private Handler handler = new Handler() { // handler for commiting fragment after data is loaded 
    @Override 
    public void handleMessage(Message msg) { 
     if(msg.what == 2) { 
      Log.d(TAG, "onload finished : handler called. setting the fragment."); 
      // commit the fragment 
     } 
    } 
}; 

Il numero di frammenti dipendono dal requisito.

This method can be mainly used in case of stackFragments, where all fragments have different related functions. 
+1

Hmm vorrei sconsigliarlo. Se hai davvero bisogno di raggruppare i frammenti come dici tu, puoi semplicemente chiamare commitAllowingStateLoss(). Questo eviterà il gestore e l'IllegalArgumentException come diresti alla piattaforma .. "va bene, sono consapevole dei rischi .. fallo comunque". Vedi [collegamento] (https://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#commitAllowingStateLoss()) – kwazi

+0

Grazie kwazi, avevo provato quel metodo. Grazie per l'aiuto. È stato un buon consiglio Saluti :) – DroidBee

+4

Solo una nota: chiamare commitAllowStateLoss non è un'opzione quando si chiama DialogFragment.show(). Ho dovuto usare un gestore per quel particolare tipo di transazione di frammento. – javahead76

8

Come per la documentazione Android sul metodo di onLoadFinished():

Nota che normalmente un'applicazione non è permesso commettere transazioni frammento, mentre nel presente invito, dal momento che può accadere dopo lo stato di un'attività viene salvato. Vedi FragmentManager.openTransaction() per ulteriori discussioni su questo.

https://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html#onLoadFinished(android.content.Loader, D)

(Nota: copia/incolla che link nel tuo browser ... StackOverflow non gestisce bene ..)

Così si dovrebbe mai semplicemente caricare un frammento in quel stato. Se davvero non vuoi mettere il Loader in the Fragment, devi inizializzare il frammento nel tuo metodo onCreate() dell'Activity, e poi quando onLoadFinished si verifica, chiama semplicemente un metodo sul tuo frammento.

Alcuni codice pseudo ruvida segue:

public class DummyFragment { 

    public void setData(Object someObject) { 
      //do stuff 
    } 

public class DummyActivity extends LoaderCallbacks<Object> { 

    public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      Fragment newFragment = DummyFragment.newInstance(); 
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
      ft.add(R.id.simple_fragment, newFragment).commit(); 

      getSupportLoaderManager.initLoader(0, null, this) 
    } 

    // put your other LoaderCallbacks here... onCreateLoader() and onLoaderReset() 

    public void onLoadFinished(Loader<Object> loader, Object result) { 
      Fragment f = getSupportLoaderManager.findFragmentById(R.id.simple_fragment); 
      f.setData(result); 
    } 

Ovviamente, che ci si vuole utilizzare l'oggetto giusto .. e il caricatore a destra, e, probabilmente, di definire un metodo utile setData() per aggiornare il frammento . Ma spero che questo ti indicherà la giusta direzione.

+0

Grazie per la tua risposta! :) Forse non ero chiaro sulla mia domanda. Ho già focalizzato la mia homefragment, volevo solo implementare l'impilamento del prossimo frammento, sul caricamento di alcuni dati. Ho trovato un metodo per l'implementazione di quello. Lo posterò come risposta. +1 per il supporto e la risposta. Non ho davvero pensato di usare f.setData (risultato) che avrei potuto usare nella stessa attività all'interno di altri frammenti. :) – DroidBee

+0

Ah, non ne ero consapevole. Comunque, vedi il mio commento sulla tua risposta riguardo a una soluzione migliore. commitAllowingStateLoss() sarebbe la strada da percorrere ... – kwazi

0

Come @kwazi risposto che questo è un brutta esperienza utente a chiamare FragmentTransition.commit() da onLoadFinished(). Ho trovato una soluzione per questo evento utilizzando ProgressDialog.

Primo creato ProgressDialog.setOnDismissListener(new listener) per guardare il onLoadFinished(). Ulteriori faccio progressDialog.show() prima getLoaderManager().restartLoader(). E eventualmente inserire progressDialog.dismiss() in onLoadFinished(). Tale approccio consente di non associare il thread dell'interfaccia utente principale e il thread del caricatore.

public class FrPersonsListAnswer extends Fragment 
 
\t \t \t \t \t \t implements 
 
\t \t \t \t \t \t LoaderCallbacks<Cursor>{ 
 
private ProgressDialog progressDialog; 
 
           \t @Override 
 
\t public View onCreateView(LayoutInflater inflater, 
 
\t \t \t ViewGroup container, Bundle savedInstanceState) { 
 
\t \t View view = inflater.inflate(R.layout.fragment_persons_list, container, false); 
 
\t \t 
 
\t \t //prepare progress Dialog 
 
\t \t progressDialog = new ProgressDialog(curActivity); 
 
\t \t progressDialog.setMessage("Wait..."); 
 
\t \t progressDialog.setIndeterminate(true); 
 
\t \t progressDialog.setOnDismissListener(new OnDismissListener() { 
 
\t \t \t 
 
\t \t \t @Override 
 
\t \t \t public void onDismiss(DialogInterface dialog) { 
 
\t \t \t \t //make FragmentTransaction.commit() here; 
 
\t \t \t \t 
 
\t \t \t \t //but it's recommended to pass control to your Activity 
 
\t \t \t \t //via an Interface and manage fragments there. 
 
\t \t \t } 
 
\t \t }); 
 
\t \t 
 
\t \t lv = (ListView) view.findViewById(R.id.lv_out1); 
 
\t \t lv.setOnItemClickListener(new OnItemClickListener() { 
 

 
\t \t \t @Override 
 
\t \t \t public void onItemClick(AdapterView<?> parent, final View view, 
 
\t \t \t \t \t final int position, long id) { 
 
\t \t \t \t 
 
\t \t \t \t //START PROGRESS DIALOG HERE 
 
\t \t \t \t progressDialog.show(); 
 
\t \t \t \t 
 
\t \t \t \t Cursor c = (Cursor) parent.getAdapter().getItem(position); 
 

 
\t \t \t \t // create Loader 
 
\t \t \t \t getLoaderManager().restartLoader(1, \t null, curFragment); 
 
\t \t \t } 
 
\t \t }); 
 

 
\t \t return view; 
 
\t } 
 
    
 
\t @Override 
 
\t public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 
 
\t \t switch (loader.getId()) { 
 
\t \t case 1: 
 
\t \t \t //dismiss dialog and call progressDialog.onDismiss() listener 
 
\t \t \t progressDialog.dismiss(); 
 
\t \t \t break; 
 

 
\t \t default: 
 
\t \t \t break; 
 
\t \t } 
 
\t }

Problemi correlati