Fragment (一)

 

1,簡介

Fragement(碎片)容許將Activity拆分紅多個徹底獨立封裝的可重用組件,每一個組件有它本身的生命週期和UI佈局,因而可知,Fragement依賴於Activity,它的生命週期直接被其所屬的宿主activity的生命週期影響。android

形象的理解Fragement,手機屏幕以下圖所示:編程

image

Fragement 具備如下優勢:app

  • 組件重用,多個Activity可重用同一個Fragement;
  • 爲不一樣屏幕大小的設備建立動態的靈活的UI,在Activity運行過程當中,能夠添加、移除或者替換Fragment(add()、remove()、replace())

 

2,生命週期

Fragement的生命週期鏡像它的宿主Activity的生命週期事件。若Activity進入active-resumed狀態的時候,添加或者移除一個Fragement就會影響它本身的生命週期。框架

Fragement生命週期方面以下:ide

/**
 * Listing 4-4: Fragment skeleton code
 * Listing 4-5: Fragment lifecycle event handlers
 */
package com.paad.fragments;

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

public class MySkeletonFragment extends Fragment {

  // Called when the Fragment is attached to its parent Activity.
  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
    // Get a reference to the parent Activity.
  }

  // Called to do the initial creation of the Fragment.
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Initialize the Fragment.
  }

  // Called once the Fragment has been created in order for it to
  // create its user interface.
  @Override
  public View onCreateView(LayoutInflater inflater, 
                           ViewGroup container,
                           Bundle savedInstanceState) {
    // Create, or inflate the Fragment's UI, and return it. 
    // If this Fragment has no UI then return null.
    return inflater.inflate(R.layout.my_fragment, container, false);
  }



  // Called once the parent Activity and the Fragment's UI have 
  // been created.
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Complete the Fragment initialization �particularly anything
    // that requires the parent Activity to be initialized or the 
    // Fragment's view to be fully inflated.
  }

  // Called at the start of the visible lifetime.
  @Override
  public void onStart(){
    super.onStart();
    // Apply any required UI change now that the Fragment is visible.
  }

  // Called at the start of the active lifetime.
  @Override
  public void onResume(){
    super.onResume();
    // Resume any paused UI updates, threads, or processes required
    // by the Fragment but suspended when it became inactive.
  }

  // Called at the end of the active lifetime.
  @Override
  public void onPause(){
    // Suspend UI updates, threads, or CPU intensive processes
    // that don't need to be updated when the Activity isn't
    // the active foreground activity.
    // Persist all edits or state changes
    // as after this call the process is likely to be killed.
    super.onPause();
  }

  // Called to save UI state changes at the
  // end of the active lifecycle.
  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save UI state changes to the savedInstanceState.
    // This bundle will be passed to onCreate, onCreateView, and
    // onCreateView if the parent Activity is killed and restarted.
    super.onSaveInstanceState(savedInstanceState);
  }

  // Called at the end of the visible lifetime.
  @Override
  public void onStop(){
    // Suspend remaining UI updates, threads, or processing
    // that aren't required when the Fragment isn't visible.
    super.onStop();
  }

  // Called when the Fragment's View has been detached.
  @Override
  public void onDestroyView() {
    // Clean up resources related to the View.
    super.onDestroyView();
  }

  // Called at the end of the full lifetime.
  @Override
  public void onDestroy(){
    // Clean up any resources including ending threads,
    // closing database connections etc.
    super.onDestroy();
  }

  // Called when the Fragment has been detached from its parent Activity.
  @Override
  public void onDetach() {
    super.onDetach();
  }
}

生命週期要點:佈局

  • 開始於綁定到它的你Activity,結束於從父Activity分離,對應於onAttach 和onDetach事件,一般狀況下,onAttach用來獲取一下Fragement的父Activity的引用,爲進一步初始化作準備;
  • 不能依賴調用onDestroy方法來銷燬它,由於此方面不定會被執行;
  • 與Activity同樣,應該使用onCreate方法來初始化Fragement,在其生命週期內建立的做用域對象,且確保只建立一次;
  • 在onCreateView和onDestroyView上初始化和銷燬UI;
  • 當Fragement暫停或中止時,保存全部的UI狀態和持久化全部的數據。

3,使用Fragement

最佳實踐是使用容器View來建立佈局,將Fragement在運行時放入容器內ui

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/ui_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" >
    </FrameLayout>

  <FrameLayout
    android:id="@+id/details_container"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="3"    
    android:visibility =」gone」    --隱藏
  />
</LinearLayout>
 

在運行時使用Fragement transaction來動態填充佈局,從而當配置改變時,能確保一致性,框架代碼以下:this

package com.paad.fragments;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;

public class MyFragmentActivity extends Activity {

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Inflate the layout containing the Fragment containers
    setContentView(R.layout.fragment_container_layout);
    
    FragmentManager fm = getFragmentManager();

    // Check to see if the Fragment back stack has been populated
    // If not, create and populate the layout.
    DetailsFragment detailsFragment = 
      (DetailsFragment)fm.findFragmentById(R.id.details_container);
    
    if (detailsFragment == null) {
       FragmentTransaction ft = fm.beginTransaction(); 
       ft.add(R.id.details_container, new DetailsFragment());
       ft.add(R.id.ui_container, new MyListFragment());
       ft.commit();
     }
  }
}
package com.paad.weatherstation;

import com.paad.fragments.R;

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

public class DetailsFragment extends Fragment {
  
  public DetailsFragment() {
  }

  // Called once the Fragment has been created in order for it to
  // create its user interface.
  @Override
  public View onCreateView(LayoutInflater inflater, 
                           ViewGroup container,
                           Bundle savedInstanceState) {
    // Create, or inflate the Fragment's UI, and return it. 
    // If this Fragment has no UI then return null.
    return inflater.inflate(R.layout.details_fragment, container, false);
  }
}
package com.paad.weatherstation;

import com.paad.fragments.R;

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

public class MyListFragment extends Fragment {
  
  public MyListFragment() {
  }

  // Called once the Fragment has been created in order for it to
  // create its user interface.
  @Override
  public View onCreateView(LayoutInflater inflater, 
                           ViewGroup container,
                           Bundle savedInstanceState) {
    // Create, or inflate the Fragment's UI, and return it. 
    // If this Fragment has no UI then return null.
    return inflater.inflate(R.layout.list_fragment, container, false);
  }
}

Fragement 和Activity之間的接口:spa

  • 任何Fragement中可以使用getActivity方法返回對父Activity的引用;
  • 在fragement須要和它的主Activity共享事件的地方,最好在Fragement中建立回調接口,而主Activity必須實現它來監聽Fragement中的改變;
package com.paad.fragments;

import android.app.Activity;
import android.app.Fragment;

/**
 * MOVED TO PA4AD_Ch04_Seasons
 */
public class SeasonFragment extends Fragment {

  public interface OnSeasonSelectedListener {
    public void onSeasonSelected(Season season);
  }
    
  private OnSeasonSelectedListener onSeasonSelectedListener;
  private Season currentSeason;

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
      
    try {
      onSeasonSelectedListener = (OnSeasonSelectedListener)activity;
    } catch (ClassCastException e) {
      throw new ClassCastException(activity.toString() + 
                " must implement OnSeasonSelectedListener");
    }
  }

  private void setSeason(Season season) {
    currentSeason = season;
    onSeasonSelectedListener.onSeasonSelected(season);
  }
  
}

若理解有難道,能夠了解一下JAVA編程思想中的上塑造型,內部類,接口方面的知識rest

相關文章
相關標籤/搜索