Android之Activity

我叫阿狸貓發表於2014-02-10
Activity
    1.什麼是Activity
               Android四大元件之一, 程式顯示的介面
    2.怎麼建立
                定義類繼承Activity
                在清單檔案中宣告<activity>節點
    3.啟動Activity
                顯式意圖:
                        建立Intent物件, 設定指定的類, startActivity()
                        通常用在應用程式內部介面跳轉
                隱式意圖:
                        建立Intent物件, 設定動作, 資料, 型別等資訊, startActivity()
                        通常用在多個應用程式之間跳轉
    4.關閉Activity
                按退出鍵
                執行finish()
    5.啟動Activity時傳遞資料
                使用啟動Activity的Intent物件的putExtra()方法可以攜帶一些資料到新的Activity中
                新的Activity中可以呼叫getIntent()方法得到Intent物件, 再呼叫getStringExtra(), getIntExtra()等方法即可得到資料
                Intent中可以攜帶8中基本資料型別, 基本資料型別陣列, Bundle, CharSequence, Serializable, Parcelable
    6.關閉Activity時返回資料
                如果啟動Activity時需要返回資料, 那麼必須使用startActivityForResult()方法來啟動
                在新的Activity中呼叫setResult()方法可以設定結果資料
                當新的Activity關閉之後, 原Activity自動執行onActivityResult()方法, 該方法的引數即是新Activity中傳回的結果資料
    7.生命週期
                onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(), onRestart()
    8.橫豎屏切換
                預設情況下, Activity會隨著感測器方向改變而改變, 在改變的時候會摧毀重建.
                如果希望摧毀時儲存資料, 可以在onSaveInstanceState()方法中儲存
                如果希望重建時恢復資料, 可以在onRestoreInstanceState()方法中恢復
                如果不希望摧毀重建, 可以在<activity>標籤中設定android:configChanges="orientation", 這樣在改變方向是就會執行onConfigurationChanged()
                如果需要指定Activity方向, 可以在<activity>標籤中設定android:screenOrientation屬性
    9.啟動模式

                standard, singleTop, singleTask, singleInstance


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class TestActivityActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    public void open(View view){
    	//1.建構函式指定新的Activity
    	//Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	Intent intent = new Intent();
    	//2.使用setClass指定
    	//intent.setClass(getApplicationContext(), OtherActivity.class);
    	//3.使用setClassName指定activity的類名
    	//intent.setClassName(getApplicationContext(), "com.xxc.activity.OtherActivity");
    	//4.使用setClassName指定其他應用的activity
    	intent.setClassName("com.xxc.webservice", "com.xxc.webservice.MainActivity");
    	startActivity(intent);
    }
}


1.建立Activity

*自定義的Activity需要繼承Activity

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

public class OtherActivity extends Activity {//需要繼承Activity

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.other);
    }
}

*在AndroidManifest.xml清單檔案中配置自定義Activity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxc.activity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".TestActivityActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 配置自定義的Activity -->
        <activity android:name=".OtherActivity"/>
    </application>
</manifest>

*在MainActivity中呼叫自定義Activity,呼叫自定義Activity有4種方法

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class TestActivityActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    public void open(View view){
    	//1.建構函式指定新的Activity
    	//Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	Intent intent = new Intent();
    	//2.使用setClass指定
    	//intent.setClass(getApplicationContext(), OtherActivity.class);
    	//3.使用setClassName指定activity的類名
    	//intent.setClassName(getApplicationContext(), "com.xxc.activity.OtherActivity");
    	//4.使用setClassName指定其他應用的activity
    	intent.setClassName("com.xxc.webservice", "com.xxc.webservice.MainActivity");
    	startActivity(intent);
    }
}
自定義Activity佈局配置省略...

效果如下:



2.顯式意圖和隱式意圖

public class TestActivityActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    /**
     * 顯式意圖呼叫 
     */
    public void explicit(View view){
    	//1.建構函式指定新的Activity
    	Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	//Intent intent = new Intent();
    	//2.使用setClass指定
    	//intent.setClass(getApplicationContext(), OtherActivity.class);
    	//3.使用setClassName指定activity的類名
    	//intent.setClassName(getApplicationContext(), "com.xxc.activity.OtherActivity");
    	//4.使用setClassName指定其他應用的activity
    	//intent.setClassName("com.xxc.webservice", "com.xxc.webservice.MainActivity");
    	startActivity(intent);
    }
    
    /**
     * 隱式意圖呼叫 
     */
    public void implicit(View view){
    	Intent intent = new Intent();
    	//開啟瀏覽器
    	/*intent.setAction(Intent.ACTION_VIEW);//android.intent.action.VIEW
    	intent.setData(Uri.parse("http://www.baidu.com"));
    	startActivity(intent);*/
    	
    	//開啟mp3   如果是模擬器的話,檔名不能用中文
    	/*intent.setAction(Intent.ACTION_VIEW);//android.intent.action.VIEW
    	intent.setDataAndType(Uri.parse("file:///mnt/sdcard/a.mp3"), "audio/*");
    	startActivity(intent);*/
    	
    	//開啟視訊
    	/*intent.setAction(Intent.ACTION_VIEW);//android.intent.action.VIEW
    	intent.setDataAndType(Uri.parse("file:///mnt/sdcard/s.mp3"), "video/*");
    	startActivity(intent);*/
    	
    	//開啟圖片
    	/*intent.setAction(Intent.ACTION_VIEW);
    	intent.setDataAndType(Uri.parse("file:///mnt/sdcard/s.jpg"), "image/*");
    	startActivity(intent);*/
    	
    	//將自己建立的activity  註冊為一個動作,供應用隱式呼叫
    	intent.setAction("com.xxc.action.OTHER_ACTIVITY");//如果要隱式呼叫這個自定義的activity,必須在清單檔案中把其他的action配置去掉
    	
    	startActivity(intent);
    }
}

