歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android開發學習之Fragment解析

Android開發學習之Fragment解析

日期:2017/3/1 9:26:36   编辑:Linux編程

1.定義

Fragment中文解釋是碎片的意思,主要用在大屏幕設備上,例如平板電腦上,支持更加動態和靈活的UI設計。Fragment在你的應用中相當於是一個模塊化和可重用的組件,因為Fragment定義了它自己的布局,以及通過使用它自己的生命周期回調方法定義了它自己的行為,你可以將Fragment包含到多個Activity中。

2.特點

(1)Fragment可以作為Activity界面的一部分組成出現;

(2)可以在一個Activity中同時出現多個Fragment,並且一個Fragment也可以在多個Activity中使用;

(3)在Activity運行過程中,可以添加、移除或者替換Fragment;

(4)Fragment可以響應自己的輸入事件,並且有自己的生命周期,它們的生命周期會受宿主Activity的生命周期影響。

3.生命周期

Fragment必須是依存於Activity而存在的,因此Activity的生命周期會直接影響到Fragment的生命周期。

生命周期中涉及的方法如上圖所示,具體觸發條件如下所述。
  • onAttach()
    • 當Fragment被添加到Activity時候會回調這個方法,並且只調用一次;
  • onCreate()
    • 創建Fragment時會回調,只會調用一次;
  • onActivityCreated()
    • 當Fragment所在的Activity啟動完成後調用;
  • onCreateView()
    • 每次創建都會去繪制Fragment的View組件時回調該方法;
  • onStart()
    • 啟動Fragment
  • onResume()
    • 恢復Fragment時會被回調,調用onStart()方法後面一定會調用onResume()方法;
  • onStop()
    • 停止Fragment
  • onDestroyView()
    • 銷毀Fragment所包含的View組件時調用
  • onDestroy()
    • 銷毀Fragment時被回調
  • onDetach()
    • Fragment從Activity中刪除時會回調該方法,並且這個方法只會調用一次

4.靜態加載

這是使用Fragment最簡單的一種方式,把Fragment當成普通的控件,直接寫在Activity的布局文件中,用布局文件調用Fragment。

(1)新建Fragment,重寫onCreateView決定Fragment布局

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_static, container, false);
    }
(2)在宿主Activity中手動添加Fragment,就把它當做普通的控件一樣,在xml文件中使用。name屬性填寫fragment的包路徑,Activity通過findFragmentById()或者findFragmentByTag()獲取Fragment。
<fragment
         Android:name="ant.snail.com.fragmentactapp.StaticFragment"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:tag="newfrag" />

這樣在宿主Activity中就能看到Fragment了。

5.動態加載

上面的靜態加載是最基本的方法,下面解析下動態加載的原理。

(1)原理

  動態加載,顧名思義是通過代碼的方式在Activity中加載Fragment。

  通過撰寫代碼將Fragment添加到一個Activity layout中,這裡需要采用Fragment的事務處理(FragmentTransaction),有點類似數據庫的事務處理。

  1. 根據用戶的交互情況,對Fragment進行添加、移除、替換,以及執行其他動作,提交給Activity的每一套變化被稱作一個事務;
  2. 每一個事務都是同時執行一套變化,可以再一個事務中設置你所有想執行的變化,包括add(),remove(),replace(),然後提交給Activity,最後調用commit()方法;
  3. 如果允許用戶通過按下BACK按鍵返回到前一個Fragment狀態,調用commit()之前可以加入addToBackStack()方法。

 (2)具體實現

  通過新建兩個Fragment,並在這兩個Fragment的Layout中添加了ImageView,用來放置圖片,而在宿主Activity中將這兩個Fragment動態切換,實現圖片的自由切換。代碼結構如下圖所示。

新建Fragment(Image1Fragment,Image2Fragment),並添加了兩個layout文件(fragment_image1,fragment_image2),其中部分代碼如下:

Image1Fragmet代碼:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 獲取Fragment的View
        View view=inflater.inflate(R.layout.fragment_image1,container,false);
return view; }

