Android入門教程 | Fragment (載入方法與通訊)

Android_anzi發表於2021-10-19

Fragment 載入方法

載入方法有兩種

  • 在xml檔案中註冊
  • 在Java程式碼中載入

xml中註冊

例如在  fragment_demo.xml 中定義

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <fragment
        android:id="@+id/main_fragment_up"
        android:name="com.rust.fragment.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
    <fragment
        android:id="@+id/main_fragment_bottom"
        android:name="com.rust.fragment.SecondFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" /></LinearLayout>

com.rust.fragment.SecondFragment 就是 Fragment 子類
SecondFragment.java裡複寫 onCreateView方法,並返回定義好的view

activity 中直接載入即可

setContentView(R.layout.fragment_demo);

Java程式碼中載入

①準備好Fragment xml佈局檔案
②新建一個類,繼承自 Fragment;在這個類中找到 Fragment 佈局檔案
③在 Activity 中使用 FragmentManager 來操作 Fragment
④別忘了commit

先自定義一個佈局檔案  fragment_first.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#0011ff" ><!-- <Button
    android:id="@+id/btn_fragment1_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/btn_fragment1"
    android:textSize="16sp"
       />
<EditText
    /> --></LinearLayout>

新建一個類  FirstFragment.java,繼承自 Fragment。複寫  onCreateView 方法。在 onCreateView方法中,可以操作 Fragment 上的控制元件。

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {        View rootView = inflater.inflate(R.layout.fragment_first, container,false);//    fragment_first是自定義好的佈局//    如果此Fragment上放了控制元件,比如Button,Edittext等。可以在這裡定義動作
  btn_fragment1_send = (Button) rootView.findViewById(R.id.btn_fragment1_1);//...
        return rootView;
    }

準備一個位置給 Fragment,比如在  activity_main.xml 中用 Framelayout 來佔位。

    <FrameLayout
        android:id="@+id/layout_container1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" >
    </FrameLayout>

在  MainActivity.java 裡,先獲得 FragmentManager,得到FragmentTransaction。Fragment 的新增刪除等操作由 FragmentTransaction 來完成。

f1 = new FirstFragment();    //    獲取例項f2 = new SecondFragment();    //FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.layout_container1,f1);    //    新增fragmentTransaction.replace(R.id.layout_container1,f1);    //    替換// 或者也可以寫成fragmentTransaction.replace(R.id.layout_container1,new FirstFragment());//              fragmentTransaction.addToBackStack(null);   //新增到返回棧,這樣按返回鍵的時候能返回已新增的fragmentfragmentTransaction.commit();    //別忘了commit//    移除操作 getFragmentManager().beginTransaction().remove(f1).commit();

相比與 xml 中註冊,程式碼載入更為靈活一些。個人較為喜歡動態載入。

Fragment 與 Activity 之間的配合

Activity 先執行 onResume 然後當前 Fragment 執行 onResume 當前Fragment 被 replace 掉,再次 replace 回來時,有些狀態並未重新初始化。
執行 replace 時會把 Fragment 的宣告週期再跑一遍。穩妥的做法是,在 onCreateView中初始化必要的變數。比如重置一些狀態值。在多個 Fragment中切換時需要特別注意。

Fragment 間的通訊

在 Fragment 的 java 檔案中,可以使用  getActivity() 來獲得呼叫它的 activity,然後再找到另一個 Fragment,進行通訊

getActivity().getFragmentManager().findFragmentById(R.id.fragment_list);

但這樣做耦合度太高,不方便後續的修改操作

Fragment 與其附著的 Activity 之間的通訊,都應該由 Activity 來完成;不能是多個 Fragment 之間直接通訊

Fragment與其附著的Activity之間通訊方式:
  • 在發起事件的Fragment中定義一個介面,介面中宣告你的方法
  • 在onAttach方法中要求Activity實現該介面
  • 在Activity中實現該方法

例如一個 activity 中佈置了 2 個 Fragment,它們之間的通訊要依靠 activity 來完成

程式碼: ListStoreActivity.java  NewItemFragment.java  ListStoreFragment.java
佈局檔案為: liststore.xml  new_item_fragment.xml

準備佈局檔案
liststore.xml 用 LinearLayout 中放置了 2 個 fragment,分別指向 2 個Fragment 檔案
new_item_fragment.xml 中並排放置一個 EditText 和一個按鈕

ListStoreFragment.java 使用前面定義的介面

public class ListStoreFragment extends ListFragment{/// 繼承自ListFragment,已經封裝好了listview/// 不需要自己寫ListView了}

NewItemFragment.java

/**
 * 宣告一個介面,定義向activity傳遞的方法
 * 繫結的activity必須實現這個方法
 */
    public interface OnNewItemAddedListener {        public void newItemAdded(String content);
    }    private OnNewItemAddedListener onNewItemAddedListener;    private Button btnAddItem;    /*複寫onAttach方法*/
    @Override    public void onAttach(Activity activity) {        super.onAttach(activity);        try {
            onNewItemAddedListener = (OnNewItemAddedListener) activity;
        } catch (ClassCastException e){            throw new ClassCastException(activity.toString() + "must implement OnNewItemAddedListener");
        }
    }

ListStoreActivity.java 載入主檢視 liststore.xml;

兩個 Fragment 透過 ListStoreActivity來通訊

在 onCreate 方法中獲取 ListStoreFragment 的例項;並且複寫 newItemAdded 方法,在裡面加上業務邏輯

public class ListStoreActivity extends Activity implements OnNewItemAddedListener{    private ArrayList<String> data;    private ArrayAdapter<String> adapter;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.liststore);
        data = new ArrayList<String>();        // 把data裝入adapter中
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);        // ListFragment並不需要再定義一個listview 
        ListStoreFragment listStoreFragment = (ListStoreFragment) getFragmentManager().findFragmentById(R.id.fragment_listview);
        listStoreFragment.setListAdapter(adapter);
    }    @Override
    public void newItemAdded(String content) {        //  複寫介面中的方法,業務程式碼在這裡實現
        if(!content.equals("")) {
            data.add(content);
            adapter.notifyDataSetChanged();
        }
    }
}

這樣做的缺點是耦合度很高

Fragment跟Activity的幾種通訊方式

  • Activity把自己的handler交給Fragment
  • 廣播
  • EventBus
  • 定義介面

除了上面提到的幾種方法,也可以用 Activity 和 Fragment 共用 ViewModel的方式實現通訊。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70008155/viewspace-2838032/,如需轉載,請註明出處,否則將追究法律責任。

相關文章