清單檔案

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxc.activity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
	<uses-permission android:name="android.permission.CALL_PHONE"/>
	<uses-permission android:name="android.permission.INTERNET"/>
	
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".TestActivityActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 配置自定義的Activity -->
        <activity android:name=".OtherActivity">
			<intent-filter><!-- 配置意圖過濾器,在裡面設定這個activity所匹配的動作 -->
			    <!-- 
			    	如果隱式呼叫自定義的activity,intent.setAction("com.xxc.action.OTHER_ACTIVITY");那麼必須把其他的action標籤去掉,否則出錯
			     -->
			   	<action android:name="com.xxc.action.OTHER_ACTIVITY"/>
				<action android:name="android.intent.action.CALL"/><!-- 當打電話的時候,會告訴使用者此activity也可用,讓使用者選 -->
				<action android:name="android.intent.action.VIEW"/>
				<data android:scheme="tel"/><!-- 約束,url是以tel開頭 -->
				<data android:scheme="http"/>
				<data android:scheme="file" android:mimeType="image/*"/><!-- 當開啟圖片的時候,會告訴使用者此activity也可用,讓使用者選 -->
				<data android:scheme="file" android:mimeType="video/*"/><!-- 當開啟視訊的時候,會告訴使用者此activity也可用,讓使用者選 -->
				<data android:scheme="file" android:mimeType="audio/*"/><!-- 當開啟音訊的時候,會告訴使用者此activity也可用,讓使用者選 -->
				<category android:name="android.intent.category.DEFAULT"/>              
			</intent-filter>            
        </activity>
    </application>
</manifest>


3.Activity之間傳遞資料

*開啟Activity的時候傳遞資料

主Activity

public class TestActivityActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    //傳遞引數一
    public void open1(View view){
    	Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	intent.putExtra("name", "xxc");
    	intent.putExtra("age", 10);
    	startActivity(intent);
    }
    
    //傳遞引數二,由於使用第一種方式傳遞多個引數名一樣的引數的時候,後者會覆蓋前者,所以要用以下方法傳遞
    public void open2(View view){
    	Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	//將引數名一樣的引數,把值設定到Bundle中
    	Bundle bundle1 = new Bundle();
    	bundle1.putString("name", "pkq");
    	bundle1.putInt("age", 5);
    	
    	Bundle bundle2 = new Bundle();
    	bundle2.putString("name", "xxm");
    	bundle2.putInt("age", 10);
    	//再將Bundle設定到意圖中傳遞過去
    	intent.putExtra("bundle1", bundle1);
    	intent.putExtra("bundle2", bundle2);
    	
    	startActivity(intent);
    }
    
    //傳遞domain引數,domain類必須實現
    public void open3(View view){
    	Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	intent.putExtra("person", new Person("xxc1",100));
    	
    	startActivity(intent);
    }
}

新建的Activity

public class OtherActivity extends Activity {

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.other);
        //對應第一種傳遞引數方式的獲取方式:
       /* Intent intent = getIntent();
        String name = intent.getStringExtra("name");
        int age = intent.getIntExtra("age", -1);*/
        
        //對應第二種傳遞引數方式的獲取方式:
      /*  Intent intent = getIntent();
        Bundle bundle1 = intent.getBundleExtra("bundle1");
        Bundle bundle2 = intent.getBundleExtra("bundle2");
        
        String name1 = bundle1.getString("name");
        int age1 = bundle1.getInt("age");
        
        String name2 = bundle2.getString("name");
        int age2 = bundle2.getInt("age");*/
        
      //對應第三種傳遞引數方式的獲取方式:
        Intent intent = getIntent();
        Person person = (Person) intent.getSerializableExtra("person");
        
        
        TextView otherTV = (TextView) findViewById(R.id.otherTV);
        otherTV.setText("name1:"+person.getName()+",age1:"+person.getAge());
	}
}
自定義Activity佈局配置省略...

效果如下:



*關閉Activity的時候傳遞資料

