Android編程基礎(chǔ)---Activity


Author:ProZoom

Hobby:愛折騰、愛思考,想靜靜的ProZoom

Github --- 簡書 --- CSDN --- 關(guān)于我


1 創(chuàng)建表示層(Activity)

1.1定義Activity ,繼承Activity

在AndroidManifest.xml的<application>節(jié)點(diǎn)中聲明<activity>

 <activity
     android:name="com.itheima.intent.SecondActivity"
     android:label="@string/title_activity_second" >
          //這兩句可以指定手機(jī)home里所是否顯示的程序圖標(biāo)
 </activity >

1.2顯式意圖創(chuàng)建方式

構(gòu)造函數(shù),代碼少

startActivity(new Intent( this,SecondActivity.class));

類名形式,靈活,可擴(kuò)展性強(qiáng)

intent.setClassName(this, "cn.itcast.activity.NewActivity");

包名類名形式,可啟動(dòng)其他程序中的Activity

intent.setClassName("cn.itcast.downloader", "cn.itcast.downloader.MainActivity");

1.3 創(chuàng)建Activity并傳遞數(shù)據(jù)

在意圖對(duì)象中封裝了一個(gè)Bundle對(duì)象,可以用來攜帶數(shù)據(jù)
在新Activity中可以獲得意圖對(duì)象以獲取其中Bundle保存的數(shù)據(jù)

Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString("key", "value");
intent.putExtras(extras);
startActivity(intent);

1.4 創(chuàng)建Activity獲取返回?cái)?shù)據(jù)

使用startActivityForResult(Intent intent, int requestCode) 方法打開Activity

重寫onActivityResult(int requestCode, int resultCode, Intent data) 方法

新Activity中調(diào)用setResult(int resultCode, Intent data) 設(shè)置返回?cái)?shù)據(jù)之后,關(guān)閉Activity就會(huì)調(diào)用onActivityResult方法

Intent intent = new Intent();
intent.putExtra("key", "value");
intent.setClassName(this, "cn.itcast.activity.NewActivity" );
startActivityForResult(intent,100);

------------------------------------------------

@Override
/**
 * requestCode 請(qǐng)求碼
 * resultCode 響應(yīng)碼
 * data     返回?cái)?shù)據(jù)
 */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       //設(shè)置返回?cái)?shù)據(jù)之后,關(guān)閉Activity就會(huì)調(diào)用onActivityResult方法
}

1.5 隱式意圖創(chuàng)建Activity

顯式意圖是指在創(chuàng)建意圖時(shí)指定了組件,而隱式意圖則不指定組件,通過動(dòng)作、類型、數(shù)據(jù)匹配對(duì)應(yīng)的組件

在清單文件中定義<activity>時(shí)需要定義<intent-filter>才能被隱式意圖啟動(dòng)

<intent-filter>中至少配置一個(gè)<action>和一個(gè)<category>,否則無法被啟動(dòng)

Intent對(duì)象中設(shè)置的action、category、data在<intent-filter>必須全部包含才能啟動(dòng)

<intent-filter>中的<action>、<category>、<data>都可以配置多個(gè),Intent對(duì)象中不用全部匹配,每樣匹配一個(gè)即可啟動(dòng)

如果一個(gè)意圖可以匹配多個(gè)Activity,Android系統(tǒng)會(huì)提示選擇

         <activity
            android:name="com.itheima.intent.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>

                  Intent intent = new Intent(this,SecondActivity.class);
                  intent.setAction( Intent.ACTION_APP_ERROR);
                  startActivity(intent);

1.6 手動(dòng)退出當(dāng)前Activity

調(diào)用finish()方發(fā),可以復(fù)寫此方法,自定義按返回鍵所發(fā)生的事件。

2 生命周期

2.1 Acitivity三種存活狀態(tài)

Active 運(yùn)行:activity在最前端運(yùn)行,處于屏幕前景(當(dāng)前task的棧頂Activity處于Active狀態(tài)),同一時(shí)刻只能有一個(gè)Activity處于Active狀態(tài)。

