Fragment使用小結(三)

上一篇主要總結了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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章