commit fragment from onLoadFinished within activity

半世苍凉 提交于 2019-11-30 09:09:56
Aswathy P Krishnan

Atlast, I have found a solution to this problem. Create a handle setting an empty message and call that handler onLoadFinished(). The code is similar to this.

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

In the handler,

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

The number of fragments depend on the requirement.

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

As per the Android docs on the onLoadFinished() method:

Note that normally an application is not allowed to commit fragment transactions while in this call, since it can happen after an activity's state is saved. See FragmentManager.openTransaction() for further discussion on this.

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

(Note: copy/paste that link into your browser... StackOverflow is not handling it well..)

So you simply should never load a fragment in that state. If you really don't want to put the Loader in the Fragment, then you need to initialize the fragment in your onCreate() method of the Activity, and then when onLoadFinished occurs, simply call a method on your fragment.

Some rough pseudo code follows:

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

Obviously, you'd want to use the right object.. and the right loader, and probably define a useful setData() method to update your fragment. But hopefully this will point you in the right direction.

sanya5791

As @kwazi answered this is a bad user experience to call FragmentTransition.commit() from onLoadFinished(). I have found a solution for this event by using ProgressDialog.

First created ProgressDialog.setOnDismissListener(new listener) for watching the onLoadFinished(). Further i do progressDialog.show() before getLoaderManager().restartLoader(). And eventually place progressDialog.dismiss() in onLoadFinished(). Such approach allow do not bind main UI thread and Loader's thread.

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;
		}
	}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!