Fragment 與 Activity 通信

前言

  • 本來打算把 Fragment 的內(nèi)容寫完,結(jié)果寫著寫著發(fā)現(xiàn)這個篇幅已經(jīng)夠長了妒茬,所以就先寫通信這一塊了轰豆,其他的另起篇幅

正文

一、 Fragment 與 Activity 通信

  • 所有的 Fragment 都是依附于 Activity 存在的鸿染,而通信則是 Fragment 與 Activity 之間相互傳遞數(shù)據(jù)。

  • 一個 Activity 可以替換多個 Fragment 乞巧,Activity 就是這多個 Fragment 的管理者涨椒,考慮到 Fragment 的復用性,盡量降低 Fragment 與 Fragment 之間的耦合绽媒,不要用一個 Fragment 來操作另一個 Fragment蚕冬,使用 Activity 來操作 Fragment

1. Activity 向 Fragment 傳遞數(shù)據(jù)
通過 bundle
  • 在動態(tài)添加 Fragment 的過程中卖词,我們在 Activity 中通過 Fragment.setArguments() 的方法為 Fragment 提供數(shù)據(jù)陵霉,setArguments 方法需要傳遞一個 Bundle,把需要傳遞的數(shù)據(jù)放在 Bundle 中即可
Bundle bundle = new Bundle();
bundle.putString("name","zhangsan");
firstFragment.setArguments(bundle);
  • 在 Fragment 中穆役,在 onAttach() 函數(shù)中通過調(diào)用 getArguments() 獲得一個 Bundle 對象获三,從而獲取我們提供的數(shù)據(jù)旁蔼。
    @Override
public void onAttach(Context context) {
    super.onAttach(context);
    name = (String) getArguments().get("name");
}
2. 在Fragment中可以通過 getActivity 得到當前綁定的 Activity 的實例,然后進行操作疙教。
  • 假如 Fragment 依附的 Activity 中有這樣一個方法:
public String getName(){

    return "lisi";
}
  • 在 Fragment 中可以這樣獲取
HuiTuiZhanActivity activity = (HuiTuiZhanActivity) getActivity();
String name = activity.getName();
3. 實現(xiàn)Fragment 中改變 Activity 中的控件內(nèi)容

通過設置回調(diào)接口來實現(xiàn)該效果

  • Fragment 中的代碼如下所示:
package com.example.administrator.fragment_text.huituizhan;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

import com.example.administrator.fragment_text.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;


/**
 * Created by Administrator on 2017/4/10.
 */

public class FirstFragment extends Fragment {

    @BindView(R.id.editText)
    EditText editText;
    @BindView(R.id.btn)
    Button btn;
    Unbinder unbinder;
    @BindView(R.id.bt2n)
    Button bt2n;

    private String name;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        Log.i("FirstFragment", "onCreateView");
        View inflate = inflater.inflate(R.layout.huituizhan_first_fragment, container, false);
        unbinder = ButterKnife.bind(this, inflate);
        return inflate;
    }


    /**
     * 點擊第一個按鈕切換到 SecondFragment
     *點擊第二個按鈕觸發(fā)自定義接口中的方法牌芋,具體做什么就看宿主 Activity
     */
    @OnClick({R.id.btn, R.id.bt2n})
    public void onViewClicked(View view) {

        switch (view.getId()) {
            case R.id.btn:
                FragmentManager fragmentManager = getFragmentManager();

                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

                SecondFragment secondFragment = new SecondFragment();

                fragmentTransaction.hide(this);
//        fragmentTransaction.remove(this);
                fragmentTransaction.add(R.id.framelayout, secondFragment, "second");
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
                break;
            case R.id.bt2n:
                //當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
                onBt2nClickListener.OnBt2nClick();
                break;
        }


    }

    private OnBt2nClickListener onBt2nClickListener;


    public void setOnBt2nClickListener(OnBt2nClickListener onBt2nClickListener){
        this.onBt2nClickListener = onBt2nClickListener;
    }

    /**
     * 自定義回調(diào)接口
     */
    public interface OnBt2nClickListener{

        public void OnBt2nClick();

    }
}

  • Activity 中的代碼如下所示:
package com.example.administrator.fragment_text.huituizhan;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.example.administrator.fragment_text.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class HuiTuiZhanActivity extends AppCompatActivity {

    @BindView(R.id.framelayout)
    FrameLayout framelayout;
    @BindView(R.id.textView)
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hui_tui_zhan);
        ButterKnife.bind(this);

        FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();

        FirstFragment firstFragment = new FirstFragment();

        Bundle bundle = new Bundle();
        bundle.putString("name", "zhangsan");
        firstFragment.setArguments(bundle);
        fragmentTransaction.add(R.id.framelayout, firstFragment, "first").commit();



    }


    @Override
    protected void onResume() {
        super.onResume();
        FirstFragment first = (FirstFragment) getSupportFragmentManager().findFragmentByTag("first");
        first.setOnBt2nClickListener(new FirstFragment.OnBt2nClickListener() {
            @Override
            public void OnBt2nClick() {
                textView.setText("珞神");
            }
        });
    }
}

這樣就實現(xiàn)了,在點擊 Fragment 中的按鈕的時候松逊,改變 Activity 中的 TextView 顯示的內(nèi)容,并且降低 Fragment 與 Activity 的耦合性肯夏,并增強了 Fragment 的復用性经宏,哪個 Activity 都能用這個 Fragment

4. 實現(xiàn) Fragment 來操作另一個 Fragment

Fragment1 操作另一個 Fragment2,不應在Fragment1 中直接來操作,應該交給他們共同的宿主 Activity 來操作驯击,也是通過設置接口來實現(xiàn)烁兰。

測試邏輯概述: FirstFragment 中的按鈕切換 Activity 中的 TextView ,SecondFragment 中的按鈕切換 ThreeFragment

  • FirstFragment 中的代碼:
package com.example.administrator.fragment_text.huituizhan;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

import com.example.administrator.fragment_text.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;


/**
 * Created by Administrator on 2017/4/10.
 */

public class FirstFragment extends Fragment {

    @BindView(R.id.editText)
    EditText editText;
    @BindView(R.id.btn)
    Button btn;
    Unbinder unbinder;
    @BindView(R.id.bt2n)
    Button bt2n;

    private String name;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        Log.i("FirstFragment", "onCreateView");
        View inflate = inflater.inflate(R.layout.huituizhan_first_fragment, container, false);
        unbinder = ButterKnife.bind(this, inflate);
        editText.setText(name);
        return inflate;
    }

    /**
     * 點擊按鈕切換到 SecondFragment
     */
    @OnClick({R.id.btn, R.id.bt2n})
    public void onViewClicked(View view) {

        switch (view.getId()) {
            case R.id.btn:
                FragmentManager fragmentManager = getActivity().getSupportFragmentManager();

                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

                SecondFragment secondFragment = new SecondFragment();

                fragmentTransaction.hide(this);
                fragmentTransaction.add(R.id.framelayout, secondFragment, "second");
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
                break;
            case R.id.bt2n:
                //如果宿主 Activity 實現(xiàn)了此接口
                if (getActivity() instanceof OnBt2nClickListener) {

                    //當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
                    ((OnBt2nClickListener) getActivity()).OnBt2nClick();
                }
                break;
        }


    }

//    private OnBt2nClickListener onBt2nClickListener;
//
//
//    public void setOnBt2nClickListener(OnBt2nClickListener onBt2nClickListener){
//        this.onBt2nClickListener = onBt2nClickListener;
//    }

    /**
     * 自定義回調(diào)接口
     */
    public interface OnBt2nClickListener {

        public void OnBt2nClick();

    }
}

注意: 這里的回調(diào)采用了另一種方式:

//如果宿主 Activity 實現(xiàn)了此接口
if (getActivity() instanceof OnBt2nClickListener) {

    //當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
    ((OnBt2nClickListener) getActivity()).OnBt2nClick();
    }
  • SecondFragment 中的代碼:
package com.example.administrator.fragment_text.huituizhan;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

import com.example.administrator.fragment_text.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;


/**
 * Created by Administrator on 2017/4/10.
 */

public class SecondFragment extends Fragment {

    @BindView(R.id.editText)
    EditText editText;
    @BindView(R.id.btn)
    Button btn;
    Unbinder unbinder;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View inflate = inflater.inflate(R.layout.huituizhan_second_fragment, container, false);
        unbinder = ButterKnife.bind(this, inflate);
        Log.i("SecondFragment", "onCreateView");
        return inflate;
    }

    @OnClick(R.id.btn)
    public void onViewClicked() {
        if (getActivity() instanceof OnBt22222nClickListener) {

            //當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
            ((OnBt22222nClickListener) getActivity()).OnBt22222nClick();
        }


    }

    private OnBt22222nClickListener onBt22222nClickListener;-->


    public void setOnBt22222nClickListener(OnBt22222nClickListener onBt22222nClickListener) {-->
        this.onBt22222nClickListener = onBt22222nClickListener;-->
    }

    /**
     * 自定義回調(diào)接口
     */
    public interface OnBt22222nClickListener {

        public void OnBt22222nClick();

    }


}