fragment_image1.xml文件代碼如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context="ant.snail.com.fragmentactapp.Image1Fragment"
    >

    <!-- TODO: Update blank fragment layout -->

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:gravity="center"
        >
        <TextView
            android:id="@+id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我是jin兔1"/>

        <Button
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="傳遞數據到主窗口"
            android:id="@+id/btfr1" />


    </LinearLayout>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView1"
        android:src="@drawable/jin1"/>
</LinearLayout>

宿主MainActivity的代碼如下,通過FragmentManager得到FragmentTransaction,然後通過replace()方法實現兩個Fragment之間的切換,最後實現了Commit()方法:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //獲取兩個按鈕的View
        bt1=(Button)findViewById(R.id.bt1);
        bt2=(Button)findViewById(R.id.bt2);

        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //主Activity動態加載Fragment
                FragmentManager fragmentManager=getFragmentManager();
                //處理Fragment事務
                FragmentTransaction beginTransaction=fragmentManager.beginTransaction();
                //獲取Image1Fragment實例
                Image1Fragment image1Fragment=Image1Fragment.newInstance("Activity傳遞圖片1到Fragment中");
                //替換操作
                beginTransaction.replace(R.id.imageLayout,image1Fragment);
                //允許用戶通過按下BACK按鍵返回到前一個Fragment狀態
                beginTransaction.addToBackStack(null);
                beginTransaction.commit();
            }
        });
        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //主Activity動態加載Fragment
                FragmentManager fragmentManager=getFragmentManager();
                //處理Fragment事務
                FragmentTransaction beginTransaction=fragmentManager.beginTransaction();
                //獲取Image1Fragment實例
                Image2Fragment image2Fragment=Image2Fragment.newInstance("Activity傳遞圖片2到Fragment中");
                //替換操作
                beginTransaction.replace(R.id.imageLayout,image2Fragment);
                //允許用戶通過按下BACK按鍵返回到前一個Fragment狀態
                beginTransaction.addToBackStack(null);
                beginTransaction.commit();
            }
        });

    }

其中NewInstance方法是在Fragment中實現的一個實例方法,用於將Fragment實例化,通過參數param1的傳遞能將Activity中的數據傳遞到Fragment中。通過setArguments()以及getArguments()實現數據從Activity向Fragment傳遞的目的,如下圖所示。

 public static Image1Fragment newInstance(String param1) {
        Image1Fragment fragment = new Image1Fragment();
        //在Activity中創建Bundle數據包,並調用Fragment的setArguments(Bundle bundle)方法
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        fragment.setArguments(args);
        return fragment;
    }
  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            //在Fragment中通過getArguments().getString()獲取Activity傳來的值
            mParam1 = getArguments().getString(ARG_PARAM1);
        }
    }

6.Fragment與Activity通信

  • Fragment調用Activity裡的數據
  在Activity中創建Bundle數據包,並調用Fragment的setArguments(Bundle bundle)方法,此方法在上面的代碼中已經介紹了。
  • Activity調用Fragment裡的數據
  在Fragment中定義一個內部回調接口,讓包含該Fragment的Activity實現該回調接口,這樣Fragment可調用該回調方法將數據傳遞給Activity。下面主要實現在Activity調用Fragment的數據。 先在Fragment中定義一個內部回調接口:
  public interface OnFragmentInteractionListener {
        public void onFragmentInteraction(String uri);
    }

在Fragment的onAttach()方法中將Activity轉換為OnFragmentInteractionListener接口:

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }
private OnFragmentInteractionListener mListener;
if (mListener != null) {
mListener.onFragmentInteraction("需要傳遞給Activity的值");

宿主Activity則需要實現此接口,並重寫onFragmentInteraction(String uri)方法,這樣就實現了數據從Fragment到Activity的傳遞:

public class MainActivity extends ActionBarActivity implements Image1Fragment.OnFragmentInteractionListener
@Override
public void onFragmentInteraction(String uri) {
TextView tv=(TextView)findViewById(R.id.tt);
tv.setText(uri);
}

7.效果截圖

本人致力於Web端與移動端的開發與研究,現主要從事GIS相關開發,如WebGIS、移動GIS開發等。

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved