Android基礎總結2 ---- Fragment與Activity

Android基礎總結2 ---- Fragment與Activity
在Android的基礎中,除了各種控件的使用之外,Fragment和Activity也是很重要的知識點。本博文參考了慕課網的Android的教學資源,學習了一段時間,很有一種想和大家分享的衝動

  • 1.Fragment作爲Activity界面的一部分組成出現
  • 2.可以在一個Activity中同時出現多個Fragment,並且,一個Fragment亦可在多個Activity中使用。
  • 3.在Activity運行過程中,可以添加、移除或者替換Fragment(add()、remove()、replace()) 
  • 4.Fragment可以響應自己的輸入事件,並且有自己的生命週期,當然,它們的生命週期直接被其所屬的宿主activity的生命週期影響。
先看看Fragment 的生命週期吧!看下圖,這裏不多做解釋。

下面是Fragment的生命週期的驗證程序:注意看註釋就明白了

package com.example.fragmentdome;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyFragment3 extends Fragment {

	private TextView tv;

	// 啓動Fragment——>屏幕鎖屏——>屏幕解鎖——>
	//切換到其他的Fragment——>回到桌面——>回到應用——>退出Fragment
	/**
	 * 每次創建都會繪製Fragment的View組件時回調該方法
	 */
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view = inflater.inflate(R.layout.fragment2, container, false);
		TextView tv = (TextView) view.findViewById(R.id.text);
		tv.setText("第一個Fragment");
		Log.i("Main", "Fragment1---onCreateView()");
		return view;
	}

	/**
	 * 當Fragment被添加到Activity時候會回調這個方法,並且只調用一次
	 */
	@Override
	public void onAttach(Activity activity) {
		// TODO Auto-generated method stub
		super.onAttach(activity);
		Log.i("Main", "Fragment1---onAttach()");

	}

	/**
	 * 創建Fragment時會回調,只會調用一次
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		Log.i("Main", "Fragment1---onCreate()");
	}

	/**
	 * 當Fragment所在的Activty啓動完成後調用
	 */
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onActivityCreated(savedInstanceState);
		Log.i("Main", "Fragment1---onActivityCreated()");

	}

	/**
	 * 啓動Fragment
	 * 
	 */
	@Override
	public void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.i("Main", "Fragment1---onStart()");

	}

	/**
	 * 恢復Fragment時會被回調,調用onStart()方法後面一定會調用onResume()方法
	 */
	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.i("Main", "Fragment1---onResume()");

	}

	/**
	 * 暫停Fragment
	 */
	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.i("Main", "Fragment1---onPause()");

	}

	/**
	 * 停止Fragment
	 */
	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.i("Main", "Fragment1---onStop()");

	}

	/**
	 * 銷燬Fragment所包含的View組件時
	 */
	@Override
	public void onDestroyView() {
		// TODO Auto-generated method stub
		super.onDestroyView();
		Log.i("Main", "Fragment1---onDestroyView()");

	}

	/**
	 * 銷燬Fragment時會被回調
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.i("Main", "Fragment1---onDestroy()");

	}

	/**
	 * Fragment從Activity中刪除時會回調該方法,並且這個方法只會調用一次
	 */
	@Override
	public void onDetach() {
		// TODO Auto-generated method stub
		super.onDetach();
		Log.i("Main", "Fragment1---onDetach()");
	}
}


接下來看看Fragment的實現吧:

1 爲Frangment添加用戶界面:

  fragment一般作爲activity的用戶界面的一部分,把它自己的layout嵌入到activitylayout中。一個要fragment提供layout,你必須實現onCreateView()回調方法,然後在這個方法中返回一個View對象,這個對象是fragmentlayout的根。看下面的代碼:

public class MyFragment extends Fragment{
	
	private String aaa;
	
	
	public String getAaa() {
		return aaa;
	}


	public void setAaa(String aaa) {
		this.aaa = aaa;
	}

