上一篇主要總結了Activity向Fragment傳遞數據的方式Fragment使用小結(二),接着Fragment向Activity傳遞數據以及Fragment間數據傳遞。
一. Fragment向Activity傳遞數據(兩種方案)
方案一:接口回調,首先在Fragment中定義一個接口,並在接口中定義傳遞數據的抽象方法,然後在Activity中實現這個接口,並重寫這個方法,最後在fragment中創建接口對象並指向Activity,傳入數據。這種方式即可以實現Fragment和Activity之間的通信,也可以實現兩個Fragment之間的通信。
MainActivity.Java
public class MainActivity extends AppCompatActivity implements ThreeFragment.MyCallBack {
private TextView mTextView;
private FragmentManager mFm;
private FragmentTransaction mTransaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.tv_data);
mFm = getFragmentManager();
// 2. 開啓Fragment處理事務.
mTransaction = mFm.beginTransaction();
// 3. 進行Fragment操作
mTransaction.add(R.id.container, new ThreeFragment());
// 4. 進行事務的提交
mTransaction.commit();
}
@Override
public void sendData(String str) {
mTextView.setText(str);
}
}
ThreeFragment.java
public class ThreeFragment extends Fragment {
private EditText mData;
private Button mButton;
private MyCallBack mCallBack;
public interface MyCallBack {
public void sendData(String str);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_three, container, false);
mData = (EditText) view.findViewById(R.id.et_message);
mButton = (Button) view.findViewById(R.id.bt_sendMessage);
mButton.setOnClickListener(new View.OnClickListener() {
private String mString;
@Override
public void onClick(View view) {
mString = mData.getText().toString().trim();
mCallBack.sendData(mString);
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallBack = (MyCallBack) getActivity();
}
}
方案二:使用廣播,首先在宿主Activity裏面註冊廣播,然後當需要通信的時候在Fragment中發送廣播,宿主Activity中接受到廣播,就可以獲取數據進行顯示了。當然也可以用廣播實現兩個Fragment之間的通信。
MainActivity.Java
private TextView mTextView;
private FragmentManager mFm;
private FragmentTransaction mTransaction;
private IntentFilter mFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.tv_data);
mFm = getFragmentManager();
// 2. 開啓Fragment處理事務.
mTransaction = mFm.beginTransaction();
// 3. 進行Fragment操作
mTransaction.add(R.id.container, new ThreeFragment());
// 4. 進行事務的提交
mTransaction.commit();
//動態註冊廣播
mFilter = new IntentFilter();
mFilter.addAction("android.activity.broadReceiver");
BroadcastReceiver mBr = new BroadReceiver();
registerReceiver(mBr, mFilter);
}
public class BroadReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle mData = intent.getExtras();
mTextView.setText(mData.getString("text"));
}
}
}
ThreeFragment.java
mButton1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("android.activity.broadReceiver");
intent.putExtra("text", "fragment通過廣播發給Activity的數據");
getActivity().sendBroadcast(intent);
}
});
除了以上兩種方案之外還可以使用EventBus等等,我會在下面的Fragment間數據傳遞中使用。
二 .Fragment間數據傳遞(五種方案)
方案一:首先直接通過getFragmentManager獲取Fragment管理器,然後通過Fragment的tag標籤找到該Fragment,最後調用該Fragment的方法即可
MainActivity.Java
public class MainActivity extends FragmentActivity {
private LeftFragment leftFragment;
private RightFragment rightFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFragment();
}
private void initFragment() {
leftFragment = new LeftFragment();
rightFragment = new RightFragment();
//將這個兩個Fragment放到當前Activity對應的佈局文件中
getSupportFragmentManager().beginTransaction().
add(R.id.fl_left, leftFragment, "left").
add(R.id.fl_right, rightFragment,"right").
commit();
}
}
LeftFragment.java
public class LeftFragment extends Fragment {
private ListView listView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_left, container, false);
//從Fragment的View中獲取到LsitView控件
listView = (ListView) view.findViewById(R.id.lv );
final String[] data = {"條目一","條目二","條目三","條目
四","條目五"};
final int[] imageIds = {R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e};
listView.setAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, data));
//給ListView設置條目的點擊事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
//1. 獲取用戶點擊的位置 對應的 title 和圖片
String title = data[position];
int imageId = imageIds[position];
//2. 將數據設置給RightFragment。
//(1)找到RightFragment
//獲取Fragment管理器
FragmentManager fragmentManager = getFragmentManager();
//通過Fragment的tag標籤找到該Fragment
RightFragment rightFragment = (RightFragment) fragmentManager.findFragmentByTag("right");
//(2)調用RightFragment的方法
rightFragment.setTitleAndImage(title, imageId);
}
});
return view;
}
}
RightFragment.java
public class RightFragment extends Fragment {
private ImageView iv;
private TextView tv_title;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_right, container, false);
tv_title = (TextView) view.findViewById(R.id.tv_title);
iv = (ImageView) view.findViewById(R.id.iv);
return view;
}
/*
* 添加一個方法,用於給自己設置標題和圖片
*/
public void setTitleAndImage(String title, int imageId) {
tv_title.setText(title);
iv.setImageResource(imageId);
}
}
方案二:使用接口來實現兩個Fragment之間通信,需要通過宿主Activity中轉一下,首先在宿主Activity中實現這個接口,這樣當Fragment調用onAttach方法時就可以實例化這個接口了,Fragment通過回調接口,將值返給Activity,Activity 通過setArguments 傳值給另一個Fragment。如果是Fragment和宿主Activity通信則直接調用即可。
MainActivity.Java
public void sendData(String title, int imgId) {
FragmentManager manager = getFragmentManager();
//得到FragmentTransaction對象
FragmentTransaction transaction = manager.beginTransaction();
rightFragment = new RightFragment();
Bundle bundle = new Bundle();
bundle.putString("title", title);
bundle.putInt("img",imgId);
rightFragment.setArguments(bundle);
//將rightFragment替換佈局
transaction.replace(R.id.fl_right, rightFragment);
transaction.commit();//提交事務
}
LeftFragment.java
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
//1. 獲取用戶點擊的位置 對應的 title 和圖片
String title = data[position];
int imageId = imageIds[position];
mCallBack.sendData(title,imageId);
}
});
return view;
}
public interface MyCallBack {
public void sendData(String title,int imgId);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallBack = (MyCallBack) getActivity();
}
RightFragment.java
//得到activity傳過來的bundle對象
Bundle bundle = getArguments();
if(bundle!=null){
tv_title.setText(bundle.getString("title"));
iv.setImageResource(bundle.getInt("img"));
}
方案三:EventBus,直接參考 http://blog.csdn.net/tyk0910/article/details/51073292
方案四:使用廣播,我採用的是LocalBroadcastManager發送廣播
LocalBroadcastManager是AndroidSupport包提供了一個工具,是用來在同一個應用內的不同組件間發送Broadcast的。
注意,這是同一個應用,也就是其他應用就算和你共進程,也是無法互相發送廣播的。
使用LocalBroadcastManager有如下好處:
1. 發送的廣播只會在自己App內傳播,不會泄露給其他App,確保隱私數據不會泄露
2. 其他App也無法向你的App發送該廣播,不用擔心其他App會來搞破壞
3. 比系統全局廣播更加高效
LeftFragment.java
/**
* 方案四 發送廣播
*/
Intent intent = new Intent("android.fragment.register");
intent.putExtra("title", title);
intent.putExtra("img", imageId);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);
RightFragment.java
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager
.getInstance(getActivity());
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.fragment.register");
BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle mData = intent.getExtras();
tv_title.setText(mData.getString("title"));
iv.setImageResource(mData.getInt("img"));
}
};
localBroadcastManager.registerReceiver(br, intentFilter);
方案五:通過宿主Activity(fragment(必須在同一個Activity中)),只需要改變LeftFragment.java以下代碼
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
String title = data[position];
int imageId = imageIds[position];
// 在Fragment中調用其所在的Activity方法 , Fragment獲取上下文的方法
FragmentActivity activity = getActivity();
if(activity instanceof MainActivity) {
// 獲取Fragment管理器
FragmentManager fm = getFragmentManager();
// 找到第二個Fragment, 直接執行方法
RightFragment fragment = (RightFragment) fm.findFragmentByTag("right");
fragment.setTitleAndImage(title, imageId);
}
}
});
return view;
}