commit fragment from onLoadFinished within activity

后端 未结 3 1369
一向
一向 2020-12-31 10:57

I have an activity which loads a data list from the server using loader callbacks. I have to list out the data into a fragment which extends

SherlockListFra         


        
相关标签:
3条回答
  • 2020-12-31 11:23

    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.

    0 讨论(0)
  • 2020-12-31 11:36

    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.
    
    0 讨论(0)
  • 2020-12-31 11:45

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

    0 讨论(0)
提交回复
热议问题