1. 程式人生 > >Android開發筆記: android四大元件之Activity

Android開發筆記: android四大元件之Activity

一,什麼是Activity? 活動

Activity:一個單獨的螢幕 一個顯示的視窗 一個介面
定義:用來顯示android應用的介面的一個元件!!!

什麼是android元件:
android應用:主要由4大元件構成
元件:建立  銷燬 :一個元件從建立到銷燬的過程:生命週期
不同的元件功能不同
android的四大元件:
Activity(介面)----接待
BroadCastReceiver(廣播)---品牌
Service(服務)---做服務
ContentProvider(內容提供者)---真正提供具體服務
使用者:服務

NOTO:anroid元件都必須在清單檔案中註冊

二,怎麼樣在清單檔案中註冊元件:

<activity
            android:name="com.tz.katehome.MainActivity"  activity名字
            android:label="@string/app_name" > activity的標籤
        </activity>
意圖過濾器:找到元件
 <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
 上面的程式碼作用:指定我們當前的android應用第1個啟動的activity


三,Activity的生命週期

        (官方文件 :1,翻牆軟體  2,國內的映象 3,sdk--dosc目錄)

國內的映象:http://wear.techbrood.com/guide/components/activities.html


onCreate,建立activity

onStart,可以看到activity

onResume,獲取焦點,使用者可以進行互動

onPause,失去焦點,被其他activity部分遮擋

onStop ,不可見activity

onDestroy, 銷燬activity

onPause->onResume, 彈出的activity退出時,主activity會進入onResume方法

onStop->onRestart->onStart

四,Activity的啟動方式:(啟動模式)

(1)顯示啟動activity,只能啟動當前應用activity

//一個activity啟動另一個actiivty,只能在當前應用啟動activity

  //:Intent意圖--四大元件的紐帶

//引數:1,當前activity的context  2,啟動得到Activity的.class
//activity啟動1
//Intent intent = new Intent(this,OtherActivity.class);
//activity啟動2
Intent intent = new Intent();
//intent.setClassName(this,"com.tz.activitylifecycle.OtherActivity");
//activity啟動3
//intent.setClassName(getPackageName(),"com.tz.activitylifecycle.OtherActivity");
//activity啟動4
//intent.setClass(this, OtherActivity.class);
//activity啟動5  Component :組織 元件
ComponentName component = new ComponentName(this, OtherActivity.class);
intent.setComponent(component);

(2)隱式啟動 ,跨程序啟動activity

        意圖過濾器---不同應用之間來啟動Actvity(其他元件)
Intent是基於訊息通訊機制

<intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

上面這的action和catetory是用來配置應用的第1個啟動的Actvit的(可以配置多個,但是會啟動xml中的第1個)


Intent-filter:包含兩個部分

1,目的【action】--------要到哪裡去
2,內容【category,data】------去的路上要帶什麼,區分性資料和內容性資料
意圖過濾器的配置:

1,action+category

總結:
(1),所有的activity的過濾器都必須設定(但是第1個啟動的activity不必)
<category android:name="android.intent.category.DEFAULT"/>
(2),在startActivity(Intent intent)方法內部預設設定了category的值為
android.intent.category.DEFAULT"
(3),(在沒有設定資料)只要intent中action和category都出現在Intent-Filteer中就能與之匹配,
否者匹配失敗

2,actoin+data

URI:統一資源標示 跟網址的組成部分是一樣
Uri:  tzEdu://www.tanzhou.com/kate

uri格式:http://blog.csdn.net/sunny09290/article/details/7514963

URL:統一資源定位  http://www.baidu.com/index.html/3(網址)
http://   -----scheme   主題
www.baidu.com  ---host  主機地址
index.html    ----path路徑
3 -----id

總結:
1)如果在Intent-filter中制定了data,如果要匹配到此Activity,必須在
 intent中設定data,否者匹配不到

2)Scheme屬性沒有指定,其他屬性都無效,host沒有指定 port path都無效

3 action+data+miniType

<data android:scheme="tzEdu" android:host="www.tanzhou.com" 
                    android:path="/kate"  注意path一定要加 //>
                <data android:mimeType="image/*"/>

1)當有data和miniType同時存在,不要單獨通過 setData() 和setType()方法進行設定
要通過setDataAndType()同時設定資料和型別才可以匹配

4 action + minaType

<data android:mimeType="image/*"/>
 
intent.setType("image/png");