Stopped 停止:activity不可見,完全被覆蓋,但依然保持所有的狀態(tài)和內(nèi)存信息。

Paused 暫停:activity可見,但前端還有其他activity,處于背景畫面畫面狀態(tài),失去了焦點(diǎn),但依然是活動(dòng)狀態(tài)。

2.2 Activity的生命周期可以分為三組

完整的生命周期 oncreate - onstart - onresume - onpause - onstop - ondestroy

可視生命周期 onstart - onresume - onpause - onstop - onstart - onresume

前臺(tái)生命周期 onresume - onpause

2.3各種狀態(tài)之間通過下列的方法調(diào)用轉(zhuǎn)換

onCreate:創(chuàng)建時(shí)調(diào)用,或者程序在暫停、停止?fàn)顟B(tài)下被殺死之后重新打開時(shí)也會(huì)調(diào)用。在activity第一次被創(chuàng)建的時(shí)候調(diào)用。這里是你做所有初始化設(shè)置的地方──創(chuàng)建視圖、設(shè)置布局、綁定數(shù)據(jù)至列表等。如果曾經(jīng)有狀態(tài)記錄(參閱后述Saving Activity State。),則調(diào)用此方法時(shí)會(huì)傳入一個(gè)包含著此activity以前狀態(tài)的包對(duì)象做為參數(shù)。

onDestroy:銷毀時(shí)調(diào)用,在activity銷毀前調(diào)用。這是activity接收的最后一個(gè)調(diào)用。這可能發(fā)生在activity結(jié)束(調(diào)用了它的 finish() 方法)或者因?yàn)橄到y(tǒng)需要空間所以臨時(shí)的銷毀了此acitivity的實(shí)例時(shí)。你可以用isFinishing() 方法來區(qū)分這兩種情況。

onStart:當(dāng)activity正要變得為用戶所見時(shí)被調(diào)用,

onStop:進(jìn)入停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用,當(dāng)activity不再為用戶可見時(shí)調(diào)用此方法。這可能發(fā)生在它被銷毀或者另一個(gè)activity(可能是現(xiàn)存的或者是新的)回到運(yùn)行狀態(tài)并覆蓋了它。

onResume:onStart之后或者從暫停狀態(tài)恢復(fù)時(shí)調(diào)用,從停止?fàn)顟B(tài)恢復(fù)時(shí)由于調(diào)用onStart,也會(huì)調(diào)用onResume,在activity開始與用戶進(jìn)行交互之前被調(diào)用。此時(shí)activity位于堆棧頂部,并接受用戶輸入。

onPause:進(jìn)入暫停、停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用,當(dāng)系統(tǒng)將要啟動(dòng)另一個(gè)activity時(shí)調(diào)用。此方法主要用來將未保存的變化進(jìn)行持久化,停止類似動(dòng)畫這樣耗費(fèi)CPU的動(dòng)作等。這一切動(dòng)作應(yīng)該在短時(shí)間內(nèi)完成,因?yàn)橄乱粋€(gè)activity必須等到此方法返回后才會(huì)繼續(xù)。

onRestart:從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用,在activity執(zhí)行onStop()停止后,在再次啟動(dòng)之前被調(diào)用。
總以onStart()繼之。

Activity Life Circle

2.4 保存信息的方法

onSaveInstanceState:在Activity被動(dòng)的摧毀或停止的時(shí)候調(diào)用,用于保存運(yùn)行數(shù)據(jù),可以將數(shù)據(jù)存在在Bundle中

onRestoreInstanceState:該方法在Activity被重新繪制的時(shí)候調(diào)用,例如改變屏幕方向,savedInstanceState為onSaveInstanceState保存的數(shù)據(jù)

2.5 Activity生命周期總結(jié)

