Activity初學乍練


本節引言:

本節開始講解Android的四大組件之一的Activity(活動),先來看下官方對於Activity的介紹: PS:官網文件:Activity

介紹如下:#大概意思:

Activity是一個應用程式的組件,他在螢幕上提供了一個區域,允許用戶在上面做一些互動性的操作, 例如打電話,照相,發送郵件,或顯示一張地圖! Activity可以理解成一個繪製使用者介面的窗口, 而這個視窗可以填滿整個螢幕,也可能比螢幕小或浮動在其他視窗的上方!

從上面這段話,我們可以得到以下資訊:

1. Activity用來顯示使用者介面,使用者透過Activity互動完成相關操作2. 一個App允許有多個Activity

好了,大概的引言就介紹到這裡,想深入了解可以繼續看API,開始本節內容~


  1. Activity的概念與Activity的生命週期圖1.jpg

注意事項:

1. onPause()和onStop()被呼叫的前提是: 打開了一個新的Activity!而前者是舊Activity仍可見的狀態;後者是舊Activity已經不可見!
2. 另外,親測:AlertDialog和PopWindow是不會觸發上述兩個回呼方法的~


2.Activity/ActionBarActivity/AppCompatActivity的區別:

在開始講解創建Activity之前要說下這三個的一個差異: Activity就不用說啦,後面這兩個都是為了低版本兼容而提出的提出來的,他們都在v7包下, ActionBarActivity已被放棄,從名字就知道,ActionBar~,而在5.0後,被Google棄用了,現在用 ToolBar...而我們現在在Android Studio建立一個Activity預設繼承的會是:AppCompatActivity! 當然你也可以只寫Activity,不過AppCompatActivity為我們提供了一些新的東西而已! 兩個選一個,Just you like~


3.Activity的建立流程

2.png

PS:

好了,上面也說過,可以繼承Activity和AppCompatActivity,只不過後者提供了一些新的東西而已! 另外,切記,Android中的四大元件,只要你定義了,不管用沒用,都要在AndroidManifest.xml對 這個元件進行聲明,不然運行時程式會直接退出,報ClassNotFindException...


4.onCreate()一個參數和兩個參數的區別:

#相信用as的朋友在重寫Act的onCreate()方法時會發現,這玩意有兩個參數:

3.png

可是正常的才只有一個參數啊:

4.png

恩呢,這就是5.0給我們提供的新的方法,要用它,先在設定檔中為我們的Activity設定一個屬性:

android:persistableMode="persistAcrossReboots"

#然後我們的Activity就擁有了持久化的能力了,一般我們會搭配另外兩個方法來使用:

public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
public vo Bundle savedInstanceState, PersistableBundle persistentState)
#

相信有些朋友對這兩個方法名稱不陌生吧,前一個方法會在下述情形中被呼叫:

  1. 點擊home鍵回到主頁或長按後選擇執行其他程式
  2. 按下電源鍵關閉螢幕
  3. 啟動新的Activity
  4. #橫豎螢幕切換時,一定會執行,因為橫豎螢幕切換的時候會先銷毀Act ,然後再重新創建 重要原則:當系統"未經你許可"時銷毀了你的activity,則onSaveInstanceState會被系統調用, 這是系統的責任,因為它必須提供一個機會讓你保存你的資料(你可以保存或不保存)。

而後者方法,和onCreate同樣可以從取出前者儲存的資料: 一般是在onStart()和onResume()之間執行! 之所以有兩個可以取得到保存資料的方法,是為了避免Act跳轉而沒有關閉, 然後不走onCreate()方法,而你又想取出保存資料~

說回來:說回這個Activity擁有了持久化的能力,增加的這個PersistableBundle參數令這些方法 擁有了系統關機後重啟的資料復原能力! !而且不影響我們其他的序列化操作,臥槽, 具體怎麼實現的,暫時還不了解,可能是另外弄了個文件保存吧~!後面知道原理的話會告知下大家! 另外,API版本要>=21,就是要5.0以上的版本才有效~


4.啟動一個Activity的幾種方式

#在Android中我們可以透過下面兩種方式來啟動一個新的Activity,注意這裡是怎麼啟動,而非 啟動模式! !分為顯示啟動和隱式啟動!

1. 明確啟動:透過套件名稱來啟動,寫入方法如下:

①最常見的:

