片段MyFragment不附到活动片段、MyFragment、不附到

2023-09-12 02:33:19 作者:满是深爱

我创建了一个小的测试应用程序,它重新presents我的问题。 我使用ActionBarSherlock实现制表符(福尔摩斯)片段。

我的code: TestActivity.java

 公共类TestActivity扩展SherlockFragmentActivity {
    私人ActionBar的动作条;

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        setupTabs(savedInstanceState);
    }

    私人无效setupTabs(包savedInstanceState){
        动作条= getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        addTab1();
        addTab2();
    }

    私人无效addTab1(){
        标签TAB1 = actionBar.newTab();
        tab1.setTag(1);
        串tabText =1;
        tab1.setText(tabText);
        tab1.setTabListener(新TabListener&其中; MyFragment>(TestActivity.this,1,MyFragment.class));

        actionBar.addTab(TAB1);
    }

    私人无效addTab2(){
        标签TAB1 = actionBar.newTab();
        tab1.setTag(2);
        串tabText =2;
        tab1.setText(tabText);
        tab1.setTabListener(新TabListener&其中; MyFragment>(TestActivity.this,2,MyFragment.class));

        actionBar.addTab(TAB1);
    }
}
 

TabListener.java

 公共类TabListener<吨延伸SherlockFragment>实现com.actionbarsherlock.app.ActionBar.TabListener {
    私人最终SherlockFragmentActivity mActivity;
    私人最终字符串MTAG;
    私人最终类别< T> mClass;

    公共TabListener(SherlockFragmentActivity活动,字符串变量,类< T> CLZ){
        mActivity =活动;
        MTAG =标签;
        mClass = CLZ;
    }

    / *下面是每个ActionBar.TabListener回调* /

    公共无效onTabSelected(TAB键,FragmentTransaction英尺){
        SherlockFragment preInitializedFragment =(SherlockFragment)mActivity.getSupportFragmentManager()findFragmentByTag(MTAG)。

        //检查片段已初始化
        如果(preInitializedFragment == NULL){
            //如果没有,实例化并把它添加到活动
            SherlockFragment mFragment =(SherlockFragment)SherlockFragment.instantiate(mActivity,mClass.getName());
            ft.add(android.R.id.content,mFragment,MTAG);
        } 其他 {
            ft.attach(preInitializedFragment);
        }
    }

    公共无效onTabUnselected(TAB键,FragmentTransaction英尺){
        SherlockFragment preInitializedFragment =(SherlockFragment)mActivity.getSupportFragmentManager()findFragmentByTag(MTAG)。

        如果(preInitializedFragment!= NULL){
            //分离的片段,因为另一个被连接
            ft.detach(preInitializedFragment);
        }
    }

    公共无效onTabReselected(TAB键,FragmentTransaction英尺){
        //用户选择已经选择的选项卡。通常什么也不做。
    }
}
 

MyFragment.java

 公共类MyFragment扩展SherlockFragment {

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        新的AsyncTask<虚空,虚空,虚空>(){

            @覆盖
            保护无效doInBackground(虚空...... PARAMS){
                尝试 {
                    视频下载(2000);
                }赶上(InterruptedException的前){
                }
                返回null;
            }

            @覆盖
            保护无效onPostExecute(无效的结果){
                。getResources()的getString(R.string.app_name);
            }

        }。执行();
    }
}
 
如何像丁草莓一样幸福 MODERN SKY LAB 昆明 本周活动预告

我已经添加了视频下载部分模拟下载数据。在code。在 onPostExecute 是模拟使用片段

当我旋转屏幕非常快的横向和纵向的,我得到一个异常的 onPostExecute code:

  

java.lang.IllegalStateException:片段MyFragment {410f6060}不   连接到活动

我想这是因为新的 MyFragment 在此期间已创建,并附着在的AsyncTask 完成。在 onPostExecute 的code呼吁一个独立的 MyFragment

但我怎么才能解决这个问题?

解决方案

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

  

返回如果片段正在增加它的活动。

  @覆盖
保护无效onPostExecute(无效的结果){
    如果(isAdded()){
        。getResources()的getString(R.string.app_name);
    }
}
 

要避免 onPostExecute 被调用的时候,片段未连接到活动是取消的AsyncTask 暂停或停止片段时。然后 isAdded()就没有必要了。不过,最好是保持这种检查到位。

I've created a small test app which represents my problem. I'm using ActionBarSherlock to implement tabs with (Sherlock)Fragments.

My code: 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();
    }
}

I've added the Thread.sleep part to simulate downloading data. The code in the onPostExecute is to simulate use of the Fragment.

When I rotate the screen very fast between landscape and portrait, I get an Exception at the onPostExecute code:

java.lang.IllegalStateException: Fragment MyFragment{410f6060} not attached to Activity

I think it's because a new MyFragment has been created in the meantime, and was attached to the Activity before the AsyncTask finished. The code in onPostExecute calls upon a unattached MyFragment.

But how can I fix this?

解决方案

I've found the very simple answer: isAdded():

Return true if the fragment is currently added to its activity.

@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. Then isAdded() would not be necessary anymore. However, it is advisable to keep this check in place.