背景
前两篇文章,我们已经了解了Fragment的基本使用以及Fragment生命周期,今天我们来看一下Fragment与Activity之间是如何通信,其中包括Activity向Fragment发消息,以及Fragment如何向Activity发消息。通信的方式有很多种,包括广播,Eventbus等,我们今天就介绍其中用的最为广泛的两种方式。
Activity向Fragment传递消息。
在我们使用Fragment进行初始化的时候可能需要传递参数,从而使用带参的构造函数,然而这是一件十分危险的事情,官网的说法如下
All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore.
当Fragment由于某些原因,比如说屏幕翻转,导致Fragment被销毁需要重建的时候,会调用onCreate()方法获取之前的状态,然后调用无参的构造函数取重建Fragment,所以如果没有无参的构造函数就会发生异常。可以使用getArguments通过Bundle去避免这个问题。
我们还是使用之前的例子如下图
其中中间是一个FrameLayout,下面是两个按钮,分别控制FragmentOne和FragmentTwo,两个Fragment中都有一个textiew,现在我们需要Activity将文本传递给Fragment并在textiew显示。
关键代码如下
FragmentTransaction transaction = fm.beginTransaction();
Bundle bundle = new Bundle();
bundle.putString("message", "这是Activity传递给FragmentOne的消息!!!");
FragmentOne fragmentOne = new FragmentOne();
fragmentOne.setArguments(bundle);
transaction.replace(R.id.content, fragmentOne);
transaction.addToBackStack(null);
transaction.commit();
首先创建Bundle,然后加入数据,最后通过setArguments()方法将bundle传递给Fragment。
然后在Fragment onCreate()中通过getArguments获取bundle,关键代码如下
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getArguments() != null) {
string = getArguments().getString("message");
}
}
效果如图
Fragment 向Activity传递消息
Fragment向Activity传递消息可以通过回调来实现,我们在之前的例子中修改,在FragmentOne中增加一个editText 和一个button,通过button将editText的内容传递给Acitivity,然后显示在Actionbar上。
FragmentOne代码如下
public class FragmentOne extends Fragment {
private String string;
private EditText editText;
private Button button;
private CallBack callBack;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one, container, false);
editText = view.findViewById(R.id.et);
button = view.findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String s = editText.getText().toString();
callBack.changTitle(s);
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof CallBack) this.callBack = (CallBack) context;
}
}
interface CallBack{
void changTitle(String string);
}
首先建立一个Callback的接口,在Fragment中声明,在onAttach中实例化callback,监听button,获取EditText的值传给changeTitle。然后在Activity中实现这个接口,重写changitle方法,Activity代码如下
public class MainActivity extends AppCompatActivity implements CallBack{
private FragmentManager fm;
private String string;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TEST","Activity creating");
setContentView(R.layout.activity_main2);
fm = getSupportFragmentManager();
fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.content, new FragmentOne());
transaction.addToBackStack(null);
transaction.commit();
}
@Override
public void changTitle(String string) {
ActionBar actionBar = getSupportActionBar();
actionBar.setTitle(string);
}
}
在changTitle中获取从Fragment传过来的字符串然后设置标题。
效果如下
相关文章
最新Androidx Fragment的前世今生系列(一)之Fragment的简单使用
最新Androidx Fragment的前世今生系列(二)之Fragment的生命周期
最新Androidx Fragment的前世今生系列(三)之Fragment与Acivity的通信
最后
Fragment与Fragment可以通过上述方法结合实现,也可以通过ViewModel实现,这个在以后JetPack的专栏文章在详细介绍。更多学习资料可以关注公众号QStack,追寻最纯粹的技术,享受编程的快乐。