startActivity(new Intent(當前Act.this,要啟動的Act.class));
②透過Intent的ComponentName:
ComponentName cn = new ComponentName("目前Act的全限定類別名稱","啟動Act的全限定類別名稱") ;
Intent intent = new Intent( ;##intent .setComponent(cn) ;
startActivity(intent) ;
初始化Intent時指定包名:
Intent intent = new Intent(" android.intent.action.MAIN");
intent.setClassName("目前Act的全限定類別名稱","啟動Act的全限定類別名稱");
startActivity(intent);

2.隱含啟動:透過Intent-filter的Action,Category或data來實現 這個是透過Intent的 intent-filter**來實現的,這個Intent那章會詳細解說! 這裡知道大概就可以了!

5.png

3. 另外還有一個直接透過套件名稱啟動apk的:

Intent intent = getPackageManager() .getLaunchIntentForPackage
("apk第一個啟動的Activity的全限定類別名稱") ;
if(intent != null) startActivity(intent) ;
#

5.橫豎螢幕切換與狀態保存的問題

前面也說到了App橫豎屏切換的時候會銷毀當前的Activity然後重新創建一個,你可以自行在生命週期 的每個方法都加入列印Log的語句,來進行判斷,又或者設一個按鈕一個TextView點擊按鈕後,修改TextView 文本,然後橫豎屏切換,會神奇的發現TextView文本變回之前的內容了! 橫豎螢幕切換時Act走下述生命週期:
onPause-> onStop-> onDestory-> onCreate->onStart->onResume
#關於橫豎螢幕切換可能遇到下述問題:


1.先說如何禁止螢幕橫向螢幕自動切換吧,很簡單,在AndroidManifest.xml中為Act新增一個屬性:android:screenOrientation, 有下述可選值:

  • unspecified:預設值由系統來判斷顯示方向.判定的策略是和裝置相關的,所以不同的裝置會有不同的顯示方向。
  • landscape:橫螢幕顯示(寬比高要長)
  • #portrait:垂直螢幕顯示(高比寬要長)
  • user:使用者目前首選的方向
  • behind:和該Activity下面的那個Activity的方向一致(在Activity堆疊中的)
  • sensor:有物理的感應器來決定。若使用者旋轉裝置這畫面會橫豎螢幕切換。
  • nosensor:忽略實體感應器,這樣就不會隨著使用者旋轉裝置而變更了("unspecified"設定除外)。

2.橫豎屏時想載入不同的佈局

1)準備兩組不同的佈局,Android會自行依照橫豎屏載入不同佈局: 建立兩個佈局資料夾:layout-land橫屏,layout-port垂直螢幕 然後把這兩套佈局檔案丟這兩個資料夾裡,檔案名稱一樣,Android就會自行判斷,然後載入對應佈局了!

2 )自己在程式碼中進行判斷,自己想載入什麼就載入什麼:

我們一般是在onCreate()方法中載入佈局檔的,我們可以在這裡對橫豎屏的狀態做下判斷,關鍵程式碼如下:

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){  
  );
}  

else if (this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {  
  }垂直屏風View(R.layout.{  
  

3. 如何讓模擬器橫豎螢幕切換

如果你的模擬器是GM的話。直接按下模擬器上的切換按鈕即可,原生模擬器可按ctrl + f11/f12切換!


4. 狀態保存問題:

這個上面也說過了,透過一個Bundle savedInstanceState參數即可完成! 三個核心方法:


onCreate(Bundle savedInstanceState);
onSaveInstanceState(Bundle outState);
onRestoreInstanceState(Bundle savedInstanceState);

你只重寫onSaveInstanceState()方法,往這個bundle中寫入數據,例如:

outState.putInt("num",1);

#這樣,然後你在onCreate或onRestoreInstanceState中就可以拿出裡面儲存的數據,不過拿之前要判斷下是否為null哦!

savedInstanceState.getInt("num");

然後想幹嘛就幹嘛~


6.系統給我們提供的常見的Activity

好的,最後給大家附上一些系統給我們提供的一些常見的Activtiy吧!

//1.撥打電話
// 給行動客服10086撥打電話
Uri uri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent .ACTION_DIAL, uri);
startActivity(intent);

//2.發送簡訊
// 給10086發送內容為「Hello」的簡訊
Uri uri = Uri.parse ("smsto:10086");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.putExtra("sms_body", "Hello");
startActivity(intent);

//3.寄送彩信(相當於寄送附附件的簡訊)
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "Hello");
Uri uri = Uri.parse("content://media/external/images/media/23");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/ png");
startActivity(intent);

//4.開啟瀏覽器:
// 開啟Google首頁
Uri uri = Uri.parse("http://www .baidu.com");
Intent intent  = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

//5.發送電子郵件:(閹割了Google服務的沒戲!!!!)
// 給someone@domain.com發郵件
Uri uri = Uri.parse("mailto:someone@domain.com");
Intent intent = new Intent( Intent.ACTION_SENDTO, uri);
startActivity(intent);
// 寄給someone@domain.com寄電子郵件內容為「Hello」的郵件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "someone@domain.com");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello" );
intent.setType("text/plain");
startActivity(intent);
// 寄email
Intent intent=new Intent(Intent.ACTION_SEND);
String[] tos = {"1@abc.com", "2@abc.com"}; // 收件人
String[] ccs = {"3@abc.com", "4@abc .com"}; // 抄送
String[] bccs = {"5@abc.com", "6@abc.com"}; // 密送
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_BCC, bccs);
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");##ject");##ject");##ject");##ject");##ject");##ject");##ject");##ject");##ject");## intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("message/rfc822");
startActivity(intent);

