Fragment與Activity之間的數據交互

一、Activity把值傳遞給Fragment

  建議的傳值方式是通過Bundle來傳遞,而不是直接作爲fragment的構造參數傳遞。在activity中創建bundle數據包,並調用fragment的setArguments(Bundle bundle)方法,即可將Bundle數據包傳給fragment。在Fragment中用getArguments方法得到傳遞過來的值。

二、Fragment把值傳遞給Activity

  在fragment中定義一個內部回調接口,再讓包含該fragment的activity實現該回調接口,這樣fragment即可調用該回調方法將數據傳給activity。其實接口回調的原理都一樣,以前的博客有講到,接口回調是Java不同對象之間數據交互的通用方法。

  activity實現完了接口怎麼傳給剛纔的fragment呢?當fragment添加到activity中時,會調用fragment的方法onAttach(),這個方法中適合檢查activity是否實現了OnArticleSelectedListener接口,檢查方法就是對傳入的activity的實例進行類型轉換,然後賦值給我們在fragment中定義的接口。

  在一個fragment從activity中剝離的時候,就會調用onDetach方法,這個時候要把傳遞進來的activity對象釋放掉,不然會影響activity的銷燬,產生不必要的錯誤。注意看onAttach方法中的代碼,在賦值之前要做一個判斷,看看Activity中有沒有實現了這個接口,用到了instanceof。如果沒有實現接口,我們就拋出異常。

例:左側加一堆按鈕,點擊左側,之後右側內容發生變化

這裏寫圖片描述

fragment書寫

package com.stady.hg.demos.fragmentinteraction;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Intellij IDEA
 * project:FragmentInteraction
 * Author:hg
 * Email:[email protected]
 * Date:2015/4/30
 */
public class MenuFragment extends Fragment implements View.OnClickListener {

    /**
     * 用來與外部activity交互的
     */
    private FragmentInteraction listterner;

    public MenuFragment(){}

    /**
     * 當FRagmen被加載到activity的時候會被回調
     * @param activity
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof FragmentInteraction)
        {
            listterner = (FragmentInteraction)activity;
        }
        else{
            throw new IllegalArgumentException("activity must implements FragmentInteraction");
        }

    }

    @Override
    public void onDetach() {
        super.onDetach();

        listterner = null;
    }

    /**
     * 定義了所有activity必須實現的接口
     */
    public interface FragmentInteraction
    {
        /**
         * Fragment 向Activity傳遞指令,這個方法可以根據需求來定義
         * @param str
         */
        void process(String str);


    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_menu, container, false);

        View btn = view.findViewById(R.id.tv_button);
        View btn_m = view.findViewById(R.id.movie_button);
        View btn_c = view.findViewById(R.id.comic_button);

        if (btn != null||btn_m!=null||btn_c!=null) {
            btn.setOnClickListener(this);
            btn_m.setOnClickListener(this);
            btn_c.setOnClickListener(this);
        }

        return view;
    }

    @Override
    public void onClick(View v) {
        int id  = v.getId();

        switch (id)
        {
            case R.id.tv_button:
                listterner.process("我是電視劇");
                break;
            case R.id.movie_button:
                listterner.process("我是電影");
                break;
            case R.id.comic_button:
                listterner.process("我是動漫");
                break;
        }
    }
}

注意在onDetach方法中把傳遞進來的activity釋放掉。

activity書寫

package com.stady.hg.demos.fragmentinteraction;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity implements MenuFragment.FragmentInteraction{

    private TextView textView;


    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        textView = (TextView) findViewById(R.id.content_text);


    }

    /**
     * 給Fragment調用
     * @param str
     */
//    public void setContent(String str)
//    {
//        if (str!=null)
//        {
//            textView.setText(str);
//        }
//    }


    @Override
    public void process(String str) {
        if (str != null) {
            textView.setText(str);
        }
    }
}

三、Fragment與Fragment之間的傳值

  在Activity中加載Fragment的時候、有時候要使用多個Fragment切換、並傳值到另外一個Fragment、也就是說兩個Fragment之間進行參數的傳遞、查了很多資料、找到兩種方法。

1、通過共同的Activity傳遞

  這種方法是在Activity裏面添加一個字段、來臨時保存要一些值。在Activity中定義一個字段、然後添加set和get方法、代碼如下、mTitle就是要傳遞的參數、如果是傳遞對象、可以把mTitle換成一個對象即可.

public class DemoActivity {
    private String mTitle;
    public String getmTitle() {
        return mTitle;
    }
    public void setmTitle(String title) {
        this.mTitle = title;
    }
}

  Fragment調用方法、需要注意的是在設值的時候要進行強轉一下

((DemoActivity)getActivity()).getmTitle();

2、通過Bundle來傳遞

  可以使用bundle進行參數傳遞、這樣在兩個Fragment跳轉的時候就可以帶上參數了、同樣也可以傳遞一個複雜的對象。

ft.hide(getActivity().getSupportFragmentManager().findFragmentByTag(""));
    DemoFragment demoFragment = new DemoFragment();  
    Bundle bundle = new Bundle();  
    bundle.putString("key", "這是方法二");  
    demoFragment.setArguments(bundle);  
    ft.add(R.id.fragmentRoot, demoFragment, SEARCHPROJECT);  
    ft.commit();  

  在另外一個Fragment獲取參數的方式只需要一個語句、key是自己定義的一個標識、參數的形式只要bundle能傳遞都可以實現

String string = getArguments().getString("key"); 

  從上面兩種方法看來、方法一要簡單一些、但個人覺得有點投機取巧、不過也很合Java的開發規範、如果是同一個Activity中要加載很多Fragment的話、這種方法無疑要簡單很多。而方法二是使用了Android的Bundle傳遞的、這種方法應該更官方一點吧、不過在項目開發中、怎麼實現簡單就怎麼來、也沒太多關係。

發佈了456 篇原創文章 · 獲贊 19 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章