編輯:關於Android編程
Activity是用戶接口程序,它是Android應用程序的基本功能單元,它的主要功能是提供界面。Activity是Android的核心類,該類的全名是android.app.Activity。Activity相當於C/S程序中的窗體(From)或Web程序的頁面。每一個Activity提供一個可視化的區域。在這個區域可以放置各種Android組件,例如按鈕、圖像、文本框等。
在Activity類中有一個oncreate事件方法,一般在該方法中對Acticity進行初始化。通過setContentView方法可以設置在Activity上顯示視圖組件。
一個帶界面的Android應用程序可以由一個或者多個Activity組成。至於這些Activity如何工作,它們之間的依賴關系,則完全取決於應用程序間的業務邏輯。
在Activity建立到摧毀的過程中需要在不同的階段調用7個生命周期方法。這七個生命周期的定義如下:
protected void onCreate(Bundle savedInstanceState) {} //在這裡創建界面,做一些數據的初始化工作;
protected void onStart() {} //到這一步變成“用戶可見不可交互”的狀態;
protected void onResume() {} //變成和用戶可交互的,(在Activity棧系統通過棧的方式管理這些Activity,即當前Activity在棧的最上端,運行完彈出棧,則回到上一個Activity);
protected void onPause() {} //到這一步是可見但不可交互的,系統會停止動畫等消耗CPU的事情。從上文的描述已經知道,應該在這裡保存你的一些數據,因為這個時候你的程序的優先級降低,有可能被系統收回。在這裡保存的數據,應該在onResume裡讀出來。
protected void onStop() {} //變得不可見 ,被下一個activity覆蓋了
protected void onRestart() {}
protected void onDestroy() {} //activity被消滅
上面7個生命周期分別在4個階段按一定順序進行調用,
開始Activity:onCreate、onStart和onResume方法 Activity失去焦點:onPause和onStop方法 Activity重新獲得焦點:onRestart、onStart和onResume方法關閉Activity:當Activity被關閉時系統會依次執行3個生命周期方法—onPause、onStop和onDestory方法
Activity的生命周期如下圖所示
從圖中可以看出Activity包含兩層循環,第一層是onPause->onResume->onPause,第二層循環是onStop->onRestart->onStart->onResume->onPause->onStop。我們可以講兩層循環看成是整個Activity生命周期中的子生命周期。第一層成為焦點生命周期,第二層為可視生命周期。也就是說,第一層循環在Acitvity焦點的獲取與失去的過程中循環,這一過程中Activity是可見的。第二層循環實在Activity可見與不可見的過程中循環。
因此,Activity有如下三種生命周期:
整體生命周期:onCreate->……->onDestroy.
可視生命周期:onStart->……->onStop. 焦點生命周期:onResume->onPause.示例代碼如下:
package com.hlh.activitydemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate: ");
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: ");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
按如下步驟來操作應用程序:
(1)啟動應用程序
(2)按手機上的主頁按鈕進入主界面,然後重新進入應用程序界面
(3)關閉應用程序
按照上面步驟執行後,DDMS的Logcat打印的信息如下:
從這個例子我們可以清晰看出Activity的整個生命周期的過程。
在 Android 中,不同的 Activity 實例可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制幫助我們在 Activity 之間傳遞消息。Android 中通過 Intent 對象來表示一條消息,一個 Intent 對象不僅包含有這個消息的目的地,還可以包含消息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個 Intent 對象,消息“目的地”是必須的,而內容則是可選項。
Intent負責對操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調用者之間的解耦。
通過下面實例我們可以很好的了解Activity之間的通信,在主界面中點擊按鈕跳轉到另外一個activity,同時將數據傳遞給OtherActivity,綁定在TextView中。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt = (Button) findViewById(R.id.toOther);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, OtherActivity.class);
intent.putExtra("msg", "hello Activity");
startActivity(intent);
}
});
}
}
OtherActivity.java
public class OtherActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
TextView tv = (TextView) findViewById(R.id.tv);
Intent intent = getIntent();
//設置文本
tv.setText(intent.getStringExtra("msg"));
}
}
note:新建立了一個Actvity後,必須在AndroidManifest.xml清單文件中的標簽中注冊該actvity。
應用程序截圖:
Activity有四種加載模式(launchMode)。launchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity實例,是否重用已經存在的實例,是否和其他Activity共用一個task。簡單介紹一個task,task是一個具有棧結構的對象,一個task可以管理多個Activity,啟動一個應用,也就創建一個與之對應的task。
Activity的四種加載模式如下:
1.standard
2.singleTop
3.singleTask
4.singleInstance
我們可以在AndroidManifest.xml配置的Android:launchMode屬性為以上四種之一即可。
下面我們結合實例一一介紹這四種lanchMode:
1.standard
standard模式是默認的啟動方式,不用為配置android:launchMode屬性即可,當然也可以指定值為standard。我們創建一個Activity,命名為FirstActivity,來演示一下標准的啟動模式。FirstActivity代碼如下:
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.start);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
}
FirstActivity界面中的TextView用來顯示當前Activity實例的序列號,Button跳轉到下一個界面
連續點擊幾個Button按鈕,將會出現下面現象:
我們發現都是FirstActivity實例但是序列號不一樣,並且我們需要按兩次後退鍵才能返回到第一個 FirstActivity。每次跳轉系統都會在task中生成一個新的FirstActivity實例,並且將其放在棧頂,當我們按下back鍵時,才能看到原來的FirstActivity實例。
因此總結出standard啟動模式,不管有沒有已經存在的實例,都會生成一個新的實例。
2.singleTop
我們在上面的基礎上為指定屬性android:launchMode=”singleTop”,系統就會按照singleTop啟動模式處理跳轉行為。我們重復上面幾個動作,將會出現下面的現象:
我們看到這個跟standard的結果不同,三個序列號都一樣,也就是說使用的是同一個FirstActivity實例。如果按back鍵,程序會立即退出。跳轉時系統會先在棧結構中尋找是否有一個FirstActivity實例正位於棧頂,如果有則不再生成新的,而是直接使用。也許有人會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎麼辦,如果不是在棧頂會如何?我們接下來再通過一個示例來證實一下大家的疑問。
再新建一個Activity命名為SecondActivity,代碼如下:
public class SecondActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(this.toString());
Button button = (Button) findViewById(R.id.start);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
startActivity(intent);
}
});
}
}
然後將之前的FirstActivity跳轉代碼改為:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
演示結果如下:
我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity實例。
我們看到,當從SecondActivity跳轉到FirstActivity時,系統發現存在有FirstActivity實例,但不是位於棧頂,於是重新生成一個實例。
這就是singleTop啟動模式,如果發現有對應的Activity實例正位於棧頂,則重復利用,不再生成新的實例。
3.singleTask
在上面的基礎上我們修改FirstActivity的屬性android:launchMode=”singleTask”。演示的結果如下:
我們注意到,在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的實例,但是從FirstActivity跳轉到SecondActivity時生成了新的實例。
在這個跳轉過程中系統發現有存在的FirstActivity實例,於是不再生成新的實例,而是根據棧先進後出的原則將FirstActivity之上的Activity實例統統出棧(如SecondActivity),將FirstActivity變為棧頂對象,顯示到幕前。如果將SecondActivity也設置為singleTask模式,那麼SecondActivity實例是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從SecondActivity跳轉到FirstActivity時,SecondActivity實例都被迫出棧,下次等FirstActivity跳轉到SecondActivity時,找不到存在的SecondActivity實例,於是必須生成新的實例。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那麼SecondActivity實例就可以保證唯一。
這就是singleTask模式,如果發現有對應的Activity實例,則使此Activity實例之上的其他Activity實例統統出棧,使此Activity實例成為棧頂對象,顯示到幕前。
4.singleInstance
這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證不再有其他Activity實例進入。
我們修改FirstActivity的launchMode=”standard”,SecondActivity的launchMode=”singleInstance”,由於涉及到了多個棧結構,我們需要在每個Activity中顯示當前棧結構的id,所以我們為每個Activity添加如下代碼:
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText("current task id: " + this.getTaskId());
然後再演示一下這個流程:
我們發現這兩個Activity實例分別被放置在不同的棧結構中.可以發現從FirstActivity跳轉到SecondActivity時,重新啟用了一個新的棧結構,來放置SecondActivity實例,然後按下後退鍵,再次回到原始棧結構。
Android針對Activity的管理使用的是棧。你有可能不清楚什麼是棧,現在來解釋一下,棧是指數據項按序排列的數據結構,只能在一端(稱為棧頂(top))對數據項進行插入和刪除,一種先進後出的數據結構。而Android中是用task來存放Activity的。在第五小節簡單介紹了一下task。這裡詳細介紹一下
google官網對task的定義:
A task is a collection of activities that users interact with when
performing a certain job. The activities are arranged in a stack
(the back stack), in the order in which each activity is opened.
簡單來說task就是一組特定的activities集合,這些activities按照每一個被打開的順序放到一個stack(棧)中。Activity棧可以由一個或者多個Task組成。
啟動一個應用時,系統會為之創建一個task來放置Activity,默認情況下,一個Activity啟動另外一個Activity時,兩個Activity放入同一個task中,後者被壓入前者所在的task棧中。當用戶按back鍵,後者從棧中彈出,前者又顯示在屏幕上。重點強調的是,啟動其他應用的Activity時,兩個Activity對用戶來說好像屬於同一個應用,其實這兩個Activity都創建了自己的task棧。系統中task和task之間是相互獨立的,當我們運行應用A時,按Home鍵回到主屏,啟動另外一個應用B,這時應用A的task被轉移到後台,剛啟動的應用B的task被轉移到前台,其棧頂Activity會顯示在屏幕上;再次按Home鍵回到開始啟動的應用A時,A應用的task任務棧又被轉移到前台,這時系統仍然保留task的所有Activity實例。
CleverCode最近在做微信開發。在調試內網用手機調試微信公眾號開發的時候,發現訪問觸屏版配置host頁面非常麻煩。最好找到一個代理工具Fiddler。1 代理原理1
前面簡單地介紹了Android程序開發中AudioRecord和AudioTrack的使用,這次再結合SurfaceView實現一個Android版的手機模擬信號示波器。
本文實例講述了Android動畫之補間動畫。分享給大家供大家參考,具體如下:前面講了《Android動畫之逐幀動畫(Frame Animation)》,今天就來詳細講解一
一、概述相信大家都遇到過這種情況,就是在Android手機中的應用,往往在應用的設置裡面,都會有一個檢查更新的功能,如果應用開發商或者運營商發布了新的應用版本,點擊設置裡