传递方向的不同:

①Activity----->Fragment:

在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法

②Fragment----->Activity:

需要在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口。

这样Fragment可调用该回调方法将数据传给Acyivity。


加载方式的不同:

①在XML文件中静态加载的Fragment与Activity中的数据传递

②在Activity代码中动态加载的Fragment与Activity中的数据传递


动态加载

那么,从Activity中传递消息给Fragment的话

我们需要在Activity中通过Bundle(数据包)的打包数据,然后通过setArguments()传递数据。

dynamicButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        MyFragment2 myFragment2 = new MyFragment2();//new一个Fragment对象
        FragmentManager fragmentManager = getFragmentManager();//获取Fragment管理器对象
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();//获取Fragment事务对象
        fragmentTransaction.add(R.id.fragment_layout, myFragment2);//在fragement_layout中填充Fragment对象
        fragmentTransaction.commit();//最后一定要提交才能显示fragment

        Bundle bundle = new Bundle();//new一个数据包
        bundle.putString("key", "从Activity往动态加载的Fragment传递消息");//将数据打包,键为key
        myFragment2.setArguments(bundle);//将数据包发送到fragment中
       }
    });


然后动态加载的Fragment通过getArguments()方法获取Bundlet(数据包)

returnButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        String msg = getArguments().getString("key");//获取键为key的对象,getArgument()返回的是Bundle数据包
        editText.setText(msg);//显示数据

        listener2.returnMSG("接收到动态加载的Fragment回传的消息");//这里回传数据给Activity,之后解释
       }
    });

这样总结一下,在动态加载Fragment的情况下,Activity传递数据给Fragment的步骤为:

在Activity中动态加载一个Fragment

创建一个Bundle数据包,并填充数据

用setArgument()发送数据包

在Fragment中调用getArgument()方法获取Bundle数据包

获取Bundle数据包中的数据


好,那么现在看下从Fragment中传递消息给Activity的步骤。

我们需要一个Fragment类中的内部接口,并定义一些方法来传递并接收数据。


public class MyFragment2 extends Fragment {
    MyListener2 listener2;
    public interface MyListener2{
        public void returnMSG(String code);
    }
    //省略其他方法
}


在Fragment里不需要实现接口中的方法,那是在Activity里面要完成的事。

在调用方法之前,我们先要获取一个MyListener2对象,这里将实现了MyListener接口的Activity强制转换(之后解释)


public class MyFragment2 extends Fragment {
    @Override
    public void onAttach(Activity activity) {//这里不懂的建议了解下Fragment的生命周期
        listener2 = (MyListener2) activity;//强制转换获得对象
        super.onAttach(activity);
    }
    //省略其他方法
}


在Fragment里面,我们只要

调用

MyListener2接口中的方法即可。

不管方法怎么执行


returnButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        String msg = getArguments().getString("key");
        editText.setText(msg);//获取Activity传递来的数据,上面已经解释过

        listener2.returnMSG("接收到动态加载的Fragment回传的消息");//不管方法如何实现,只管调用
       }
    });

然后,我们需要在Activity中实现Fragment中的MyListener接口中的方法

public class MainActivity extends Activity implements MyFragment2.MyListener2{

    //省略其他方法
    @Override
    public void returnMSG(String code) {
        returnText.setText(code);//在Activity中的TextView对象中显示传递过来的code值
    }
}


那么再总结一下,动态加载的Fragment传递数据给Activity的步骤有:

先在Fragment里面写一个内部接口,里面有一些方法,用来发送数据。

在Activity中实现Fragment中写的内部接口中的方法,用来接受并处理数据。

在onAttach方法中,将实现了接口的Activity强制转换成接口类型,获得对象。

在Fragment中使用接口中的方法,发送数据。


静态加载

静态加载的Fragment和Activity的数据传递比较简单。

在xml静态加载的fragment可以看成Activity中的组件,直接在Activity中用findViewById()就可以获得fragment中的组件。

那么,从Activity中传递消息给Fragment的话

我们只需要在Activity中通过Fragment管理器(Fragment)findFragmentById()或者findFragmentByTag()获取Fragment对象。

findFragmentById()是通过Fragment的id属性来获取Fragment对象

findFragmentByTag()是通过Fragment的tag属性来获取Fragment对象

id和tag都唯一的标识了一个Fragment组件。

staticButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        FragmentManager fragmentManager = getFragmentManager();//获取该Activity中的Fragment管理器
        MyFragment1 myFragment1 = (MyFragment1) fragmentManager.findFragmentById(R.id.fragment1);//通过id属性获取Fragment对象并强制转换
        myFragment1.setMSG("静态传输成功");//调用MyFragment类中的方法,通过Activity中的staticButton传递消息给Fragment中的组件
       }
    });


