Activity

作者: 简安理思 | 来源:发表于2022-02-21 10:11 被阅读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()--> 被销毁,可以做一些回收和最终的资源释放

    • 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创建过程

    相关文章

      网友评论

          本文标题:Activity

          本文链接:https://www.haomeiwen.com/subject/juozaltx.html