//6.顯示地圖:
// 打開Google地圖中國北京位置(北緯39.9,東經116.3)
Uri uri = Uri.parse("geo:39.9,116.3");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

//7.路徑規劃
// 路徑規劃:從北京某地(北緯39.9,東經116.3)到上海某地(北緯31.2,東經121.4)
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=39.9 116.3&daddr=31.2"121. ##Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

//8.多媒體播放:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/foo.mp3");
intent.setDataAndType(uri, "audio/mp3");
startActivity(intent);

//取得SD卡下所有音訊檔案,然後播放第一首=-= 
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");#ent#Intent intint = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

//9.開啟相機拍照:
// 開啟拍照程式
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE); 
startActivityForResult(intent, 0);
// 取出照片資料
Bundle extras = intent.getExtras(); map##Bitmap bitmap = intent.getExtras(); map##Bitmap]bitmap ");

//另一種:
//呼叫系統相機應用程序,並儲存拍攝的照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbute(Environment
.getExternalStorageDirectory()。 .jpg")));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);

//10.取得並剪下圖片
// 取得並剪下圖片
Intent intent = new Intent (Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra("crop", "true"); // 開啟剪下
intent.putExtra("aspectX ", 1); // 剪切的寬高比為1:2
intent.putExtra("aspectY", 2);
intent.putExtra("outputX", 20); // 保存圖片的寬與高
intent.putExtra("outputY", 40); 
intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp"))); // 保存路徑
intent.putExtra("outputFormat", "JPEG");// 返回格式
startActivityForResult(intent, 0);
// 剪切特定圖片
Intent intent ==new Intent(" com.android.camera.action.CROP"); 
intent.setClassName("com.android.camera", "com.android.camera.CropImage"); 
intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp")))); 
intent.putExtra("outputX", 1); // 剪下的寬高比為1:2
intent.putExtra("outputY", 2);
intent.putExtra("aspectX", 20); // 保存圖片的寬度和高度
intent.putExtra("aspectY", 40);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true); 
intent.putExtra("output", Uri.parse("file:///mnt/sdcard/temp")); 
startActivityForResult(intent, 0);

/ /11.打開Google Market 
// 打開Google Market直接進入程式的詳細頁面
Uri uri = Uri.parse("market://details?id=" + "com.demo.app") ;
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

//12.進入手機設定介面:
// 進入無線網路設定介面(其它可以舉一反三)  
Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);  
startActivityForResult(intent,#10);#o#/1##startActivityForResult(intent,#10);#o#/133. installUri = Uri.fromParts("package", "xxx", null);   
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, = Uri.fromParts("package", strPackageName, null);      
Intent it = new Intent(Intent.ACTION_DELETE,  );#15% :
Intent it = new Intent(Intent.ACTION_SEND);      
it.putExtra(Intent.EXTRA_SUBJECT, "The email /sdcard/eoe.mp3");      
sendIntent.setType("audio/mp3");      
startActivity(Intent.createChooser(it, "Choose 
startActivity(Intent.createChooser(it, "Choose 
startActivity(Intent.createChooser(it, "Choose 
#Client)); 16.進入聯絡人頁面:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);

//17.查看指定聯絡人:
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id聯絡人ID
Intent intent = new Intent ();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);


本節小結:

好吧,寫著寫著就不像入門教程了,哈哈,不過學多點沒事的,本節初窺門徑就到這裡吧~下節我們會繼續來研究這個Activity,例如資料傳遞,啟動模式等~敬請期待~