Android编程基础---Activity


Author:ProZoom

Hobby:爱折腾、爱思考,想静静的ProZoom

Github --- 简书 --- CSDN --- 关于我


1 创建表示层(Activity)

1.1定义Activity ,继承Activity

在AndroidManifest.xml的<application>节点中声明<activity>

 <activity
     android:name="com.itheima.intent.SecondActivity"
     android:label="@string/title_activity_second" >
          //这两句可以指定手机home里所是否显示的程序图标
 </activity >

1.2显式意图创建方式

构造函数,代码少

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

类名形式,灵活,可扩展性强

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

包名类名形式,可启动其他程序中的Activity

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

1.3 创建Activity并传递数据

在意图对象中封装了一个Bundle对象,可以用来携带数据
在新Activity中可以获得意图对象以获取其中Bundle保存的数据

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

1.4 创建Activity获取返回数据

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

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

新Activity中调用setResult(int resultCode, Intent data) 设置返回数据之后,关闭Activity就会调用onActivityResult方法

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

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

@Override
/**
 * requestCode 请求码
 * resultCode 响应码
 * data     返回数据
 */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       //设置返回数据之后,关闭Activity就会调用onActivityResult方法
}

1.5 隐式意图创建Activity

显式意图是指在创建意图时指定了组件,而隐式意图则不指定组件,通过动作、类型、数据匹配对应的组件

在清单文件中定义<activity>时需要定义<intent-filter>才能被隐式意图启动

<intent-filter>中至少配置一个<action>和一个<category>,否则无法被启动

Intent对象中设置的action、category、data在<intent-filter>必须全部包含才能启动

<intent-filter>中的<action>、<category>、<data>都可以配置多个,Intent对象中不用全部匹配,每样匹配一个即可启动

如果一个意图可以匹配多个Activity,Android系统会提示选择

         <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 手动退出当前Activity

调用finish()方发,可以复写此方法,自定义按返回键所发生的事件。

2 生命周期

2.1 Acitivity三种存活状态

Active 运行:activity在最前端运行,处于屏幕前景(当前task的栈顶Activity处于Active状态),同一时刻只能有一个Activity处于Active状态。

Stopped 停止:activity不可见,完全被覆盖,但依然保持所有的状态和内存信息。

Paused 暂停:activity可见,但前端还有其他activity,处于背景画面画面状态,失去了焦点,但依然是活动状态。

2.2 Activity的生命周期可以分为三组

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

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

前台生命周期 onresume - onpause

2.3各种状态之间通过下列的方法调用转换

onCreate:创建时调用,或者程序在暂停、停止状态下被杀死之后重新打开时也会调用。在activity第一次被创建的时候调用。这里是你做所有初始化设置的地方──创建视图、设置布局、绑定数据至列表等。如果曾经有状态记录(参阅后述Saving Activity State。),则调用此方法时会传入一个包含着此activity以前状态的包对象做为参数。

onDestroy:销毁时调用,在activity销毁前调用。这是activity接收的最后一个调用。这可能发生在activity结束(调用了它的 finish() 方法)或者因为系统需要空间所以临时的销毁了此acitivity的实例时。你可以用isFinishing() 方法来区分这两种情况。

onStart:当activity正要变得为用户所见时被调用,

onStop:进入停止状态,或者销毁时会调用,当activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个activity(可能是现存的或者是新的)回到运行状态并覆盖了它。

onResume:onStart之后或者从暂停状态恢复时调用,从停止状态恢复时由于调用onStart,也会调用onResume,在activity开始与用户进行交互之前被调用。此时activity位于堆栈顶部,并接受用户输入。

onPause:进入暂停、停止状态,或者销毁时会调用,当系统将要启动另一个activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个activity必须等到此方法返回后才会继续。

onRestart:从停止状态恢复时调用,在activity执行onStop()停止后,在再次启动之前被调用。
总以onStart()继之。

Activity Life Circle

2.4 保存信息的方法

