問題解決:Fragment not attached to Activity

1觅够、問題引入

在Fragment中執(zhí)行一段耗時任務(wù)菱属,在任務(wù)未結(jié)束的時候,重建Activity就會導致getActivity()null,所有用到getActivity()的地方都會引起空指針異常,如果使用了getResources()方法贫堰,就會導致Fragment not attached to Activity

為了重現(xiàn)這一異常享扔,我們編寫如下代碼:

  • FirstFragment.java
public class FirstFragment extends Fragment implements View.OnClickListener {
    private TextView tvMsg;
    private Button btnStartTask, btnRecreate;
    private static final String TAG = "FirstFragment";

    public FirstFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, container, false);
        tvMsg = (TextView) view.findViewById(R.id.tvMsg);
        btnStartTask = (Button) view.findViewById(R.id.btnStartTask);
        btnRecreate = (Button) view.findViewById(R.id.btnRecreate);
        btnStartTask.setOnClickListener(this);
        btnRecreate.setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnStartTask:
                // 模擬一個耗時任務(wù)
                new AsyncTask<Void, Void, Void>() {

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

                    @Override
                    protected void onPostExecute(Void aVoid) {
                        super.onPostExecute(aVoid);
                        Log.d(TAG, "getActivity = " + getActivity());
                        tvMsg.setText(getResources().getString(R.string.app_name));
                    }
                }.execute();
                break;
            case R.id.btnRecreate:
                // 重新創(chuàng)建MainActivity
                getActivity().recreate();
                break;
        }
    }
}
  • SecondFragment.java
public class SecondFragment extends Fragment {
    
    public SecondFragment() {
        // Required empty public constructor
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_second, container, false);
    }
}

  • fragment_first.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="cc.duduhuo.fragmentattachdemo.fragment.FirstFragment">

    <TextView
        android:id="@+id/tvMsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="The First Fragment" />

    <Button
        android:id="@+id/btnStartTask"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="耗時任務(wù)" />

    <Button
        android:id="@+id/btnRecreate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="重建Activity" />
</LinearLayout>
  • fragment_second.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cc.duduhuo.fragmentattachdemo.fragment.SecondFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="The Second Fragment" />

</FrameLayout>
  • MainActivity.java
public class MainActivity extends FragmentActivity {
    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mViewPager = (ViewPager) this.findViewById(R.id.pager);
        initial();
    }

    private void initial() {
        List<Fragment> fragmentList = new ArrayList<>();
        List<String> titleList = new ArrayList<>();
        fragmentList.add(new FirstFragment());
        fragmentList.add(new SecondFragment());
        titleList.add("First");
        titleList.add("Second");

        MyFragmentPageAdapter adapter = new MyFragmentPageAdapter(getSupportFragmentManager(), fragmentList, titleList);
        mViewPager.setAdapter(adapter);
    }

    private class MyFragmentPageAdapter extends FragmentPagerAdapter {
        private List<Fragment> fragmentList;
        private List<String> titleList;

        public MyFragmentPageAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList) {
            super(fm);
            this.fragmentList = fragmentList;
            this.titleList = titleList;
        }

        @Override
        public Fragment getItem(int position) {
            return (fragmentList == null || fragmentList.size() == 0) ? null : fragmentList.get(position);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return (titleList.size() > position) ? titleList.get(position) : "";
        }

        @Override
        public int getCount() {
            return fragmentList == null ? 0 : fragmentList.size();
        }
    }
}
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cc.duduhuo.fragmentattachdemo.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v4.view.PagerTabStrip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top" />
    </android.support.v4.view.ViewPager>
</LinearLayout>

當點擊FirstFragment里面的“耗時任務(wù)”按鈕時狱意,會執(zhí)行一個2000ms的任務(wù)(上面的代碼是用休眠2000ms代替一個耗時任務(wù))。如果點過之后靜靜等待2000ms烹吵,上面的TextView的文本就會變成FragmentAttachDemo碉熄,并不會報出任何異常。但是當我們點擊“耗時任務(wù)”按鈕之后年叮,在它還未執(zhí)行完畢時具被,點擊下面的“重建ACTIVITY”按鈕,很快程序就會崩潰只损。

控制臺打印出來的信息如下圖所示:


錯誤信息

除了點擊“重建ACTIVITY”按鈕之外一姿,點擊“耗時任務(wù)”按鈕之后立即旋轉(zhuǎn)手機屏幕也會導致此異常,因為默認情況下屏幕旋轉(zhuǎn)也會重建Activity跃惫。

2叮叹、問題解決

FirstFragmentonPostExecute()方法中的

tvMsg.setText(getResources().getString(R.string.app_name));

改為

if (isAdded()) {
    tvMsg.setText(getResources().getString(R.string.app_name));
}

isAdded()方法可以判斷當前的Fragment是否已經(jīng)添加到Activity中,只有當Fragment已經(jīng)添加到Activity中時才執(zhí)行getResources()等方法爆存。

另請參考:http://stackoverflow.com/questions/10919240/fragment-myfragment-not-attached-to-activity

當然蛉顽,以上只是引起該異常的一個例子,并不能解決所有“Fragment not attached to Activity”的問題先较。

3携冤、代碼下載

Demo代碼下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悼粮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子曾棕,更是在濱河造成了極大的恐慌扣猫,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翘地,死亡現(xiàn)場離奇詭異申尤,居然都是意外死亡,警方通過查閱死者的電腦和手機衙耕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門昧穿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人橙喘,你說我怎么就攤上這事时鸵。” “怎么了渴杆?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵寥枝,是天一觀的道長。 經(jīng)常有香客問我磁奖,道長囊拜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任比搭,我火速辦了婚禮冠跷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘身诺。我一直安慰自己蜜托,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布霉赡。 她就那樣靜靜地躺著橄务,像睡著了一般。 火紅的嫁衣襯著肌膚如雪穴亏。 梳的紋絲不亂的頭發(fā)上蜂挪,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音嗓化,去河邊找鬼棠涮。 笑死,一個胖子當著我的面吹牛刺覆,可吹牛的內(nèi)容都是我干的严肪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驳糯!你這毒婦竟也來了篇梭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤酝枢,失蹤者是張志新(化名)和其女友劉穎很洋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隧枫,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年谓苟,在試婚紗的時候發(fā)現(xiàn)自己被綠了官脓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡涝焙,死狀恐怖卑笨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仑撞,我是刑警寧澤赤兴,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站隧哮,受9級特大地震影響桶良,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沮翔,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一陨帆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧采蚀,春花似錦疲牵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妆够,卻和暖如春识啦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背责静。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工袁滥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灾螃。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓题翻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嵌赠,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容