	/*
	 * setContentView和inflate的區別
	 * setContentView()一旦調用, layout就會立刻顯示UI
	 * 而inflate只會把Layout形成一個以view類實現成的對象,有需要時再用setContentView(view)顯示出來。
	 * 一般在activity中通過setContentView()將界面顯示出來,但是如果在非activity中如何對控件佈局設置操作了,
	 * 這就需要LayoutInflater動態加載。
	 */
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		//layout佈局文件轉換成View對象
		/**
		 * inflate就相當於將一個xml中定義的佈局找出來.
		 * inflater.inflate(resource, root, attachToRoot);
		 * resource:Fragment需要加載的佈局文件
		 * root:加載layout的父ViewGroup
		 * attactToRoot:false,不返回父ViewGroup
		 */
		
		View view = inflater.inflate(R.layout.fragment, container, false);
		TextView text=(TextView) view.findViewById(R.id.text);
		Button button=(Button) view.findViewById(R.id.button);
		text.setText("靜態加載Fragment");
		button.setText("獲取內容");
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
			String value = getAaa();
			Toast.makeText(getActivity(), "value="+value, Toast.LENGTH_SHORT).show();
		<span style="white-space:pre">	</span>}
		});
		return view;
	}
}

上面的代碼中還要注意註釋部分:
/*
	 * setContentView和inflate的區別
	 * setContentView()一旦調用, layout就會立刻顯示UI
	 * 而inflate只會把Layout形成一個以view類實現成的對象,有需要時再用setContentView(view)顯示出來
	 * 一般在activity中通過setContentView()將界面顯示出來,但是如果在非activity中如何對控件佈局設置操作了,
	 * 這就需要LayoutInflater動態加載。
	 */
<pre name="code" class="java" style="font-size: 18px;">//layout佈局文件轉換成View對象
		/**
		 * inflate就相當於將一個xml中定義的佈局找出來.
		 * inflater.inflate(resource, root, attachToRoot);
		 * resource:Fragment需要加載的佈局文件
		 * root:加載layout的父ViewGroup
		 * attactToRoot:false,不返回父ViewGroup
		 */


注:如果你的fragment是從ListFragment中派生的,就不需要實現onCreateView()方法了,因爲默認的實現已經爲你返回了ListView控件對象。    要從onCreateView()方法中返回layout對象,你可以從layoutxml中生成layout對象。爲了幫助你這樣做,onCreateView()提供了一個LayoutInflater對象。

  另外,onCreateView()參數中的container是存放fragmentlayoutViewGroup對象savedInstanceState參數是一個Bundle,跟activityonCreate()Bundle差不多,用於狀態恢復。此處的Bundle中存放的數據與onCreate()中存放的數據還是不同的。

Inflate()方法有三個參數:

  • 1 layout的資源ID。
  • 2 存放fragment的layout的ViewGroup。
  • 3 布爾型數據表示是否在創建fragment的layout期間,把layout附加到container上了

 2 把Frangment添加到Activity:

在Activity中加載Frangment的方式有2種,一種是靜態加載(通過XML靜態配置),一種是動態加載(通過程序動態創建)。

如方法一:在activity的layoutxml文件中聲明fragment (靜態配置)

看程序:

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

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="發送" />
    <!-- 靜態加載傳值 -->
    <fragment 
        android:id="@+id/frag"
        android:name="com.example.fragmentdome.MyFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

當系統創建layout時,它實例化fragment,然後調用onCreateView()方法,以獲取fragment的layout。系統把fragment返回的view對象插入到<fragment>元素的位置,直接代替<fragment>元素。每個fragment都需要提供一個ID,系統在activity重新創建時用它來恢復fragment們,你也可以用它來操作fragment進行其它的事物,比如刪除它。


有三種方法給fragment提供ID:

  • 1 爲android:id屬性賦一個數字。
  • 2 爲android:tag屬性賦一個字符串。
  • 3如果你沒有使用上述任何一種方法,系統將使用fragment的容器的ID

