安卓基礎第六天(四大組件之Activity)

  • 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任務棧

  1. 程序打開時就創建了一個任務棧, 用於存儲當前程序的activity,所有的activity 屬於一個任務棧。
  2. 一個任務棧包含了一個activity 的集合, 去有序的選擇哪一個activity 和用戶進行交互:只有在任務棧棧頂的activity 纔可以跟用戶進行交互
  3. 任務棧可以移動到後臺, 並且保留了每一個activity 的狀態. 並且有序的給用戶列出它們的任務, 而且還不丟失它們狀態信息
  4. 退出應用程序時:當把所有的任務棧中所有的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
應用場景: 來電頁面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章