onSaveInstanceState:在Activity被动的摧毁或停止的时候调用,用于保存运行数据,可以将数据存在在Bundle中

onRestoreInstanceState:该方法在Activity被重新绘制的时候调用,例如改变屏幕方向,savedInstanceState为onSaveInstanceState保存的数据

2.5 Activity生命周期总结

1,Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume

2,Activity未被完全覆盖只是失去焦点:onPause--->onResume

3,当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变

3 启动模式

activity的任务栈的概念:

activity task stack

activity stack

back stack 后退栈

在Android系统中我们创建的Acitivity是以栈的形式呈现的

Actvity的启动模式

在AndroidManifest.xml中的<activity>标签中可以配置android:launchMode属性,用来控制Actvity的启动模式

        <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(其中前两个是一组、后两个是一组),默认为standard

standard:就是intent将发送给新的实例,所以每次跳转都会生成新的activity。

singleTop:也是发送新的实例,但不同standard的一点是,在请求的Activity正好位于栈顶时(配置成singleTop的Activity),不会构造新的实例

singleTask:和后面的singleInstance都只创建一个实例,当intent到来,需要创建设置为singleTask的Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。

singleInstance:首先说明一下task这个概念,Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么Android就创建了一个Task,然后启动这个应用的入口Activity,那在它的界面上调用其他的Activity也只是在这个task里面。那如果在多个task中共享一个Activity的话怎么办呢。举个例来说,如果开启一个导游服务类的应用程序,里面有个Activity是开启GOOGLE地图的,当按下home键退回到主菜单又启动GOOGLE地图的应用时,显示的就是刚才的地图,实际上是同一个Activity,实际上这就引入了singleInstance。singleInstance模式就是将该Activity单独放入一个栈中,这样这个栈中只有这一个Activity,不同应用的intent都由这个Activity接收和展示,这样就做到了共享。当然前提是这些应用都没有被销毁,所以刚才是按下的HOME键,如果按下了返回键,则无效

//可以有多个A
standard:每次调用startActivity()启动时都会创建一个新的Activity放在栈顶
singleTop:启动Activity时,指定Activity不在栈顶就创建,如在栈顶,则不再创建
//单例的,不能使用返回数据方法
singleTask:如果启动的Activity不存在就创建,如果存在直接跳转到指定的Activity所在位置
singleInstance:如果启动的Activity不存在就创建,如果存在就将指定的Activity移动到栈顶

6 android推出activity的方式总结

在android中使用:[activityname].this.finish(); 只是退出了activity的堆栈中,要真正的退出程序在手机cpu中的运行,当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用:

一 使用killProcess()函数,首先获取当前进程的id,然后杀死该进程:

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

 通过这种方式不能将应用程序完全杀死,并且他不会把当前应用应用的Activity的task任务栈清空

二 在activity的生命周期函数中添加如下的函数,强制关闭与该包有关联的一切执行:

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

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

  还需要在AndroidManifest.xml文件中加入如下的权限:<uses-permission android:name="android.permission.RESTART_PACKAGES" />

  此做法:只能杀死别人,不能杀死自己

三、 终止当前正在运行的Java虚拟机,导致程序终止
System.exit(0);
不会把自己的应用程序杀死

企业中做法:

创建类app 继承Application

AndroidMainfest -->name -->app //声明该类为整个应用程序全局的实例

创建整个应用程序全局的实例
App.class:
ArrayList<Activity> activities;

其他的Activity中:
public void onCreate(Bundle savedInstanceState) {
        App app = (App) getApplication();//获取应用程序全局的实例引用
        app.activities.add(this);    //把当前Activity放入集合中
}

public void onDestory(){
        App app = (App) getApplication();//获取应用程序全局的实例引用
        app.activities.remove(this); //把当前Activity从集合中移除
}

安全退出:
在菜单退出按钮的事件中定义如下代码:
App app = (App) getApplication();
List<Activity> activities = app.activities;
for(Activity act:activities){
  act.finish();//显式结束
}