1,Activity運(yùn)行時(shí)按下HOME鍵(跟被完全覆蓋是一樣的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume

2,Activity未被完全覆蓋只是失去焦點(diǎn):onPause--->onResume

3,當(dāng)前Activity產(chǎn)生事件彈出Toast和AlertDialog的時(shí)候Activity的生命周期不會(huì)有改變

3 啟動(dòng)模式

activity的任務(wù)棧的概念:

activity task stack

activity stack

back stack 后退棧

在Android系統(tǒng)中我們創(chuàng)建的Acitivity是以棧的形式呈現(xiàn)的

Actvity的啟動(dòng)模式

在AndroidManifest.xml中的<activity>標(biāo)簽中可以配置android:launchMode屬性,用來控制Actvity的啟動(dòng)模式

        <activity
            android:launchMode="singleInstance"
            android:name="com.itheima.mode.A_Activity"
            android:label="14.A_Activity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
        <activity
            android:launchMode="singleInstance"
            android:name="com.itheima.mode.B_Activity"
            android:label="14.B_Activity" >
        </activity>

Activity有四種加載模式:

standard、singleTop、singleTask、singleInstance(其中前兩個(gè)是一組、后兩個(gè)是一組),默認(rèn)為standard

standard:就是intent將發(fā)送給新的實(shí)例,所以每次跳轉(zhuǎn)都會(huì)生成新的activity。

singleTop:也是發(fā)送新的實(shí)例,但不同standard的一點(diǎn)是,在請(qǐng)求的Activity正好位于棧頂時(shí)(配置成singleTop的Activity),不會(huì)構(gòu)造新的實(shí)例

singleTask:和后面的singleInstance都只創(chuàng)建一個(gè)實(shí)例,當(dāng)intent到來,需要?jiǎng)?chuàng)建設(shè)置為singleTask的Activity的時(shí)候,系統(tǒng)會(huì)檢查棧里面是否已經(jīng)有該Activity的實(shí)例。如果有直接將intent發(fā)送給它。

singleInstance:首先說明一下task這個(gè)概念,Task可以認(rèn)為是一個(gè)棧,可放入多個(gè)Activity。比如啟動(dòng)一個(gè)應(yīng)用,那么Android就創(chuàng)建了一個(gè)Task,然后啟動(dòng)這個(gè)應(yīng)用的入口Activity,那在它的界面上調(diào)用其他的Activity也只是在這個(gè)task里面。那如果在多個(gè)task中共享一個(gè)Activity的話怎么辦呢。舉個(gè)例來說,如果開啟一個(gè)導(dǎo)游服務(wù)類的應(yīng)用程序,里面有個(gè)Activity是開啟GOOGLE地圖的,當(dāng)按下home鍵退回到主菜單又啟動(dòng)GOOGLE地圖的應(yīng)用時(shí),顯示的就是剛才的地圖,實(shí)際上是同一個(gè)Activity,實(shí)際上這就引入了singleInstance。singleInstance模式就是將該Activity單獨(dú)放入一個(gè)棧中,這樣這個(gè)棧中只有這一個(gè)Activity,不同應(yīng)用的intent都由這個(gè)Activity接收和展示,這樣就做到了共享。當(dāng)然前提是這些應(yīng)用都沒有被銷毀,所以剛才是按下的HOME鍵,如果按下了返回鍵,則無效

//可以有多個(gè)A
standard:每次調(diào)用startActivity()啟動(dòng)時(shí)都會(huì)創(chuàng)建一個(gè)新的Activity放在棧頂
singleTop:啟動(dòng)Activity時(shí),指定Activity不在棧頂就創(chuàng)建,如在棧頂,則不再創(chuàng)建
//單例的,不能使用返回?cái)?shù)據(jù)方法
singleTask:如果啟動(dòng)的Activity不存在就創(chuàng)建,如果存在直接跳轉(zhuǎn)到指定的Activity所在位置
singleInstance:如果啟動(dòng)的Activity不存在就創(chuàng)建,如果存在就將指定的Activity移動(dòng)到棧頂

6 android推出activity的方式總結(jié)

在android中使用:[activityname].this.finish(); 只是退出了activity的堆棧中,要真正的退出程序在手機(jī)cpu中的運(yùn)行,當(dāng)應(yīng)用不再使用時(shí),通常需要關(guān)閉應(yīng)用,可以使用以下三種方法關(guān)閉android應(yīng)用:

