фиксация фрагмента из onLoadFinished в рамках activity


У меня есть действие, которое загружает список данных с сервера, используя обратные вызовы загрузчика. Я должен перечислить данные в фрагмент, который расширяется

SherlockListFragment 

Я попытался зафиксировать фрагмент с помощью

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

В onLoadFinished и это дает IllegalStateException говоря

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

Я привел пример в actionbar sherlock, но эти примеры имеют загрузчики внутри фрагментов, а не действия.

Может ли кто-нибудь помочь мне с этим o, чтобы я мог это исправить без вызова загрузчика из фрагмента!

3 11

3 ответа:

Атласт, я нашел решение этой проблемы. Создайте дескриптор, устанавливающий пустое сообщение, и вызовите этот обработчик onLoadFinished(). Код похож на этот.

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

В обработчике,

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
        }
    }
}; 

Количество фрагментов зависит от требования.

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

Согласно документам Android по методу onLoadFinished ():

Обратите внимание, что обычно приложению не разрешается совершать фрагментарные транзакции во время этого вызова, так как это может произойти после сохранения состояния действия. Смотрите Раздел FragmentManager.openTransaction() для дальнейшего обсуждения этого вопроса.

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

(Примечание: скопируйте / вставьте эту ссылку в ваш браузер... StackOverflow не справляется с этим хорошо..)

Таким образом, вы просто никогда не должны загружать фрагмент в этом состоянии. Если вы действительно не хотите помещать загрузчик во фрагмент, то вам нужно инициализировать фрагмент в вашем методе onCreate() действия, а затем, когда onLoadFinished произойдет, просто вызовите метод на вашем фрагменте.

Некоторый грубый псевдокод выглядит следующим образом:

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);
     } 
Очевидно, вы захотите использовать правильный объект.. и правильный загрузчик, и, вероятно, определить полезный метод setData() для обновления вашего фрагмента. Но, надеюсь, это укажет вам правильное направление.

Как ответил @kwazi, это плохой пользовательский опыт для вызова FragmentTransition.commit() из onLoadFinished(). Я нашел решение для этого события с помощью ProgressDialog.

Впервые создан ProgressDialog.setOnDismissListener(new listener) для наблюдения за onLoadFinished(). Далее я делаю progressDialog.show() Перед getLoaderManager().restartLoader(). И в конце концов поместить progressDialog.dismiss() в onLoadFinished(). Такой подход позволяет не связывать основной поток пользовательского интерфейса и поток загрузчика.

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

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

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

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

		default:
			break;
		}
	}