前言
- 本來打算把 Fragment 的內(nèi)容寫完,結(jié)果寫著寫著發(fā)現(xiàn)這個篇幅已經(jīng)夠長了妒茬,所以就先寫通信這一塊了轰豆,其他的另起篇幅
正文
一、 Fragment 與 Activity 通信
所有的 Fragment 都是依附于 Activity 存在的鸿染,而通信則是 Fragment 與 Activity 之間相互傳遞數(shù)據(jù)。
一個 Activity 可以替換多個 Fragment 乞巧,Activity 就是這多個 Fragment 的管理者涨椒,考慮到 Fragment 的復用性,盡量降低 Fragment 與 Fragment 之間的耦合绽媒,不要用一個 Fragment 來操作另一個 Fragment蚕冬,使用 Activity 來操作 Fragment
1. Activity 向 Fragment 傳遞數(shù)據(jù)
通過 bundle
- 在動態(tài)添加 Fragment 的過程中卖词,我們在 Activity 中通過 Fragment.setArguments() 的方法為 Fragment 提供數(shù)據(jù)陵霉,setArguments 方法需要傳遞一個 Bundle,把需要傳遞的數(shù)據(jù)放在 Bundle 中即可
Bundle bundle = new Bundle();
bundle.putString("name","zhangsan");
firstFragment.setArguments(bundle);
- 在 Fragment 中穆役,在 onAttach() 函數(shù)中通過調(diào)用 getArguments() 獲得一個 Bundle 對象获三,從而獲取我們提供的數(shù)據(jù)旁蔼。
@Override
public void onAttach(Context context) {
super.onAttach(context);
name = (String) getArguments().get("name");
}
2. 在Fragment中可以通過 getActivity 得到當前綁定的 Activity 的實例,然后進行操作疙教。
- 假如 Fragment 依附的 Activity 中有這樣一個方法:
public String getName(){
return "lisi";
}
- 在 Fragment 中可以這樣獲取
HuiTuiZhanActivity activity = (HuiTuiZhanActivity) getActivity();
String name = activity.getName();
3. 實現(xiàn)Fragment 中改變 Activity 中的控件內(nèi)容
通過設置回調(diào)接口來實現(xiàn)該效果
- Fragment 中的代碼如下所示:
package com.example.administrator.fragment_text.huituizhan;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.example.administrator.fragment_text.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
/**
* Created by Administrator on 2017/4/10.
*/
public class FirstFragment extends Fragment {
@BindView(R.id.editText)
EditText editText;
@BindView(R.id.btn)
Button btn;
Unbinder unbinder;
@BindView(R.id.bt2n)
Button bt2n;
private String name;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("FirstFragment", "onCreateView");
View inflate = inflater.inflate(R.layout.huituizhan_first_fragment, container, false);
unbinder = ButterKnife.bind(this, inflate);
return inflate;
}
/**
* 點擊第一個按鈕切換到 SecondFragment
*點擊第二個按鈕觸發(fā)自定義接口中的方法牌芋,具體做什么就看宿主 Activity
*/
@OnClick({R.id.btn, R.id.bt2n})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
SecondFragment secondFragment = new SecondFragment();
fragmentTransaction.hide(this);
// fragmentTransaction.remove(this);
fragmentTransaction.add(R.id.framelayout, secondFragment, "second");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
case R.id.bt2n:
//當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
onBt2nClickListener.OnBt2nClick();
break;
}
}
private OnBt2nClickListener onBt2nClickListener;
public void setOnBt2nClickListener(OnBt2nClickListener onBt2nClickListener){
this.onBt2nClickListener = onBt2nClickListener;
}
/**
* 自定義回調(diào)接口
*/
public interface OnBt2nClickListener{
public void OnBt2nClick();
}
}
- Activity 中的代碼如下所示:
package com.example.administrator.fragment_text.huituizhan;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.example.administrator.fragment_text.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class HuiTuiZhanActivity extends AppCompatActivity {
@BindView(R.id.framelayout)
FrameLayout framelayout;
@BindView(R.id.textView)
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hui_tui_zhan);
ButterKnife.bind(this);
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
FirstFragment firstFragment = new FirstFragment();
Bundle bundle = new Bundle();
bundle.putString("name", "zhangsan");
firstFragment.setArguments(bundle);
fragmentTransaction.add(R.id.framelayout, firstFragment, "first").commit();
}
@Override
protected void onResume() {
super.onResume();
FirstFragment first = (FirstFragment) getSupportFragmentManager().findFragmentByTag("first");
first.setOnBt2nClickListener(new FirstFragment.OnBt2nClickListener() {
@Override
public void OnBt2nClick() {
textView.setText("珞神");
}
});
}
}
這樣就實現(xiàn)了,在點擊 Fragment 中的按鈕的時候松逊,改變 Activity 中的 TextView 顯示的內(nèi)容,并且降低 Fragment 與 Activity 的耦合性肯夏,并增強了 Fragment 的復用性经宏,哪個 Activity 都能用這個 Fragment
4. 實現(xiàn) Fragment 來操作另一個 Fragment
Fragment1 操作另一個 Fragment2,不應在Fragment1 中直接來操作,應該交給他們共同的宿主 Activity 來操作驯击,也是通過設置接口來實現(xiàn)烁兰。
測試邏輯概述: FirstFragment 中的按鈕切換 Activity 中的 TextView ,SecondFragment 中的按鈕切換 ThreeFragment
- FirstFragment 中的代碼:
package com.example.administrator.fragment_text.huituizhan;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.example.administrator.fragment_text.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
/**
* Created by Administrator on 2017/4/10.
*/
public class FirstFragment extends Fragment {
@BindView(R.id.editText)
EditText editText;
@BindView(R.id.btn)
Button btn;
Unbinder unbinder;
@BindView(R.id.bt2n)
Button bt2n;
private String name;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("FirstFragment", "onCreateView");
View inflate = inflater.inflate(R.layout.huituizhan_first_fragment, container, false);
unbinder = ButterKnife.bind(this, inflate);
editText.setText(name);
return inflate;
}
/**
* 點擊按鈕切換到 SecondFragment
*/
@OnClick({R.id.btn, R.id.bt2n})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn:
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
SecondFragment secondFragment = new SecondFragment();
fragmentTransaction.hide(this);
fragmentTransaction.add(R.id.framelayout, secondFragment, "second");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
case R.id.bt2n:
//如果宿主 Activity 實現(xiàn)了此接口
if (getActivity() instanceof OnBt2nClickListener) {
//當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
((OnBt2nClickListener) getActivity()).OnBt2nClick();
}
break;
}
}
// private OnBt2nClickListener onBt2nClickListener;
//
//
// public void setOnBt2nClickListener(OnBt2nClickListener onBt2nClickListener){
// this.onBt2nClickListener = onBt2nClickListener;
// }
/**
* 自定義回調(diào)接口
*/
public interface OnBt2nClickListener {
public void OnBt2nClick();
}
}
注意: 這里的回調(diào)采用了另一種方式:
//如果宿主 Activity 實現(xiàn)了此接口
if (getActivity() instanceof OnBt2nClickListener) {
//當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
((OnBt2nClickListener) getActivity()).OnBt2nClick();
}
- SecondFragment 中的代碼:
package com.example.administrator.fragment_text.huituizhan;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.example.administrator.fragment_text.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
/**
* Created by Administrator on 2017/4/10.
*/
public class SecondFragment extends Fragment {
@BindView(R.id.editText)
EditText editText;
@BindView(R.id.btn)
Button btn;
Unbinder unbinder;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.huituizhan_second_fragment, container, false);
unbinder = ButterKnife.bind(this, inflate);
Log.i("SecondFragment", "onCreateView");
return inflate;
}
@OnClick(R.id.btn)
public void onViewClicked() {
if (getActivity() instanceof OnBt22222nClickListener) {
//當需要切換 Activity 中的 TextView 的時候觸發(fā)該接口中的方法
((OnBt22222nClickListener) getActivity()).OnBt22222nClick();
}
}
private OnBt22222nClickListener onBt22222nClickListener;-->
public void setOnBt22222nClickListener(OnBt22222nClickListener onBt22222nClickListener) {-->
this.onBt22222nClickListener = onBt22222nClickListener;-->
}
/**
* 自定義回調(diào)接口
*/
public interface OnBt22222nClickListener {
public void OnBt22222nClick();
}
}
注意: SecondFragment 中的回調(diào)設置與 FirstFragment 中的一樣徊都,我試過按照常規(guī)方式 ( setOnBt22222nClickListener 方式 ) 設置沪斟,切換 Fragment 的時候程序崩潰,而這種方式則沒問題暇矫,不知道為嘛 - -主之!
- Activity 中的代碼:
package com.example.administrator.fragment_text.huituizhan;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.example.administrator.fragment_text.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class HuiTuiZhanActivity extends AppCompatActivity implements FirstFragment.OnBt2nClickListener, SecondFragment.OnBt22222nClickListener {
@BindView(R.id.framelayout)
FrameLayout framelayout;
@BindView(R.id.textView)
TextView textView;
private SecondFragment second;
private FirstFragment firstFragment;
private ThreeFragment three;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hui_tui_zhan);
ButterKnife.bind(this);
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
firstFragment = new FirstFragment();
Bundle bundle = new Bundle();
bundle.putString("name", "zhangsan");
firstFragment.setArguments(bundle);
fragmentTransaction.add(R.id.framelayout, firstFragment, "first").commit();
}
//FirstFragment 中回調(diào)的點擊事件
@Override
public void OnBt2nClick() {
textView.setText("珞神");
if (second == null) {
second = new SecondFragment();
second.setOnBt22222nClickListener(this);
}
}
//SecondFragment 中回調(diào)的點擊事件
@Override
public void OnBt22222nClick() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (three == null) {
three = new ThreeFragment();
}
if (second == null) {
second = new SecondFragment();
}
// fragmentTransaction.hide(second);
// fragmentTransaction.add(R.id.framelayout,three,"three");
fragmentTransaction.replace(R.id.framelayout, three, "three");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
5. 通過 getFragmentManager.findFragmentByTag() 或者 findFragmentById() 獲得任何 Fragment 實例,然后來操作 Fragment 中的方法李根。
- 假如 Fragment 中有這樣一個方法:
public String getName(){
return "珞神";
}
- 在其宿主 Activity 中可以這樣操作:
FirstFragment first = (FirstFragment) getSupportFragmentManager().findFragmentByTag("first");
String name = first.getName();
至此槽奕,完結(jié)如有錯誤和遺漏,一經(jīng)發(fā)現(xiàn)房轿,必然改正粤攒!