片段 MyFragment 未附加到 Activity

新手上路,请多包涵

我创建了一个代表我的问题的小型测试应用程序。我正在使用 ActionBarSherlock 来实现带有 (Sherlock)Fragments 的选项卡。

我的代码: TestActivity.java

 public class TestActivity extends SherlockFragmentActivity {
    private ActionBar actionBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupTabs(savedInstanceState);
    }

    private void setupTabs(Bundle savedInstanceState) {
        actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        addTab1();
        addTab2();
    }

    private void addTab1() {
        Tab tab1 = actionBar.newTab();
        tab1.setTag("1");
        String tabText = "1";
        tab1.setText(tabText);
        tab1.setTabListener(new TabListener<MyFragment>(TestActivity.this, "1", MyFragment.class));

        actionBar.addTab(tab1);
    }

    private void addTab2() {
        Tab tab1 = actionBar.newTab();
        tab1.setTag("2");
        String tabText = "2";
        tab1.setText(tabText);
        tab1.setTabListener(new TabListener<MyFragment>(TestActivity.this, "2", MyFragment.class));

        actionBar.addTab(tab1);
    }
}

TabListener.java

 public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener {
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

        // Check if the fragment is already initialized
        if (preInitializedFragment == null) {
            // If not, instantiate and add it to the activity
            SherlockFragment mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            ft.attach(preInitializedFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

        if (preInitializedFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(preInitializedFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

MyFragment.java

 public class MyFragment extends SherlockFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result){
                getResources().getString(R.string.app_name);
            }

        }.execute();
    }
}

我添加了 Thread.sleep 部分来模拟下载数据。 onPostExecute 中的代码是模拟使用 Fragment

当我在横向和纵向之间快速旋转屏幕时,在 onPostExecute 代码处出现异常:

java.lang.IllegalStateException:片段 MyFragment{410f6060} 未附加到 Activity

我认为这是因为同时创建了一个新的 MyFragment ,并且在 AsyncTask 完成之前附加到了 Activity。 onPostExecute 中的代码调用未附加的 MyFragment

但是我该如何解决这个问题?

原文由 nhaarman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 331
2 个回答

我找到了非常简单的答案: isAdded()

如果片段当前已添加到其活动中,则返回 true

 @Override
protected void onPostExecute(Void result){
    if(isAdded()){
        getResources().getString(R.string.app_name);
    }
}

To avoid onPostExecute from being called when the Fragment is not attached to the Activity is to cancel the AsyncTask when pausing or stopping the Fragment 。那么 isAdded() 就不再需要了。但是,建议保留此检查。

原文由 nhaarman 发布,翻译遵循 CC BY-SA 3.0 许可协议

将此添加到您的 Fragment

 Activity activity;
@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    activity = context instanceof Activity ? (Activity) context : null;
}

然后用 活动 更改 getContext() 、 getActivity() 、 requireActivity() 或 requireContext()

原文由 Jose 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题