一 使用killProcess()函數(shù),首先獲取當(dāng)前進(jìn)程的id,然后殺死該進(jìn)程:

android.os.Process.killProcess(android.os.Process.myPid());

 通過這種方式不能將應(yīng)用程序完全殺死,并且他不會(huì)把當(dāng)前應(yīng)用應(yīng)用的Activity的task任務(wù)棧清空

二 在activity的生命周期函數(shù)中添加如下的函數(shù),強(qiáng)制關(guān)閉與該包有關(guān)聯(lián)的一切執(zhí)行:

   ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);  

  am.restartPackage("packagename"); 
 或殺死 am.killBackgroundProcesses(info.getPackname());

  還需要在AndroidManifest.xml文件中加入如下的權(quán)限:<uses-permission android:name="android.permission.RESTART_PACKAGES" />

  此做法:只能殺死別人,不能殺死自己

三、 終止當(dāng)前正在運(yùn)行的Java虛擬機(jī),導(dǎo)致程序終止
System.exit(0);
不會(huì)把自己的應(yīng)用程序殺死

企業(yè)中做法:

創(chuàng)建類app 繼承Application

AndroidMainfest -->name -->app //聲明該類為整個(gè)應(yīng)用程序全局的實(shí)例

創(chuàng)建整個(gè)應(yīng)用程序全局的實(shí)例
App.class:
ArrayList<Activity> activities;

其他的Activity中:
public void onCreate(Bundle savedInstanceState) {
        App app = (App) getApplication();//獲取應(yīng)用程序全局的實(shí)例引用
        app.activities.add(this);    //把當(dāng)前Activity放入集合中
}

public void onDestory(){
        App app = (App) getApplication();//獲取應(yīng)用程序全局的實(shí)例引用
        app.activities.remove(this); //把當(dāng)前Activity從集合中移除
}

安全退出:
在菜單退出按鈕的事件中定義如下代碼:
App app = (App) getApplication();
List<Activity> activities = app.activities;
for(Activity act:activities){
  act.finish();//顯式結(jié)束
}

2.3以后應(yīng)用不能完全退出,被屏蔽了。怎樣完全退出呢?

   由于android 是 基于liux 操作系統(tǒng)的, 所以 一般情況下 我們 使用
       android.os.Process.killProcess(android.os.Process.myPid()); 這個(gè)方法就可以殺掉進(jìn)程,
    不過當(dāng) activity 多的時(shí)候,而且當(dāng)我們忘記finish 其中的某幾個(gè),或者說,你對(duì) AndroidMainfest.xml 中的 每個(gè) Activity 中 android:launchMode , android:alwaysRetainTaskState 這些都不是很清楚時(shí),就會(huì)出現(xiàn) 應(yīng)用的 關(guān)閉不完全,主要原因是由于 殘留的 Activity 本身是一個(gè)進(jìn)程,所以系統(tǒng)又把這個(gè)Activity提到了最前面,就會(huì)使我們的程序沒有完全關(guān)閉,

        那么 再 1.5---2.1  用了一個(gè) 方法,都可以成功的解決這個(gè)問題,那就是

             final ActivityManager am = (ActivityManager) ACTIVITY
