Fragment 与 Activity 通信

前言

  • 本来打算把 Fragment 的内容写完,结果写着写着发现这个篇幅已经够长了,所以就先写通信这一块了,其他的另起篇幅

正文

一、 Fragment 与 Activity 通信

  • 所有的 Fragment 都是依附于 Activity 存在的,而通信则是 Fragment 与 Activity 之间相互传递数据。

  • 一个 Activity 可以替换多个 Fragment ,Activity 就是这多个 Fragment 的管理者,考虑到 Fragment 的复用性,尽量降低 Fragment 与 Fragment 之间的耦合,不要用一个 Fragment 来操作另一个 Fragment,使用 Activity 来操作 Fragment

1. Activity 向 Fragment 传递数据
通过 bundle
  • 在动态添加 Fragment 的过程中,我们在 Activity 中通过 Fragment.setArguments() 的方法为 Fragment 提供数据,setArguments 方法需要传递一个 Bundle,把需要传递的数据放在 Bundle 中即可
Bundle bundle = new Bundle();
bundle.putString("name","zhangsan");
firstFragment.setArguments(bundle);
  • 在 Fragment 中,在 onAttach() 函数中通过调用 getArguments() 获得一个 Bundle 对象,从而获取我们提供的数据。
    @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. 实现Fragment 中改变 Activity 中的控件内容

通过设置回调接口来实现该效果

  • 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
     *点击第二个按钮触发自定义接口中的方法,具体做什么就看宿主 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 的时候触发该接口中的方法
                onBt2nClickListener.OnBt2nClick();
                break;
        }


    }

    private OnBt2nClickListener onBt2nClickListener;


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

    /**
     * 自定义回调接口
     */
    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("珞神");
            }
        });
    }
}

这样就实现了,在点击 Fragment 中的按钮的时候,改变 Activity 中的 TextView 显示的内容,并且降低 Fragment 与 Activity 的耦合性,并增强了 Fragment 的复用性,哪个 Activity 都能用这个 Fragment

4. 实现 Fragment 来操作另一个 Fragment

Fragment1 操作另一个 Fragment2,不应在Fragment1 中直接来操作,应该交给他们共同的宿主 Activity 来操作,也是通过设置接口来实现。

测试逻辑概述: 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 实现了此接口
                if (getActivity() instanceof OnBt2nClickListener) {

                    //当需要切换 Activity 中的 TextView 的时候触发该接口中的方法
                    ((OnBt2nClickListener) getActivity()).OnBt2nClick();
                }
                break;
        }


    }

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

    /**
     * 自定义回调接口
     */
    public interface OnBt2nClickListener {

        public void OnBt2nClick();

    }
}

注意: 这里的回调采用了另一种方式:

//如果宿主 Activity 实现了此接口
if (getActivity() instanceof OnBt2nClickListener) {

    //当需要切换 Activity 中的 TextView 的时候触发该接口中的方法
    ((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 的时候触发该接口中的方法
            ((OnBt22222nClickListener) getActivity()).OnBt22222nClick();
        }


    }

    private OnBt22222nClickListener onBt22222nClickListener;-->


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

    /**
     * 自定义回调接口
     */
    public interface OnBt22222nClickListener {

        public void OnBt22222nClick();

    }


}

注意: SecondFragment 中的回调设置与 FirstFragment 中的一样,我试过按照常规方式 ( 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 中回调的点击事件
    @Override
    public void OnBt2nClick() {
        textView.setText("珞神");
        if (second == null) {
            second = new SecondFragment();
            second.setOnBt22222nClickListener(this);
        }

    }

    //SecondFragment 中回调的点击事件
    @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();

至此,完结如有错误和遗漏,一经发现,必然改正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容