Android Fragment之間的數(shù)據(jù)交流

Android Fragment Argument

眾所周知纹坐,多用Fragment能打造更靈活的程序。
本文通過(guò)一個(gè)淺顯的例子,來(lái)闡釋fragment之間基于Argument的數(shù)據(jù)交流决左。

簡(jiǎn)單說(shuō)一下要實(shí)現(xiàn)的目標(biāo):
本項(xiàng)目包含兩個(gè)活動(dòng)和分別依附于這兩個(gè)活動(dòng)的兩個(gè)Fragment。
簡(jiǎn)單起見(jiàn),這里分別為他們起名為:FirstActivity哆窿、FirstFragment链烈、SecondActivitySecondFragment挚躯。
他們之間的關(guān)系是:
兩個(gè)活動(dòng)只負(fù)責(zé)容納(或者說(shuō)托管)其對(duì)應(yīng)的兩個(gè)Fragment强衡。而具體的顯示和與用戶交互則由Fragment負(fù)責(zé)。

為了突出重點(diǎn)码荔,這里只實(shí)現(xiàn)最簡(jiǎn)單的功能:

  • FirstFragment中顯示一個(gè)ListView漩勤,這個(gè)ListView顯示一串編程語(yǔ)言的名稱。
  • 當(dāng)用戶點(diǎn)擊其中的item時(shí)缩搅,會(huì)跳轉(zhuǎn)到SecondActivity越败。
  • 這時(shí)SecondActivityonCreate()方法啟動(dòng),在其中加載SecondFragment硼瓣。
  • 最后SecondFragmentTextView控件根據(jù)傳過(guò)來(lái)的信息顯示相應(yīng)的編程語(yǔ)言的名字究飞。

如圖:


就是這個(gè)意思

在代碼中實(shí)現(xiàn)時(shí),FirstActivitySecondActivity甚至都不需要對(duì)應(yīng)的Layout資源文件堂鲤。因?yàn)樗鼈兾ㄒ坏淖饔弥皇菫镕ragment提供容器亿傅,所以這里只需要在java代碼中為兩個(gè)Activity設(shè)置contentView即可:

setContentView(R.layout.common_fragment_container);

這個(gè)名為common_fragment_container的布局文件提供了一個(gè)FrameLayout來(lái)作為Fragment的容器:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

根據(jù)我們的構(gòu)想,當(dāng)用戶點(diǎn)擊FirstFragment中的ListView的item時(shí)瘟栖,應(yīng)該跳轉(zhuǎn)到SecondActivity葵擎。
為此,我們?cè)?code>SecondActivity中定義靜態(tài)方法:


    private final static String 
    EXTRA_LANGUAGE_PICKED = "language_picked"; //鍵

    
//靜態(tài)方法半哟,提供從別的活動(dòng)跳轉(zhuǎn)到SecondActivity
public static Intent newIntent(Context packageContext, String languagePicked) {
        Intent intent = new Intent(packageContext, SecondActivity.class);
        intent.putExtra(EXTRA_LANGUAGE_PICKED, languagePicked);
        return intent;
    }

FirstFragment中ListView item的點(diǎn)擊回調(diào):

public class FirstFragment extends Fragment {

    ListView mList;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_first, container, false);
        mList = v.findViewById(R.id.list);
//點(diǎn)擊回調(diào)
        mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Resources resources = getResources();
//得到資源文件中定義的字符串?dāng)?shù)組
                String[] languages = 
resources.getStringArray(R.array.languages);
                String str = languages[position];
                Intent intent = SecondActivity.newIntent(
getActivity(), str);
//啟動(dòng)SecondActivity
                startActivity(intent);
            }
        });
        return v;

    }
}

當(dāng)FirstFragment通過(guò)startActivity(intent)啟動(dòng)SecondActivity之后酬滤。
SecondActivity并不直接與用戶交互。

它要做的是:

  • 將傳入的intent中的用戶點(diǎn)擊的編程語(yǔ)言名稱取出來(lái)寓涨;
  • 然后傳給SecondFragment盯串。由SecondFragment將它顯示出來(lái)。

SecondFragment想從SecondActivity那兒取到數(shù)據(jù)有兩種方式:

第一種比較直接:

SecondFragment簡(jiǎn)單粗暴地通過(guò)getActivity()方法得到托管自己的SecondActivity戒良;
然后通過(guò)getIntent()方法得到從FirstFragment中傳過(guò)來(lái)的Intent對(duì)象嘴脾;
最后得到其中的extra信息。

這種方式雖然簡(jiǎn)單蔬墩,但也有代價(jià)译打。那就是破壞了封裝。使得SecondFragment不能被復(fù)用拇颅。因?yàn)榇藭r(shí)它還承擔(dān)了的工作奏司。

第二種方式比較復(fù)雜,但也更靈活:附加argument給Fragment:

要附加argument給Fragment樟插,需要調(diào)用Fragment.setArguments(Bundle)方法韵洋。而且必須是在fragment創(chuàng)建后竿刁,添加給Activity之前。
因此搪缨,一般的慣用做法是在Fragment類中添加newInstance()靜態(tài)方法食拜。
通過(guò)這個(gè)方法完成fragment實(shí)例以及Bundle對(duì)象的創(chuàng)建,
最后再把a(bǔ)rgument放入bundle對(duì)象中副编,并附加給fragment:

//SecondFragment
public class SecondFragment extends Fragment {

private static final String 
ARG_LANGUAGE_PICKED = "arg_language_picked";

    TextView mText;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        
        View v = inflater.inflate(R.layout.fragment_second, container, false);
        mText = v.findViewById(R.id.language_picked);
        String languagePicked 
= getArguments().getString(ARG_LANGUAGE_PICKED);
        mText.setText(languagePicked);
        return v;
    }

//newInstance()方法
    public static Fragment newInstance(String languagePicked) {
        Bundle bundle = new Bundle();
        bundle.putSerializable(ARG_LANGUAGE_PICKED, languagePicked);

        Fragment SecondFragmentInstance = new SecondFragment();
        SecondFragmentInstance.setArguments(bundle);
        return SecondFragmentInstance;
    }

}

現(xiàn)在我們有了這個(gè)方法负甸,又得到了FirstFragment傳入的Intent對(duì)象中的extra信息languagePicked
我們只需要在SecondActivityonCreate()方法中痹届,將languagePicked作為參數(shù)傳入SecondFragment.newInstance()方法呻待;
即可實(shí)現(xiàn),在SecondFragment創(chuàng)建之后队腐,被添加給SecondActivity之前蚕捉;
SecondFragment裝載argument

//SecondActivity
public class SecondActivity extends AppCompatActivity {

private final static String 
EXTRA_LANGUAGE_PICKED = "language_picked";

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//使用通用的Fragment容器,
setContentView(R.layout.common_fragment_container);
//因?yàn)槟壳皟蓚€(gè)Activity的布局中
//其實(shí)都只需要一個(gè)用于容納Fragment的frameLayout
       
        //要想在Activity中創(chuàng)建Fragment柴淘,先要得到FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            //在firstActivity中通過(guò)Intent跳轉(zhuǎn)到secondActivity迫淹,
            //SecondActivity創(chuàng)建之后,從傳入的Intent中得到extra信息为严,
            //然后根據(jù)這個(gè)信息來(lái)創(chuàng)建secondFragment實(shí)例敛熬,
            //得到的信息將用來(lái)作為參數(shù),傳入secondFragment的newInstance()方法
            String languagePicked = 
getIntent().getStringExtra(EXTRA_LANGUAGE_PICKED);
//SecondFragment.newInstance()方法
            fragment = SecondFragment.newInstance(languagePicked);

            fragmentManager.beginTransaction()
                    .add(R.id.fragment_container, fragment)
                    .commit();
        }


    }

    //靜態(tài)方法梗脾,提供從別的活動(dòng)跳轉(zhuǎn)到自身的Intent
    public static Intent newIntent(Context packageContext, String languagePicked) {
        Intent intent = new Intent(packageContext, SecondActivity.class);
        intent.putExtra(EXTRA_LANGUAGE_PICKED, languagePicked);
        return intent;
    }
}

這一做法的靈活之處就在于:
SecondFragment雖然需要得到數(shù)據(jù),但是它不再親自去盹靴,
而是由托管它的Activity(此處是SecondActivity)來(lái)負(fù)責(zé)提供數(shù)據(jù)炸茧。
如此一來(lái),就實(shí)現(xiàn)了SecondActivity的復(fù)用稿静。
倘若現(xiàn)在有一個(gè)ThirdActivity也想要托管SecondFragment梭冠,那它只要能提供數(shù)據(jù)(類似于SecondActivity提供的languagePicked),那它就一樣可以其onCreate()方法中作出類似的實(shí)現(xiàn)改备。
-- end --

水平有限控漠,難免紕漏,如有錯(cuò)誤悬钳,歡迎指正盐捷。
諸君共勉:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市默勾,隨后出現(xiàn)的幾起案子碉渡,更是在濱河造成了極大的恐慌,老刑警劉巖母剥,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滞诺,死亡現(xiàn)場(chǎng)離奇詭異形导,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)习霹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)朵耕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人淋叶,你說(shuō)我怎么就攤上這事阎曹。” “怎么了爸吮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵芬膝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我形娇,道長(zhǎng)锰霜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任桐早,我火速辦了婚禮癣缅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哄酝。我一直安慰自己友存,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布陶衅。 她就那樣靜靜地躺著屡立,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搀军。 梳的紋絲不亂的頭發(fā)上膨俐,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音罩句,去河邊找鬼焚刺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛门烂,可吹牛的內(nèi)容都是我干的乳愉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼屯远,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔓姚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起慨丐,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赂乐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后咖气,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體挨措,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挖滤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浅役。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斩松。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖觉既,靈堂內(nèi)的尸體忽然破棺而出惧盹,到底是詐尸還是另有隱情,我是刑警寧澤瞪讼,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布钧椰,位于F島的核電站,受9級(jí)特大地震影響符欠,放射性物質(zhì)發(fā)生泄漏嫡霞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一希柿、第九天 我趴在偏房一處隱蔽的房頂上張望诊沪。 院中可真熱鬧,春花似錦曾撤、人聲如沸端姚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)渐裸。三九已至,卻和暖如春装悲,著一層夾襖步出監(jiān)牢的瞬間昏鹃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工衅斩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盆顾,地道東北人怠褐。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓畏梆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奈懒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奠涌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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