//                                .getSystemService(Context.ACTIVITY_SERVICE);
//                am.restartPackage(ACTIVITY.getPackageName());

       但是到了 2.2 的時(shí)候, 這個(gè)方法,就不奏效了, 那么我想請(qǐng)問 各位同仁們,有沒有 什么通用的辦法呢~~~~  

           這個(gè)問題,網(wǎng)上的童鞋,也是有非常多做法,android123 也給我們提供了,非常多的解決辦法, 但是小弟不才,他們提供的方法,有些時(shí)候,不管用,所以很費(fèi)腦~~~~
          現(xiàn)在我將我 這個(gè)方法 分享給大家, 這個(gè)方法在 1.5--2.3 的機(jī)器上都測(cè)試過,是可以完全殺死進(jìn)程的

       該方法需要兩個(gè)必要條件
      條件一:  一個(gè)自己管理Activity 的列表, 網(wǎng)上很多用 ArryList 來存儲(chǔ)acitivity
      條件二: 需要一段,重新開啟堆棧,跳轉(zhuǎn)到 Home界面,并且 用liux的殺掉進(jìn)程的方法

      代碼如下
       protected void quit()
      {
             int size = activityManager.activityStackCount();
            for(int i =size-1 ; i > 0 ;i--)
              {
                Activity activity =  activityManager.allTaskActivity().get(i);
                 activityManager.popActivity(activity);
              }
              activityManager = null;
             getActivity().finish();
            //目前最為通用的 關(guān)閉進(jìn)程的方法以后的版本使用
            Intent startMain = new Intent(Intent.ACTION_MAIN);
            startMain.addCategory(Intent.CATEGORY_HOME);
            startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(startMain);
           android.os.Process.killProcess(android.os.Process.myPid());
     } 
     

7 any tips

一些關(guān)于 Activity 的技巧
鎖定 Activity 運(yùn)行時(shí)的屏幕方向
Android 內(nèi)置了方向感應(yīng)器的支持。在 G1 中,Android 會(huì)根據(jù) G1 所處的方向自動(dòng)在豎屏和橫屏間切換。但是有時(shí)我們的應(yīng)用程序僅能在橫屏 / 豎屏?xí)r運(yùn)行,比如某些游戲,此時(shí)我們需要鎖定該 Activity 運(yùn)行時(shí)的屏幕方向,<activity >節(jié)點(diǎn)的 android:screenOrientation屬性可以完成該項(xiàng)任務(wù),示例代碼如下:

 <activity android:name=".EX01"
 android:label="@string/app_name" 
 android:screenOrientation="portrait">// 豎屏 , 值為 landscape 時(shí)為橫屏
…………
 </activity>

全屏的 Activity

要使一個(gè) Activity 全屏運(yùn)行,可以在其 onCreate()方法中添加如下代碼實(shí)現(xiàn):

 // 設(shè)置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); 

 // 去除標(biāo)題欄
 
requestWindowFeature(Window.FEATURE_NO_TITLE);

在 Activity 的 Title 中加入進(jìn)度條

為了更友好的用戶體驗(yàn),在處理一些需要花費(fèi)較長時(shí)間的任務(wù)時(shí)可以使用一個(gè)進(jìn)度條來提示用戶“不要著急,我們正在努力的完成你交給的任務(wù)”。如下圖:
在 Activity 的標(biāo)題欄中顯示進(jìn)度條不失為一個(gè)好辦法,下面是實(shí)現(xiàn)代碼:

 // 不明確進(jìn)度條
 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 
 setContentView(R.layout.main); 
 setProgressBarIndeterminateVisibility(true); 

 // 明確進(jìn)度條
 requestWindowFeature(Window.FEATURE_PROGRESS); 
 setContentView(R.layout.main); 
 setProgress(5000);
 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,001評(píng)論 25 709
  • Activity 一、四種形態(tài) 運(yùn)行狀態(tài): 當(dāng) Activity 處于棧的頂層,可見,并可與用戶進(jìn)行交互 onRe...
    任教主來也閱讀 1,881評(píng)論 1 10
  • 1.什么是Activity?問的不太多,說點(diǎn)有深度的 四大組件之一,一般的,一個(gè)用戶交互界面對(duì)應(yīng)一個(gè)activit...
    JoonyLee閱讀 5,858評(píng)論 2 51
  • 又是一年中秋節(jié),我已經(jīng)記不清哪一年是與家人在一起,共同慶祝這一象征團(tuán)圓的節(jié)日了。從2008年開始,中秋節(jié)成了法定假...
    Megan頎閱讀 293評(píng)論 0 1
  • 人們往往秉持“勸和不勸分” 的原則,大抵是因?yàn)椤皠窈筒缓秃眯脑?,勸分不分惡名留”吧。敏敏懂這個(gè)理,卻終究是做不來這...
    郵曉閱讀 894評(píng)論 0 0

友情鏈接更多精彩內(nèi)容