Activity

概念
启动模式
声明周期
启动过程
加载window

是什么:

是用来处理用户触摸滑动、输入等交互的页面承载者,显示Android提供的一些输入框、按钮等控件的一个类。activity所有的方法(生命周期、view初始化)等都是在主线程的。

如何使用:

  1. 新建一个类 FirstActivity extends Activity(Activity是最基础的,他还有很多子类,比如AppCompatActivity,还可以直接使用Android studio,右键file-->new-->activity-->empty Activity创建,这样studio可以自动为你生成第2步的声明)
  2. 在AndroidManifest.xml里<Application>标签内声明一个<activity android:name= "com.package.name.FirstActivity"/>
  3. 在另一个Activity里面调用这个方法:startActivity(context,FirstActivity.class);/startActivityForResult();

4.如果是应用一启动就要展示的页面就要这么声明

<Application>
  <activity android:name= "com.package.name.FirstActivity">
      <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
  </activity>
</Application>

概念

生命周期
生命周期是指启动一个activity,Android系统要走很多步骤,每个步骤对应不同的状态,并且提供了不同状态下可以重写的方法,例如onCreate()就是在系统经过反射拿到我们activity的对象时,有个类Instrumentation.callActivityOnCreate()这个方法里,调用了activity.onCreate(),所以我们重写的方法才会被回调。那他们对应的方法名和状态分别是:
onCreate()--> 创建,是生命周期的第一个方法,主要做的就是初始化布局、数据
onRestart()--> 被重新启动,就是从不可见到可见的过程会调用
onStart()--> 已经启动,但还不可见,不能和用户交互
onResume()--> 已经可见可交互
onPause()--> 正在停止,可以做一些数据缓存,停止动画之类的,如果要做销毁,不要做太耗时的(影响下一个activity的启动)
onStop()--> 停止状态,可以做一些不是很耗时的销毁动作
onDestory()--> 被销毁,可以做一些回收和最终的资源释放

  • onPause()是另一个activity到了前台会走的方法
  • onRestart()是在这个Activity A 走过onStop()之后,又返回了到了A才会走
  • onStop()是Activity不可见的时候就会走
  • onActivityResult(),如果A启动B时使用startActivityForResult();那么由B返回A时会调用这个方法。
  • onSaveInstanceState(),在activity被杀死前调用,用来存储当前状态,可以在Bundle里面存储一些值。
  • onRestoreInstanceState(),在onStart()后面调用,用来恢复一个再次初始化的activity在onSaveInstanceState()里面存储的值。

举例:

  • 单纯打开activity A :onCreate(),onStart(),onResume();
  • 锁屏/回到桌面:onPause(),onStop();
  • 开屏/再次打开:onRestart(),onStart(),onResume();
  • A启动第二个activity B:A:onPause(),B:onCreate(),onStart(),onResume(),A:onStop();
  • 由B返回A:B:onPause(),onActivityResult(),onRestart(),onStart(),onResume(),onStop(),onDestory();
  • 系统配置发生改变:onPause(),onSaveInstanceState(),onStop(),onDestory(),再重建:onCreate(),onStart(),onRestoreInstanceState(),onResume();

一个小知识:onSaveInstanceState(),当Activity意外终止是,Activity会先调用该方法去存数据,然后Activity会委托Window去保存数据,然后window再委托顶级(是ViewGroup,可能是DectorView)保存,最后顶级再通知子view去保存数据。

启动模式
1.有两种设置方式,一种是在Manifest文件里用launchMode属性来标识(这种没有办法设置FLAG_ACTIVITY_CLEAR_TOP标识),第二种是在代码中设置,并且这种方式的优先级比第一种高,两种都存在以代码中设置的为准(代码里不能设置Activity以SingleInstance方式启动)
2.有四种取值

  • standard:可以多次实例化Activity,一个栈中可以有多个实例
  • singleTop:·没有实例对象的时候,启动放在栈顶,·如果有实例,并且在栈顶,那么就复用,并且调用onNewInstance()方法,·如果有实例但是不在栈顶,就跟standard一样,重新创建一个对象放在栈顶
  • singleTask 如果栈中没有实例对象,启动放在栈顶,如果有实例在栈顶,那会走个onStop(),onNewInstance(),onResume()在栈顶显示。如果有实例不在栈顶,那么会清除在它之上所有的Activity实例,把自己放在栈顶然后调用一下onNewInstance()方法
  • singleInstance 会启动一个Activity实例放到一个单独的栈里,并且系统中之后有这一个实例A,如果A打开B,那么B是在其他栈里的,不与A在同一个栈内

FLAGS
主要是用来初始化Intent时,来标识这个Intent是有什么特性,这个特性可以设定Activity的启动模式、运行状态等等,intent.setFlags(Intent.FLAG_ACTIVITY_*);

