- Activity 是Android 四大組件之一,它用於展示界面。
- 是一個負責與用戶交互的組件,可以通過setContentView(View)來顯示指定控件。
- Activity 之間通過Intent 進行通信。### Activity之間的跳轉
Activity清單配置
- 定義類繼承Activity
- 在AndroidManifest.xml 的節點中聲明
application中lable指程序的名字,
activity中的lable是指activity 的名字
name 屬性::包名.Activity 類名
包名如果與mainfest 的package 一致,可以用“.”代替。或者不寫
Intent-filter 子節點:
- 添加意圖過濾,可以通過隱式意圖啓動。
- 可以在桌面生成快捷方式,應用程序的入口
如果此activity還指定了以下filter那麼這個界面就會在桌面創建快捷方式
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Icon 屬性:圖標
theme 屬性:指定主題
Activity 之間的跳轉
顯式意圖跳轉
- 可以引用到那個類, 並且可以引用到那個類的字節碼時可以使用。
- 一般用於自己程序的內部。顯式跳轉不可以跳轉到其他程序的頁面中。
隱式意圖跳轉
- 可以在當前程序跳轉到另一個程序的頁面
- 隱式跳轉不需要引用到那個類,但是必須得知道那個界面的動作(action)和信息(category)。
使用Intent意圖傳遞數據
Activity 之間通過Intent 進行通信。Intent 即意圖,用於描述一個頁面的信息,同時也是一個數據的載體。
- 案例 RP計算器
public class MainActivity extends Activity {
private EditText et_name;
private RadioGroup rg_group;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = (EditText) findViewById(R.id.et_name);
rg_group = (RadioGroup) findViewById(R.id.radioGroup1);
}
// 點擊按鈕 實現計算人品 跳轉到ResultActivity頁面
public void click(View v) {
// [1]獲取用戶名
String name = et_name.getText().toString().trim();
// [2] 判斷一下name 是否爲空
if (TextUtils.isEmpty(name)) {
Toast.makeText(getApplicationContext(), "親 請輸入姓名", 1).show();
return;
}
// [3]判斷用戶選擇的性別
int radioButtonId = rg_group.getCheckedRadioButtonId();
int sex = 0;
switch (radioButtonId) {
case R.id.rb_male: // 代表選擇的是男
sex = 1;
break;
case R.id.rb_female: // 代表選擇的是女
sex = 2;
break;
case R.id.rb_other: // 代表選擇的是人妖
sex = 3;
break;
}
if(sex == 0){
Toast.makeText(getApplicationContext(), "請選擇性別", 1).show();
return;
}
//[4]跳轉到ResultActivity頁面 用顯示意圖跳轉
Intent intent = new Intent(this, ResultActiviyt.class);
//傳遞姓名
intent.putExtra("name", name);
//傳遞性別
intent.putExtra("sex", sex);
startActivity(intent);
}
}
跳轉頁
public class ResultActiviyt extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// [1]加載佈局
setContentView(R.layout.activity_result);
TextView tv_name = (TextView) findViewById(R.id.tv_name);
TextView tv_sex = (TextView) findViewById(R.id.tv_sex);
TextView tv_result = (TextView) findViewById(R.id.tv_result);
// [2]獲取mainActivity 傳遞過來的數據
Intent intent = getIntent(); // 獲取開啓此Activity的意圖對象
// [3]獲取name 和 sex 的值 小技巧 :傳遞的是什麼數據類型 這邊就按照傳遞的數據類型取
String name = intent.getStringExtra("name");
int sex = intent.getIntExtra("sex", 0);
// [4]根據name 和 sex 顯示數據
tv_name.setText(name);
byte[] bytes = null;
// [5]顯示性別
try {
switch (sex) {
case 1:
tv_sex.setText("男");
bytes = name.getBytes("gbk");
break;
case 2:
tv_sex.setText("女");
bytes = name.getBytes("utf-8");
break;
case 3:
tv_sex.setText("人妖");
bytes = name.getBytes("iso-8859-1");
break;
default:
break;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//[6]計算人品結果 市面上大多數應用採用的是隨機數
int total = 0;
for (byte b : bytes) { // 0001 1111
int number = b&0xff; // 1111 1111
total+=number;
}
// 獲取得分
int score = Math.abs(total)%100;
if (score > 90) {
tv_result.setText("您的人品非常好,您家的祖墳都冒青煙啦");
}else if (score > 80) {
tv_result.setText("您的人品還可以 ");
}else if (score > 60) {
tv_result.setText("您的人品剛及格");
}else{
tv_result.setText("您的人品太次了 您需要努力啊");
}
}
}
案例 短信發送器 (請求碼,結果碼)
- requestCode 開啓activity時設置的請求嗎
- resultCode 在目標activity中設置的結果碼
主頁面
public class MainActivity extends Activity {
private EditText et_number;
private EditText et_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到我們關心的控件
et_number = (EditText) findViewById(R.id.et_number);
et_content = (EditText) findViewById(R.id.et_content);
}
//點擊按鈕跳轉到發送短信模板頁面
public void insertsms(View v){
Intent intent = new Intent(this,SmsTemplateActivity.class);
startActivityForResult(intent, 2);
}
//點擊按鈕 跳轉到ContactActivity 頁面
public void add(View v){
Intent intent = new Intent(this,ContactActivity.class);
// startActivity(intent);
//小細節 如果點擊按鈕 開啓了另外一Activity 並且當開啓的這個Activity關閉的時候 我想要這個開啓Activity的數據 用下面這個方法開啓activity
startActivityForResult(intent, 1);
}
//當我們開啓的Activity 頁面關閉的時候 這個方法就調用
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==1) {
//代表請求ContactActivity這個頁面的數據
String phone = data.getStringExtra("phone");
et_number.setText(phone);
}else if (requestCode == 2) {
//代表請求 短信模板頁面的數據
String smsContent = data.getStringExtra("smscontent");
et_content.setText(smsContent);
}
/*
if (resultCode == 10) {
//說明數據是從 ContactActivity 返回
String phone = data.getStringExtra("phone");
et_number.setText(phone);
}else if (resultCode == 20) {
//說明數據 是從 SmsTempate 返回
String smsContent = data.getStringExtra("smscontent");
et_content.setText(smsContent);
}
*/
super.onActivityResult(requestCode, resultCode, data);
}
//點擊按鈕 發送短信
public void send(View v){
//[1]獲取發送短信的號碼 和 發送的內容
String number = et_number.getText().toString().trim();
String content = et_content.getText().toString().trim();
//[2]獲取到smsmanager的實例
SmsManager smsManager = SmsManager.getDefault();
ArrayList<String> divideMessages = smsManager.divideMessage(content);
for (String div : divideMessages) {
/**
* destinationAddress 發送給誰
* scAddress 服務中心號碼
*
* text 要發送的內容
*/
smsManager.sendTextMessage(number, null, div, null, null);
}
}
}
獲取聯繫人頁面
public class ContactActivity extends Activity {
private List<Person> lists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加載佈局
setContentView(R.layout.activity_contact);
//[1]找到控件
ListView lv = (ListView) findViewById(R.id.lv);
//[2]準備listview 要顯示的數據 模擬點假數據
lists = new ArrayList<Person>();
for (int i = 0; i < 20; i++) {
Person p = new Person();
p.setName("張三"+i);
p.setPhone("11"+i);
lists.add(p);
}
//[3]展示數據
lv.setAdapter(new MyAdapter());
//[4]給listview 設置點擊事件
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//[5]獲取我點中條目的數據 數據在哪裏面存着呢 就去哪裏取
String phone = lists.get(position).getPhone();
//[5.0]把數據返回給調用者
Intent intent = new Intent();
intent.putExtra("phone", phone);
//把結果返回給調用者
setResult(10, intent);
//[5.1]關閉當前頁面
finish();
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
private class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = View.inflate(getApplicationContext(), R.layout.contact_item, null);
}else {
view = convertView;
}
//[1]找到我們在item 中定義的控件 用來顯示 數據
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
//[2]展示數據
tv_name.setText(lists.get(position).getName());
tv_phone.setText(lists.get(position).getPhone());
return view;
}
}
}
獲取短信模板頁
public class SmsTemplateActivity extends Activity {
String objects[] = {"我在喫飯,請稍後聯繫","我在開會,請稍後聯繫","我在上課,請稍後聯繫","我在打代碼,請稍後聯繫","我在約會,請稍後聯繫"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smstemplate);
//[1]找到lv
ListView lv = (ListView) findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.smstemplate_item, objects);
//[2]顯示數據
lv.setAdapter(adapter);
//[3]設置lv 的條目的點擊事件
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//[4]取出點擊條目的數據
String smsContent = objects[position];
//[5]把smsContent 返回調用者
Intent intent = new Intent();
intent.putExtra("smscontent", smsContent);
setResult(20, intent);
//[6]調用finish
finish();
}
});
}
}
Activity生命週期
Activity 有三種狀態:
- 1、當它在屏幕前臺時,響應用戶操作的Activity, 它是激活或運行狀態
- 2、當它上面有另外一個Activity,使它失去了焦點但仍然對用戶可見時, 它處於暫停狀態。
- 3、當它完全被另一個Activity 覆蓋時則處於停止狀態。
當Activity 從一種狀態轉變到另一種狀態時,會調用以下保護方法來通知這種變化:
方法名 | 說明 |
---|---|
void onCreate() | 設置佈局以及進行初始化操作 |
void onStart() | 可見, 但不可交互 |
void onRestart() | 調用onStart() |
void onResume() | 可見, 可交互 |
void onPause() | 部分可見, 不可交互 |
void onStop() | 完全不可見 |
void onDestroy() | 銷燬 |
圖
- startActivity 開啓一個Activity 時, 生命週期的過程是:
onCreate ->onStart(可見不可交互) ->onResume(可見可交互) - 點擊back 鍵關閉一個Activity 時, 生命週期的過程是:
onPause(部分可見不可交互)->onStop(完全不可見)->onDestroy(銷燬) - 當開啓一個新的Activity(以對話框形式), 新的activity 把後面的activity 給蓋住一部分時, 後面的activity 的生命週期執行的方法是:
onPause(部分可見, 不可交互)
Activity 以對話框的形式顯示,需在activity 節點追加主題android:theme=”@android:style/Theme.Dialog” - 當把新開啓的Activity(以對話框形式)給關閉時, 後面的activity 的生命週期執行的方法是:
onResume(可見, 可交互) - 當開啓一個新的activity 把後面的activity 完全蓋住時, 生命週期的方法執行順序是:
onPause ->onStop(完全不可見) 當把新開啓的activity(完全蓋住)給關閉時, 生命週期的方法執行順序是:
onRestart ->onStart ->onResume(可見, 可交互)實際工作中常用的方法以及應用場景有:
onResume 可見, 可交互.。把動態刷新的操作啓動。
onPause 部分可見, 不可交互. 把動態刷新的一些操作, 給暫停了。
onCreate 初始化一些大量的數據。
onDestroy 把數據給釋放掉, 節省內存。
橫豎屏切換
橫豎屏切換時,默認情況下會把activity 先銷燬再創建,這個體驗是非常差的
不讓Activity 在橫豎屏切換時銷燬,只需要在清單文件聲明Activity 時配置節點的幾個屬性即可
兼容所有版本:
android:configChanges="orientation|keyboardHidden|screenSize
禁止橫豎屏:
screenOrientation=”” 指定屏幕固定方向,不會隨着屏幕旋轉而旋轉
android:screenOrientation=”portrait” 始終豎屏
android:screenOrientation=”landscape” 始終橫屏
Activity任務棧
- 程序打開時就創建了一個任務棧, 用於存儲當前程序的activity,所有的activity 屬於一個任務棧。
- 一個任務棧包含了一個activity 的集合, 去有序的選擇哪一個activity 和用戶進行交互:只有在任務棧棧頂的activity 纔可以跟用戶進行交互
- 任務棧可以移動到後臺, 並且保留了每一個activity 的狀態. 並且有序的給用戶列出它們的任務, 而且還不丟失它們狀態信息
- 退出應用程序時:當把所有的任務棧中所有的activity 清除出棧時,任務棧會被銷燬,程序退出。
重複數據太多, 會導致內存溢出的問題(OOM)
Activity啓動模式
爲了解決任務棧產生的問題,Android 爲Activity 設計了啓動模式
可以在AndroidManifest.xml 配置的android:launchMode 屬性爲以下四種之一即可。
四種launchMode:
1.standard
默認模式
2.singleTop
如果任務棧的棧頂存在這個要開啓的activity,不會重新的創建activity,而是複用已經存在的activity。保證棧頂如果存在,不會重複創建。
應用場景:瀏覽器的書籤
3.singleTask
單一任務棧,在當前任務棧裏面只能有一個實例存在,
當開啓activity的時候,就去檢查在任務棧裏面是否有實例已經存在,
如果有實例存在就複用這個已經存在的activity,
並且把這個activity上面的所有的別的activity都清空,
複用這個已經存在的activity。保證整個任務棧裏面只有一個實例存在
應用場景:瀏覽器的activity
4.singleInstance
activity會運行在自己的任務棧裏面,並且這個任務棧裏面只有一個實例存在
如果你要保證一個activity在整個手機操作系統裏面只有一個實例存在,使用singleInstance
應用場景: 來電頁面