2.3以后应用不能完全退出,被屏蔽了。怎样完全退出呢?

   由于android 是 基于liux 操作系统的, 所以 一般情况下 我们 使用
       android.os.Process.killProcess(android.os.Process.myPid()); 这个方法就可以杀掉进程,
    不过当 activity 多的时候,而且当我们忘记finish 其中的某几个,或者说,你对 AndroidMainfest.xml 中的 每个 Activity 中 android:launchMode , android:alwaysRetainTaskState 这些都不是很清楚时,就会出现 应用的 关闭不完全,主要原因是由于 残留的 Activity 本身是一个进程,所以系统又把这个Activity提到了最前面,就会使我们的程序没有完全关闭,

        那么 再 1.5---2.1  用了一个 方法,都可以成功的解决这个问题,那就是

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

       但是到了 2.2 的时候, 这个方法,就不奏效了, 那么我想请问 各位同仁们,有没有 什么通用的办法呢~~~~  

           这个问题,网上的童鞋,也是有非常多做法,android123 也给我们提供了,非常多的解决办法, 但是小弟不才,他们提供的方法,有些时候,不管用,所以很费脑~~~~
          现在我将我 这个方法 分享给大家, 这个方法在 1.5--2.3 的机器上都测试过,是可以完全杀死进程的

       该方法需要两个必要条件
      条件一:  一个自己管理Activity 的列表, 网上很多用 ArryList 来存储acitivity
      条件二: 需要一段,重新开启堆栈,跳转到 Home界面,并且 用liux的杀掉进程的方法

      代码如下
       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();
            //目前最为通用的 关闭进程的方法以后的版本使用
            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

一些关于 Activity 的技巧
锁定 Activity 运行时的屏幕方向
Android 内置了方向感应器的支持。在 G1 中,Android 会根据 G1 所处的方向自动在竖屏和横屏间切换。但是有时我们的应用程序仅能在横屏 / 竖屏时运行,比如某些游戏,此时我们需要锁定该 Activity 运行时的屏幕方向,<activity >节点的 android:screenOrientation属性可以完成该项任务,示例代码如下:

 <activity android:name=".EX01"
 android:label="@string/app_name" 
 android:screenOrientation="portrait">// 竖屏 , 值为 landscape 时为横屏
…………
 </activity>

全屏的 Activity

要使一个 Activity 全屏运行,可以在其 onCreate()方法中添加如下代码实现:

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

 // 去除标题栏
 
requestWindowFeature(Window.FEATURE_NO_TITLE);

在 Activity 的 Title 中加入进度条

为了更友好的用户体验,在处理一些需要花费较长时间的任务时可以使用一个进度条来提示用户“不要着急,我们正在努力的完成你交给的任务”。如下图:
在 Activity 的标题栏中显示进度条不失为一个好办法,下面是实现代码:

 // 不明确进度条
 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 
 setContentView(R.layout.main); 
 setProgressBarIndeterminateVisibility(true); 

 // 明确进度条
 requestWindowFeature(Window.FEATURE_PROGRESS); 
 setContentView(R.layout.main); 
 setProgress(5000);
 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,367评论 25 707
  • Activity 一、四种形态 运行状态: 当 Activity 处于栈的顶层,可见,并可与用户进行交互 onRe...
    任教主来也阅读 1,622评论 1 10
  • 1.什么是Activity?问的不太多,说点有深度的 四大组件之一,一般的,一个用户交互界面对应一个activit...
    JoonyLee阅读 5,724评论 2 51
  • 又是一年中秋节,我已经记不清哪一年是与家人在一起,共同庆祝这一象征团圆的节日了。从2008年开始,中秋节成了法定假...
    Megan颀阅读 220评论 0 1
  • 人们往往秉持“劝和不劝分” 的原则,大抵是因为“劝和不和好心在,劝分不分恶名留”吧。敏敏懂这个理,却终究是做不来这...
    邮晓阅读 817评论 0 0