方法二:在代碼中添加fragment到一個ViewGroup(動態加載)

  <span style="white-space:pre">	</span>MyFragment2 fragment2=new MyFragment2();
            //從 FragmentManager 獲得一個FragmentTransaction的實例 :
            FragmentManager fragmentManager = getFragmentManager();
            FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
            //通過Fragment的ID來加載
            beginTransaction.add(R.id.frame, fragment2);
            /*
             * 在調用commint()之前,你可以用addToBackStack()把事務添加到一個後退棧中,
             * 這個後退棧屬於所在的activity。有了它,就可以在用戶按下返回鍵時,返回到fragment們執行事務之前的狀態。
             */
            beginTransaction.addToBackStack(null);
            beginTransaction.commit();


/*
			 * 解釋:調用addToBackStack(),fragment就被放入後退棧中,於是當用戶按下返回鍵時,事務發生回溯,原先的fragment又回來了。
			 * 如果你向事務添加了多個動作,比如多次調用了add(),remove()等之後又調用了addToBackStack()方法,
			 * 那麼所有的在commit()之前調用的方法都被作爲一個事務。當用戶按返回鍵時,所有的動作都被反向執行(事務回溯)。
			 * 事務中動作的執行順序可隨意,但要注意以下兩點:
			 * 1. 你必須最後調用commit()。
			 * 2. 如果你添加了多個fragment,那麼它們的顯示順序跟添加順序一至(後顯示的覆蓋前面的)。
			 */

    爲了完成fragment的事務(比如添加,刪除,替換等),你必須使用FragmentTransaction的方法。你可以從activity獲取到FragmentTransaction,如上面的

FragmentManager fragmentManager getFragmentManager()
FragmentTransaction fragmentTransaction fragmentManager.beginTransaction();

  然後你可以用add()方法添加一個fragment;

  最後必須調用方法commit()提交這些改變。


3 與其他Fragment的通訊


這個其實很簡單,依靠Frangment的事務處理機制發送數據。首先定義一個Bundle,將要出入的數據設置好。然後利用fragment.setArguments(bundle);發送數據包,利用管理者模式,管理事務的模式,通過Fragment的Tag方式來加載到指定的Frangment.最後不要忘了提交事務。看程序:

package com.example.fragmentdome;

import com.example.fragmentdome.MyFragment5.MyListener;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity4 extends Activity implements MyListener {

	private EditText editext;
	private Button send;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main4);
		editext = (EditText) findViewById(R.id.editText);
		send = (Button) findViewById(R.id.send);
		
		
		send.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				String text = editext.getText().toString();
				MyFragment5 fragment5 = new MyFragment5();
				Bundle bundle = new Bundle();
				bundle.putString("name", text);
				//發送數據包
				fragment5.setArguments(bundle);
				//管理者模式,管理事務的模式
				FragmentManager fragmentManager = getFragmentManager();
				FragmentTransaction beginTransaction = fragmentManager
						.beginTransaction();
				//通過Fragment的Tag方式來加載
				
				beginTransaction.add(R.id.layout, fragment5, "fragment5");
				beginTransaction.commit();
				
				Toast.makeText(MainActivity4.this, "向Fragment發送數據" + text,
						Toast.LENGTH_SHORT).show();
			}
		});	
		
		FragmentManager fragmentManager = getFragmentManager();
		Fragment findFragmentById = fragmentManager.findFragmentById(R.id.frag);
        MyFragment frag=(MyFragment) findFragmentById;
        frag.setAaa("fragment靜態傳值");
	}

	@Override
	public void thank(String code) {
		// TODO Auto-generated method stub
		Toast.makeText(MainActivity4.this, "已成功接收到" + code + ",客氣了!",
				Toast.LENGTH_SHORT).show();
	}

}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章