11

我有一个使用加载器回调从服务器加载数据列表的活动。我必须将数据列出到一个扩展的片段中

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 中引用了该示例,但这些示例在片段中包含加载程序,而不是在活动中。

谁能帮我解决这个问题,我可以在不从片段中调用加载程序的情况下修复它!

4

3 回答 3

14

Atlast,我已经找到了解决这个问题的方法。创建一个设置空消息的句柄并调用该处理程序 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.
于 2012-09-14T09:17:41.813 回答
8

根据 onLoadFinished() 方法的 Android 文档:

请注意,通常不允许应用程序在此调用中提交片段事务,因为它可能在保存活动状态后发生。有关这方面的进一步讨论,请参阅 FragmentManager.openTransaction()。

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

(注意:将该链接复制/粘贴到您的浏览器中...... StackOverflow 处理得不好......)

因此,您根本不应该加载处于该状态的片段。如果你真的不想把Loader放到Fragment里面,那么你需要在你的Activity的onCreate()方法中初始化Fragment,然后当onLoadFinished发生时,简单的在你的Fragment上调用一个方法。

一些粗略的伪代码如下:

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() 方法来更新您的片段。但希望这将为您指明正确的方向。

于 2012-09-07T16:36:40.790 回答
0

正如@kwazi 回答的那样,这是一个糟糕的用户体验FragmentTransition.commit()onLoadFinished()我通过使用 ProgressDialog 找到了此事件的解决方案。

最初是ProgressDialog.setOnDismissListener(new listener)为了观看onLoadFinished().progressDialog.show()之前所做的进一步而创建的getLoaderManager().restartLoader()。并最终progressDialog.dismiss()放入onLoadFinished(). 这种方法允许不绑定主 UI 线程和 Loader 的线程。

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

于 2015-03-20T11:25:40.623 回答