使用举例:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
等于
manifest
<activity android:name="com.package.com.FirstActivity" android:LaunchMode="singleTask"/>

intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
等于
manifest
<activity android:name="com.package.com.FirstActivity" android:LaunchMode="singleTop"/>

IntentFilter

意图过滤,Intent启动Activity有两种,一指定类(显式调用),二用IntentFilter过滤器匹配(隐式调用)
举例:

  <Application>
  <activity android:name= "com.package.name.FirstActivity"
      android:configChanges="ScreenLayout|"
      android:launchMode=""
      android:taskAffinity="">
      <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
          <data android:mimeType="image/*"/>
      </intent-filter>
  </activity>
</Application>
intent filter包含三个子项
action

主要用来指定这个用来干啥的,比如系统自带:Intent.ACTION_MAIN(作为应用主入口启动) ACTION_VIEW(用来给用户展示数据)ACTION_WEB_SEARCH(执行一次网络搜索) 官方建议,如果定义自己的action,应该用自己的applicationId开头
匹配规则: 全文匹配并且区分大小写,但是action可以定义多个,在intent中传递的只要匹配一个就行,如果manifest里面没有定义,但是intent里写了action的话,也是匹配失败的。

category

主要定义这个是个什么种类范畴的,比如系统自带:Intent.CATEGORY_BROWSABLE(可以打开网页进行浏览的)CATEGORY_APP_MARKET(可以浏览和下载APP的)
匹配规则:全文匹配,intent中指定的category必须在manifest里面都有定义,否则就匹配失败。

data

主要规定这个intent操作什么数据。data里面有Uri(scheme、host、port、path、pathPattern、pathPrefix)和mimeType。Uri中scheme/host是必写的字段,但是Uri不是必须设置的,看你需要。pathPattern和path意思相同,但是pathPattern可以有通配符。

//完整data定义举例
<data 
  android:scheme="abc" 
  android:host="com.host.name" 
  android:port=2021 
  android:path="/path/subpath"
  android:pathPattern="/path/*"
  android:mimeType="text/html"/>

mimeType就是image/png啊这些,可以参考mimeType表格
匹配规则 举例说明:

//manifets
<data android:scheme="abc" android:host="com.host.name" android:port=2021 android:mimeType="text/html"/>
//intent
Intent intent = new Intent();
intent.setData(Uri.prease(abc://com.host.name:2021));
//如果要设置data和mimeType
intent.setDataAndType(Uri.prease(abc://com.host.name:2021),"text/html");

一个小知识 如果要设置data和mimeType,只能调用intent.setDataAndType,如果单独调用intent.setData(),这个方法会清空type,intent.setType()会清空data()。原因setDataAndType注释说系统会根据data推断出正确的mimeType,如果自己设置的对不上就会报错。如果是自己设置的scheme比如abc而不是content、file等等,那就自己调用setDataAndType设置。

隐式启动异常规避

比如没有匹配成功,intent启动失败就会异常,startActivity之前先调用下面的方法

调用这个:
PackageManager.queryIntentActivities(intent)返回一个list里面从匹配度最高排向匹配度最低,如果没有就是一个空的list
或者这个:
Intent.resolveActivity(PackageManager)没有匹配的就返回null

一个小知识 mainfest文件里,activity的taskAffinity 这个参数主要和singleTask或者和allowTaskReparenting属性一起使用,在其他情况下这个参数没有意义。还有,如果要指定栈,要与应用包名不同才行。
如果和allowTaskReparenting属性一起用,比如A应用启动了B应用的一个Activity,那么当点击B应用的图标启动的时候,这个activity会从A的栈中回到B的栈中。

一个小知识 onSaveInstanceState()方法的调用时机:
1,按下Home键
2,长按Home键,切换到其它应用。
3,关闭屏幕显示。
4,跳转到另一个Activity。
5,切换屏幕方向。

Activity构成

每个Activity都持有一个PhoneWindow(Window的实现类)在里面就是一个DecorView,然后这个里面分为两块,一个是titleView一个是ContentView的父容器(一个ViewGroup用来盛放最终我们设置的Activity的布局文件)
——————————————————————————
|Activity
| ———————————————————————
| |PhoneWindow
| | ————————————————————
| | |DecorView
| | | ——————————————————
| | | |ViewGroup(ContentViewParent)
| | | | ————————————————
| | | | | contentView(The layout xml)

Activity启动过程分析

从调用startActivity开始,acitivty启动是一个IPC过程,底层会用到Binder和系统通信,系统实现组件的增改删查。

Activity的window创建过程

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

推荐阅读更多精彩内容