注意: SecondFragment 中的回調(diào)設置與 FirstFragment 中的一樣徊都,我試過按照常規(guī)方式 ( setOnBt22222nClickListener 方式 ) 設置沪斟,切換 Fragment 的時候程序崩潰,而這種方式則沒問題暇矫,不知道為嘛 - -主之!

  • Activity 中的代碼:
package com.example.administrator.fragment_text.huituizhan;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.example.administrator.fragment_text.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class HuiTuiZhanActivity extends AppCompatActivity implements FirstFragment.OnBt2nClickListener, SecondFragment.OnBt22222nClickListener {

    @BindView(R.id.framelayout)
    FrameLayout framelayout;
    @BindView(R.id.textView)
    TextView textView;
    private SecondFragment second;
    private FirstFragment firstFragment;
    private ThreeFragment three;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hui_tui_zhan);
        ButterKnife.bind(this);

        FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();

        firstFragment = new FirstFragment();

        Bundle bundle = new Bundle();
        bundle.putString("name", "zhangsan");
        firstFragment.setArguments(bundle);
        fragmentTransaction.add(R.id.framelayout, firstFragment, "first").commit();


    }

    //FirstFragment 中回調(diào)的點擊事件
    @Override
    public void OnBt2nClick() {
        textView.setText("珞神");
        if (second == null) {
            second = new SecondFragment();
            second.setOnBt22222nClickListener(this);
        }

    }

    //SecondFragment 中回調(diào)的點擊事件
    @Override
    public void OnBt22222nClick() {
        FragmentManager fragmentManager = getSupportFragmentManager();

        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if (three == null) {

            three = new ThreeFragment();
        }
        if (second == null) {

            second = new SecondFragment();
        }
//        fragmentTransaction.hide(second);
//        fragmentTransaction.add(R.id.framelayout,three,"three");
        fragmentTransaction.replace(R.id.framelayout, three, "three");
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
}

5. 通過 getFragmentManager.findFragmentByTag() 或者 findFragmentById() 獲得任何 Fragment 實例,然后來操作 Fragment 中的方法李根。
  • 假如 Fragment 中有這樣一個方法:
    public String getName(){

        return "珞神";
    }
  • 在其宿主 Activity 中可以這樣操作:
FirstFragment first = (FirstFragment) getSupportFragmentManager().findFragmentByTag("first");
String name = first.getName();

至此槽奕,完結(jié)如有錯誤和遺漏,一經(jīng)發(fā)現(xiàn)房轿,必然改正粤攒!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末所森,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子夯接,更是在濱河造成了極大的恐慌焕济,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盔几,死亡現(xiàn)場離奇詭異晴弃,居然都是意外死亡,警方通過查閱死者的電腦和手機问欠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門肝匆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人顺献,你說我怎么就攤上這事旗国。” “怎么了注整?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵能曾,是天一觀的道長。 經(jīng)常有香客問我肿轨,道長寿冕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任椒袍,我火速辦了婚禮驼唱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驹暑。我一直安慰自己玫恳,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布优俘。 她就那樣靜靜地躺著京办,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帆焕。 梳的紋絲不亂的頭發(fā)上惭婿,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音叶雹,去河邊找鬼财饥。 笑死,一個胖子當著我的面吹牛折晦,可吹牛的內(nèi)容都是我干的佑力。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筋遭,長吁一口氣:“原來是場噩夢啊……” “哼打颤!你這毒婦竟也來了暴拄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤编饺,失蹤者是張志新(化名)和其女友劉穎乖篷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體透且,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡撕蔼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了秽誊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲸沮。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锅论,靈堂內(nèi)的尸體忽然破棺而出讼溺,到底是詐尸還是另有隱情,我是刑警寧澤最易,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布怒坯,位于F島的核電站,受9級特大地震影響藻懒,放射性物質(zhì)發(fā)生泄漏剔猿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一嬉荆、第九天 我趴在偏房一處隱蔽的房頂上張望归敬。 院中可真熱鬧,春花似錦鄙早、人聲如沸汪茧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至什往,卻和暖如春扳缕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背别威。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工躯舔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人省古。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓粥庄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親豺妓。 傳聞我的和親對象是個殘疾皇子惜互,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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