Activity

2022-02-21  本文已影响0人  简安理思

概念
启动模式
声明周期
启动过程
加载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()--> 被销毁,可以做一些回收和最终的资源释放

举例:

一个小知识: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创建过程

上一篇下一篇

猜你喜欢

热点阅读