这个setMSG()方法是在Fragment中定义的(感觉好像是java的知识了,没什么好说的)

public class MyFragment1 extends Fragment {
    private String msg;
    public void setMSG(String msg){
        this.msg = msg;
    }
    public String getMSG(){
        return msg;
    }
}


除了这种方法外,还可以直接在Activity中用findViewById()就可以获得fragment中的组件。

值得注意的是,已经静态加载了的Fragment,不能用setArgument()进行数据传递,否则会爆出则会Fragment already active错误


静态加载的Fragment回传数据给Activity和动态加载时一样,这里就不赘述。

以下附上Demo源码

//主Activity
public class MainActivity extends Activity implements MyFragment1.MyListener1,MyFragment2.MyListener2{

    Button staticButton, dynamicButton;
    TextView returnText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        staticButton = (Button) findViewById(R.id.staticButton);
        dynamicButton = (Button) findViewById(R.id.dynamicButton);
        returnText = (TextView) findViewById(R.id.returnText);

        staticButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager fragmentManager = getFragmentManager();
                MyFragment1 myFragment1 = (MyFragment1) fragmentManager.findFragmentById(R.id.fragment1);
                myFragment1.setMSG("从Activity往静态加载的Fragment传递消息");
            }
        });


        dynamicButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MyFragment2 myFragment2 = new MyFragment2();
                FragmentManager fragmentManager = getFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                fragmentTransaction.add(R.id.fragment_layout, myFragment2);
                fragmentTransaction.commit();//动态加载Fragment

                Bundle bundle = new Bundle();
                bundle.putString("key", "从Activity往动态加载的Fragment传递消息");
                myFragment2.setArguments(bundle);//发送数据包
            }
        });

    }

    @Override
    public void returnMSG(String code) {
        returnText.setText(code);//实现MyListener接口
    }
}
//动态加载的Fragment
public class MyFragment2 extends Fragment {

    TextView descText;
    EditText editText;
    Button  returnButton;

    MyListener2 listener2;
    public interface MyListener2{
        public void returnMSG(String code);//内部接口
    }

    @Override
    public void onAttach(Activity activity) {
        listener2 = (MyListener2) activity;//将实现了MyListener接口的Activity强制转换
        super.onAttach(activity);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_fragment, container, false);
        descText = (TextView) view.findViewById(R.id.descText);
        editText = (EditText) view.findViewById(R.id.editText);
        returnButton = (Button) view.findViewById(R.id.returnButton);

        descText.setText("动态加载的Fragment:");
        returnButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String msg = getArguments().getString("key");//获取Activity传递来的数据包
                editText.setText(msg);

                listener2.returnMSG("接收到动态加载的Fragment回传的消息");
            }
        });
        return view;
    }
}
//静态加载的Fragment
public class MyFragment1 extends Fragment {

    TextView descText;
    EditText editText;
    Button  returnButton;

    private String msg;
    public void setMSG(String msg){
        this.msg = msg;
    }
    public String getMSG(){
        return msg;
    }

    private MyListener1 listener1;
    public interface MyListener1{
        public void returnMSG(String code);//内部接口
    }

    @Override
    public void onAttach(Activity activity) {
        listener1 = (MyListener1) activity;//将实现了MyListener接口的Activity强制转换
        super.onAttach(activity);
    }


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

        View view = inflater.inflate(R.layout.layout_fragment, container, false);
        descText = (TextView) view.findViewById(R.id.descText);
        editText = (EditText) view.findViewById(R.id.editText);
        returnButton = (Button) view.findViewById(R.id.returnButton);

        descText.setText("静态加载的Fragment:");
        returnButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                editText.setText(msg);
                listener1.returnMSG("接收到静态加载的Fragment回传的消息");
            }
        });
        return view;
    }
}
<!--主Activity的布局activity_main.xml-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:orientation="vertical">

    <TextView android:id="@+id/returnText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment回传的信息"/>
    <Button
        android:id="@+id/staticButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="静态传输"/>
    <Button
        android:id="@+id/dynamicButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动态传输"/>

    <!--静态加载的Fragment-->
    <fragment
        android:id="@+id/fragment1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="ahao.demo.MyFragment1"
        />
    <!--动态加载的Fragment的容器Layout-->
    <LinearLayout
        android:id="@+id/fragment_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </LinearLayout>
</LinearLayout>
<!--两个Fragment的布局xml-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView android:id="@+id/descText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="静/动态加载的Fragment:" />
    <EditText android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取的数据"/>
    <Button android:id="@+id/returnButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取并回传"/>
</LinearLayout>