public class TestActivityActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    public void open(View view){
    	Intent intent = new Intent(getApplicationContext(),OtherActivity.class);
    	startActivityForResult(intent, 100);//啟動一個Activity,等待返回結果,執行onActivityResult回撥函式
    }
    
    /**
     * 當前Activity啟動的新Activity關閉時,就會自動執行這個方法
     * requestCode 就是startActivityForResult(intent,100)  100  開啟Activity時候設定的值
     * 		用處是:用於區分,當有多個按鈕分別開啟Activity時候,哪個按鈕對應哪個Activity
     * resultCode 就是setResult(200, intent);  200  關閉Activity時候設定的返回值
     * 		用處:與requestCode同理
     */
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	TextView mainTV = (TextView) findViewById(R.id.mainTV);
    	mainTV.setText("age="+data.getIntExtra("age",-1));
    }
}
新建的Activity

public class OtherActivity extends Activity {

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.other);

        Intent data = getIntent();
        data.putExtra("age", 100);
        setResult(200, data);
	}
	
	public void close(View view){
		finish();//關閉當前Activity
	}
}

自定義Activity佈局配置省略...

效果如下:



Activity的生命週期

Acitivity三種狀態:(Activity的顯示相當於一個棧的形式,先開後關,第一個開的在棧底,最後開的在棧頂)

執行:activity在最前端執行

停止:activity不可見,完全被覆蓋

暫停:activity可見,但前端還有其他比較小的activity


生命週期相關方法

onCreate:建立時呼叫,或者程式在暫停、停止狀態下被殺死之後重新開啟時也會呼叫

onStartonCreate之後或者從停止狀態恢復時呼叫  顯示後執行

onResumeonStart之後或者從暫停狀態恢復時呼叫,從停止狀態恢復時由於呼叫onStart,也會呼叫onResume   獲取焦點後執行

onPause:進入暫停、停止狀態,或者銷燬時會呼叫    失去焦點後執行

onStop:進入停止狀態,或者銷燬時會呼叫          不顯示後執行

onDestroy:銷燬時呼叫

onRestart:從停止狀態恢復時呼叫           





橫豎屏切換

//這個方法是在橫豎屏切換的時候執行,需要在activity標籤中配置android:configChanges="orientation",如果不配置,那麼每次切換螢幕就是重新啟動一個Activity
public void onConfigurationChanged(Configuration newConfig) {
	super.onConfigurationChanged(newConfig);
	System.out.println("橫豎屏切換: "+newConfig.orientation);
}
	
//橫豎屏切換的時候儲存資料的方法
protected void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putString("data", "銷燬前儲存的資料!!!");
	System.out.println("onSaveInstanceState");
}
	
//恢復螢幕之後,恢復資料操作
protected void onRestoreInstanceState(Bundle savedInstanceState) {
	super.onRestoreInstanceState(savedInstanceState);
	System.out.println("onRestoreInstanceState");
	System.out.println(savedInstanceState.getString("data"));
}
設定螢幕橫豎
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxc.life"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <!-- 
        	android:configChanges="orientation"  配置這個以後,橫豎屏切換執行的是onConfigurationChanged方法,而不是先摧毀再重新啟動一個Activity
        	android:screenOrientation=""   這個配置的是螢幕如何切換
        					landscape:橫屏
        					reverseLandscape:反著的橫屏
        					portrait:豎屏
        					reversePortait:反著的豎屏
        					sensor:使用感測器
        					sensorLandscape:只能在兩個橫屏之間切換
        					sensorPortait:只能在兩個豎屏直接切換
        					fullSensor:上下左右都能切換
         -->
        <activity
            android:configChanges="orientation"
            android:screenOrientation="sensor"
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".FullScreenActivity"/>
        <!-- 
        	android:theme="@android:style/Theme.Dialog"
        	表示將Activity的主題配置成對話方塊的形式
         -->
        <activity android:name=".DialogActivity" android:theme="@android:style/Theme.Dialog"/>
    </application>

</manifest>


Activity的啟動模式

AndroidManifest.xml中的<activity>標籤中可以配置android:launchMode屬性,用來控制Actvity的啟動模式

Android系統中我們建立的Acitivity是以棧的形式呈現的

1.standard(預設):每次呼叫startActivity()啟動時都會建立一個新的Activity放在棧頂

2.singleTop:啟動Activity時,指定Activity不在棧頂就建立,如在棧頂,則不再建立

3.singleTask:如果啟動的Activity不存在就建立,如果存在直接跳轉到指定的Activity所在位置(例如A在棧底,B在A上面,B中開A,那麼就將B移除,露出A)

4.singleInstance:如果啟動的Activity不存在就建立,如果存在就將指定的Activity移動到棧頂(例如A在棧底,B在A上面,B中開A,那麼就將A移到B的上面)

注意:如果使用3和4這兩種啟動模式,那麼就不能使用onActivityResult來獲取關閉的Activity的資料了。因為3和4建立的Activity都是單例的,不會被關閉。


Activity的記憶體管理

Android系統在執行多個程式時,如果系統資源不足,會強制結束一些程式。優先選擇哪個程式來結束是有優先順序的。從上倒下的順序。

空:程式中所有Activity都已銷燬

後臺:程式中有一個停止狀態的Activity

可見:程式中有一個暫停狀態的Activity

前臺:程式中正在執行一個Activity




相關文章