传递方向的不同:
①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>
视频资料:慕课网,http://www.imooc.com/video/2504