上一篇文章講解了Fragment的一些基本用法,主要包括Fragment的動態和靜態添加的問題。但是在實際的項目開發中,Fragment與Fragment,Fragment與Activity之間的數據通信也是經常會用遇到的問題。比如你點擊一個Fragment中的按鈕,使得另一個Fragment中的內容發生改變。下面就用兩個例子使用用不同的方法來實現這個功能。
Fragment與Fragment之間的通信
FragmentDemoActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.example.daniel.test.activities.FragmentDemoActivity">
<fragment
<strong>android:id="@+id/fragment_send"</strong>
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.example.daniel.test.fragments.SendFragment"
tools:layout="@layout/fragment_send" />
<fragment
<strong>android:id="@+id/fragment_receive"</strong>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="com.example.daniel.test.fragments.ReceiveFragment"
tools:layout="@layout/fragment_receive" />
</LinearLayout>
public class FragmentDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_demo);
}
}
public class ReceiveFragment extends Fragment {
public ReceiveFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_receive, container, false);
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.daniel.test.fragments.ReceiveFragment">
<TextView
android:id="@+id/textview_receive"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment"
android:textSize="24sp"
/>
</FrameLayout>
SendFragment
public class SendFragment extends Fragment {
public SendFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_send, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
<strong>Button sendBtn = (Button)getActivity().findViewById(R.id.btn_send_sendFragment);</strong>
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView receiveTexView = (TextView) getActivity().findViewById(R.id.textview_receive);
receiveTexView.setText("Send message received!");
}
});
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.daniel.test.fragments.SendFragment">
<Button
android:id="@+id/btn_send_sendFragment"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send" />
</FrameLayout>
通過這個例子,就能發現,fragment可以通過getActivity()這個方法獲得所在Activity的引用,進而可以對在同一個Activity中的其他Fragment進行操作。
注意:
1. 在Activity的xml中,fragment的id一定要寫,不然會報XML解析錯誤。
2. 在SendFragment中獲得sendBtn的操作不能放在onCreateView裏,因爲此時Fragment的view還沒有被inflate。放在onActivityCreated中即可,關於Fragment的生命週期不清楚的,可以參考我的上一篇博客。
Fragment與Activity通信
package com.example.daniel.test.fragments;
import android.content.Context;
import android.os.Bundle;
<strong>import android.support.v4.app.Fragment;</strong>
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.example.daniel.test.R;
/**
* A simple {@link Fragment} subclass.
*/
public class SendFragment extends Fragment {
private SendBtnListener mSendBtnListener;
public SendFragment() {
// Required empty public constructor
}
public interface SendBtnListener{
public void sendBtnClick();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d("Debug","onAttach invoked!");
if(context instanceof SendBtnListener){
mSendBtnListener = (SendBtnListener)context;
}
else {
throw new ClassCastException(context.toString()+"must implement SendBtnListener!");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_send, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button sendBtn = (Button)getActivity().findViewById(R.id.btn_send_sendFragment);
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TextView receiveTexView = (TextView) getActivity().findViewById(R.id.textview_receive);
// receiveTexView.setText("Send message received!");
mSendBtnListener.sendBtnClick();
}
});
}
}
FragmentDemoActivity 修改爲
public class FragmentDemoActivity extends AppCompatActivity implements SendFragment.SendBtnListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_demo);
}
@Override
public void sendBtnClick() {
TextView receiveTexView = (TextView) findViewById(R.id.textview_receive);
receiveTexView.setText("Send message received!");
}
}
注意:在API 23中Fragment有個Bug,新的public void onAttach(Context context)不被調用的問題,應使用support Fragment代替。詳情請查看我的博客。
點擊Send按鈕前
點擊Send按鈕後
實現的流程爲:
1)在SendFragment中聲明一個Interface,稱爲回調接口。
2)Activity實現這個接口。
3)在Fragment的onAttach()方法中使用Interface的變量獲得Activity的引用,用這個接口的引用調用Activity中的方法。
4)Activity中的方法決定ReceiveFragment的響應。