Android 如何根据异步请求的结果更改片段

Android 如何根据异步请求的结果更改片段,android,android-fragments,android-asynctask,loader,asynctaskloader,Android,Android Fragments,Android Asynctask,Loader,Asynctaskloader,我希望根据对本地数据库的异步请求的结果来管理屏幕上的片段。 例如: 1.转到数据库 2.获得结果 3.交付结果后,选择应向用户显示的片段。 (类似于下面的代码)。 公共类MainActivity扩展活动{ @凌驾 创建时受保护的void(Bundle savedInstanceState){ super.onCreate(savedInstanceState); getLoaderManager().restartLoader(0,null,新的LoaderManager.LoaderCallb

我希望根据对本地数据库的异步请求的结果来管理屏幕上的片段。 例如:
1.转到数据库
2.获得结果
3.交付结果后,选择应向用户显示的片段。
(类似于下面的代码)。

公共类MainActivity扩展活动{
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
getLoaderManager().restartLoader(0,null,新的LoaderManager.LoaderCallbacks(){
@凌驾
公共加载器onCreateLoader(int-id,Bundle-args){
返回新的MyLoader(MainActivity.this);
}
@凌驾
public void onLoadFinished(加载程序,布尔数据){
FragmentTransaction FragmentTransaction=getFragmentManager().beginTransaction();
如果(数据){
fragmentTransaction.add(新的MyFragment1(),null);
}否则{
fragmentTransaction.add(新的MyFragment2(),null);
}
fragmentTransaction.addToBackStack(空);
fragmentTransaction.commit();
}
@凌驾
公共void onLoaderReset(加载器){
}
});
}
私有静态类MyLoader扩展了AsyncTaskLoader{
公共MyLoader(上下文){
超级(上下文);
}
@凌驾
公共布尔loadInBackground(){
试一试{
Thread.sleep(1000);//让我们假装正在本地数据库中查找某些内容
}捕捉(中断异常e){
e、 printStackTrace();
}
return(System.currentTimeMillis()%2)==0;//随机返回true或false
}
}
}
因此,我得到:
java.lang.IllegalStateException:无法在onLoadFinished内执行此操作

我可以愚弄原因系统,将片段事务包装成可运行事务,并在处理程序上调用它,但似乎我仍然会得到一个异常,即加载程序结果将在saveInstanceState()调用和onStop()之间传递。 我不能使用“commitAllowingStateLoss”方法,因为我依赖于片段的有效堆栈,我不希望它被弄乱


有人能建议如何以适当的方式做到这一点吗?

您首先要阅读的是一篇由谷歌开发人员撰写的文章,其中解释了什么是状态丢失以及如何避免状态丢失。你也可以看看我是如何避免这种情况的。但简短的故事是,碎片事务和状态丢失是一个巨大的痛苦,我已经读了一整天这篇文章:)。很明显,我应该小心不要在onStateSave之后修改片段,但我绝对不清楚如何在不破坏整个系统的情况下实现这一点。我已经考虑过将我的“更新片段”指令存储在一个可运行的队列中,如果它们发生在状态保存之后,并在onStart中逐个执行。但这看起来像一个黑客,我认为应该有一个适当的方法来做到这一点。我确信,作为异步操作的结果来管理片段是一个常见的问题。相信我,不管怎样,这都会让人感觉像是一个黑客。我最后做的是将片段设置为一个保留实例,然后在片段中创建一个成员变量,该变量跟踪其自身对用户可见的状态。然后,每当需要捕获所有片段的状态时,我就从活动中设置该变量。然后,当配置更改出现时(如方向更改),我只是询问片段是否应该显示。如果它说是,那么我会将其添加到活动中。这是你上面提到的一个版本。看来这是唯一的办法。
public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getLoaderManager().restartLoader(0, null, new LoaderManager.LoaderCallbacks<Boolean>() {
        @Override
        public Loader<Boolean> onCreateLoader(int id, Bundle args) {
            return new MyLoader(MainActivity.this);
        }

        @Override
        public void onLoadFinished(Loader<Boolean> loader, Boolean data) {
            FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
            if (data) {
                fragmentTransaction.add(new MyFragment1(), null);
            } else {
                fragmentTransaction.add(new MyFragment2(), null);
            }
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }

        @Override
        public void onLoaderReset(Loader<Boolean> loader) {
        }
    });
}

private static class MyLoader extends AsyncTaskLoader<Boolean> {

    public MyLoader(Context context) {
        super(context);
    }

    @Override
    public Boolean loadInBackground() {
        try {
            Thread.sleep(1000); //Let's pretend we are looking for something in local db
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return (System.currentTimeMillis() % 2) == 0; // return true or false randomly
    }
}
}