传递方向的不同:
①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>