五,設定點選事件:

(1)xml佈局中為要設定點選事件的控制元件加屬性:
android:onClick="startOther"

然後在activity中定義startOther(View v){}方法

(2)activity作為監聽器
在Activity獲取控制元件物件,然後通過setOnClickListener(this);
  Activity實現OnClickListener介面 然後重寫介面的onClick方法


(3)匿名內部類監聽器
start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {

}
});
(4)重寫監聽器類  實現OnClickListener介面

btn_start.setOnClickListener(new MyOnclicklistener());


public class MyOnclicklistener implements View.OnClickListener{


    @Override
    public void onClick(View v) {


    }
}


(5)註解的方式(ioc)

六 activity模式

Activity一共有以下四種launchMode:

1.standard

2.singleTop

3.singleTask

4.singleInstance

作用概述:規定是否新建activity,是否公用task(task:應用啟動時,會建立一個對應的task。task主要負責對activity進行管理。)

使用方法:我們可以在AndroidManifest.xml配置<activity>的android:launchMode屬性為以上四種之一即可,預設情況下為標準模式。

第一種模式:standard

這是系統預設的啟動模式,即:不用再在AndroidManifest.xml配置<activity>的android:launchMode。

作用:標準模式下,只要用intent 跳轉,系統會自動建立一個新的activity例項,並且放在棧頂。按下回退鍵,系統會從頂部開始一個一個清除Activity。

第二種模式:singleTop

作用:singleTop模式下,如果要跳轉的activity的例項已經在棧中存在,看其是否位於棧頂,如果位於棧頂,則直接啟用舊的,不在建立例項,如果不在棧頂,則建立一個新的例項。

第三種模式:singleTask

作用:如果要啟動的activity的例項不存在,則建立一個新的例項。如果要啟動activity的例項在棧中已經存在,則清除此activty舊例項以上的所有activity,啟動舊activity的例項並且至於棧頂,開始執行OnResum()方法。

問題:啟動模式為singletask,activity無法獲取到intent的傳值問題。

原因:

1.啟動一個為啟動過的activity ,會獲取到新的 intent。也就是說就是啟動模式設定為:singletask,第一次啟動介面是傳遞的資料是可以接受到的。

2.當此介面再次被啟動時,因為他的啟動模式是:singletask,所以不會重新建立一個activity,而是啟動舊的activity例項,通過getIntent()方法獲取到的 intent 也是舊的Intent,沒有攜帶新的資料。所以無法獲取到資料。

解決方法:重寫這個方法,並且把呼叫setIntent(intent),對Intent進行更新。此方法在activity(啟動模式為:singletask)的介面第二次啟動時,在onresume()方法之前被回撥。

         @Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
setIntent(intent);
}

第四種模式:singleInstance

作用:系統會重新啟用一個棧,並且把這個activity放入新的棧中,並且保證不會再讓其他的activity進入。再次跳轉該activity,activity如果存在則直接啟用,不存在建立新的。

注意:5.0以上的部分手機,一個應用存在多個棧的情況下,切到後臺,後臺會出現多個後臺同一個應用的介面,這是因為介面不在同一個棧中。

七  Activity棧(Task)的相關知識總結:

1.Activity的affinity(親和力)

2.Intent幾種常見的flags

3.<activity>與task相關屬性


第一個: Affinity(密切關係

在系統預設情況下,開啟一個app,系統預設包名為affinity的值。task自身的affinity的值取決於根activity的affinity。具有相同的affinity的activity同屬於一個task。

例項1:

           建立兩個demo App分別命名為 A 和 B。從 A 的主介面通過意圖跳轉到 B 的主介面介面。此時兩個app的介面位於同一個App A的棧內。如圖:


第二個:  Intent 常用的 flag:

1.FLAG_ACTIVITY_NEW_TASK    根據Activity 的 affinity去尋找task 棧。如果一個task 的 affinity與 activity 的 affinity的相同,則                                                                      Activity會壓入棧中。如果沒有找到相同的,則新建立棧,並且把activity壓入棧中。

例項1: 從App  A主介面跳轉到 App B主介面。給Intent新增FLAG_ACTIVITY_NEW_TASK    標識。

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

               

結果會建立兩個棧。App A 的介面在App A 的棧裡。App B 的介面在 App B 的棧裡邊。

例項2:在例項1 的基礎上,在App B裡新增程式碼,給App B的主介面 在manifest 中新增  

  <activity
            android:name="com.example.b.MainActivity"
            
android:taskAffinity="com.example.a"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="hello" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

com.example.a為App A 的包名。這樣的結果是 App A 和App B的介面會在同一個棧裡。

2.FLAG_ACTIVITY_CLEAR_TOP  檢查棧內是否存在要啟動的Activity例項,如果存在例項,則會呼叫舊的Activity例項,並且清除此Activty                                                        上面的所有的activty,使其至於棧頂顯示出來。

注意:1. intnet.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 跳轉的頁面會從 OnCreate()方法開始執行。

           2.FLAG_ACTIVITY_CLEAR_TOP  相當於 載入模式的 signleTask

3.FLAG_ACTIVITY_SINGLE_TOP  相當於載入模式的  signleTop

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET   如果Intent 包含此屬性,那麼,要跳轉的activity和次activity上的所有介面,都會在task重置時被清除。(待定)

5.FLAG_ACTIVITY_NO_HISTORY  如果Intent 包含此屬性,那麼,要啟動activity 將顯示一次,不會再task棧內儲存。

6.FLAG_ACTIVITY_REORDER_TO_FRONT    把已經存在的介面拿到棧頂,

例:ABCD已經存在,D通過FLAG_ACTIVITY_REORDER_TO_FRONT    去啟動A,則棧內順序BCDA。

7.FLAG_ACTIVITY_BROUGHT_TO_FRONT(測試不起作用)

八,Activity之間資料的傳遞

Activity之間傳資料
* 1,基本型別和陣列

* 2, 傳物件     a,bundle物件(andoid寫好的)

* b,自定義的物件:序列化  java中用:Serializable  不可以跨程序  
* android中用:Parcelable 可以跨程序
NOTE: parcelable序列化的時候,write屬性的順序必須和read的順序一致
* android中推薦使用:Parcelable

  自定義物件要implements Serializable 或者Parcelable

                 Serializable:簡單,不需要實現方法,不跨程序

                 Parcelable:複雜,需要實現相關方法,且讀寫物件順序要一致,跨程序

傳遞圖片的bitmap
intent.putExtra("bitmap",bitmap);

Bitmap bitmap = intent.getParcelableExtra("bitmap");
Activity之間的回傳資料
1,啟動方式:
startActivityForResult(intent, 101);//請求碼
2,返回方式:
setResult(100,intent);
finish();//銷燬當前介面
3,回傳過來的資料會被 onActivityResult接收
通過請求碼和結束碼來區分不同請求和回傳值

             Intent intent = new Intent(this,SecondActivity.class);
/**
* 帶資料
* 1,基本型別和陣列
* 2, 傳物件 a,bundle物件(andoid寫好的)
* b,自定義的物件:序列化  java:Serializable  不可以跨程序  
* android:Parcelable 可以跨程序
* android中推薦使用:Parcelable
*/
/*intent.putExtra("name", "二狗子");//key-value:鍵值對
intent.putExtra("age", 18);*/

/*Bundle bundle = new Bundle();//袋子
bundle.putString("name","二狗子");
bundle.putInt("age",18);
intent.putExtra("bundle", bundle);*/

/*Student stu = new Student();
stu.setName("二狗子");
stu.setAge(18);
intent.putExtra("stu", stu);//java序列化*/

/*Person  p = new Person("旺財",12);
intent.putExtra("person", p);*/

Bitmap  bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
intent.putExtra("bitmap",bitmap);

startActivity(intent);

package com.example.kateintent_tz;

import java.io.Serializable;

public class Student implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	
}

package com.example.kateintent_tz;

import android.os.Parcel;
import android.os.Parcelable;
/**
 * public class MyParcelable implements Parcelable {
     private int mData;

     public int describeContents() {
         return 0;
     }

     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }

     public static final Parcelable.Creator<MyParcelable> CREATOR
             = new Parcelable.Creator<MyParcelable>() {
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);
         }

         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     };
     
     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }
 * @author Administrator
 *
 */
public class Person implements Parcelable{
	private String name;
	int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
    	out.writeString(name);
        out.writeInt(age);
    }

    public static final Parcelable.Creator<Person> CREATOR
            = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
    
    private Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
    
}

案例:Activity--啟動相簿----相簿返回圖片
 知識:手機中放入(視訊 音訊  圖片 )多媒體檔案,android系統會將多媒體檔案資訊儲存到系統資料庫中