美文网首页
android开发艺术探索 笔记(一)

android开发艺术探索 笔记(一)

作者: M1chaelY0ung | 来源:发表于2017-05-03 19:02 被阅读0次

    第一章Activity的启动与生命周期

    正常情况下的启动状态
    onCreate加载布局,初始化数据
    onStart界面可视化,但尚在后台,不可交互。
    onRestart从不可见(onStop)到可见(onStart)需要经过onRestart
    onResume从后台到前台,Activity变得可以交互。
    onPause一般onPause后紧接着onStop,所以不推荐将耗时的操作放在这里。
    ×当新的Activity为透明时,原先Activity还是可视的,因而不会执行onStop
    onStop从不可互动到不可视,如点击home键回到桌面,这是Activity一般还没有被销毁,等待着onRestart->onStart->onResume重新恢复状态
    onDestroy销毁Activity,并进行一些回收工作,如关闭数据库等。
    
    一张应该出现过很多遍的图

    基于书上说的屏幕的点亮熄灭以及手指的触摸,我个人试了一下

    界面一切·从简,就是默认emptyActivity的界面
    每个方法写都写一个Log.d("ActivityLife","onXXXX");//XXXX视方法而定
    

    Activity刚启动时: onCreate->onStart->onResume


    启动时

    点击返回键,关闭程序时:onPause->onStop->onDestroy


    退出
    点击home键:onPause->onStop
    后台

    从后台唤醒:onRestart->onStart->onResume


    唤醒
    一直到这里,都和我们在前面的理论是一样的。
    锁屏时,其实和挂到后台是一样的
    锁屏
    当唤醒屏幕时,如果有密码的话,唤醒之后是要输入密码,这个时候Activity的界面依旧不可见,因此不会调用以上的任何方法,只有解锁后,Activity重新可见时,又会执行之前从后台唤醒相同的步骤
    唤醒
    从Activity1启动Activity2,会先执行Activity1的onPause,然后创建Activity2(onCreate->onStart->onResume)再执行Activity1的onStop.
    一些小细节
    关于生命周期的重点在于onStart、onStop控制的是Activity是否可见(在后台),onResume、onPause控制的是Activity是否在前台可供操作。
    异常情况下的生命周期

    而onSaveInstanceState是系统自行销毁Activity时对数据的保存。重新打开时调用onRestoreInstanceState恢复数据。即异常情况下销毁Activity时,会调用这两个方法恢复数据。而横竖屏就属于这种异常情况。


    横竖屏
    • 这里我们可以发现,onSaveInstanceState是在onStop前执行的,而onRestoreInstanceState是在onStart后执行的。
    • 当Activity异常情况下的情况下需要重新创建时,系统会默认我们保存当前Activity的视图结果,并在Activity重启后为我们恢复这些数据,比如文本框用户输入的数据,ListView的滚动位置等
    • 关于保存和恢复View的层次结构,系统的工作流程:首先Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window会委托它上面的顶级容器去保存数据,顶层容器一般是DecorView(ViewGroup);最后顶层容器再去一一通知它的子元素保存数据,这样整个数据的保存过程就完成了。
      ×这里还要注意一下,onSaveInstanceState还有一个两个参数的方法,是不会在异常状态中调用的。
    资源不足导致的Activity被销毁
    Activity的优先级
    • 正在和用户交互的Activity优先级最高: onResume
    • 可见但非前台的Activity优先级次之:onPause
    • 后台Activity优先级最低:onStop
      当系统内存不足时会杀死目标Activity的进程,再用onSaveInstanceState和onRestoreInstanceState进行恢复。
      如果一个进程在后台没有四大组件在运行,很容易被系统回收,因此可以在后台放入一个service提高优先级。
    configChanges

    当系统配置发生改变时,Activity会重新创建,如果在Activity指定configChanges属性,Activity就会执行configChanges的属性,而不用重新创建了。
    如横竖屏切换:

    manifests中配置
    android:configChanges = "orientation"
    //多个属性用|
    
    @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            Log.d("ActivityLife","onConfigChanged:"+newConfig.orientation);
        }
    

    Activity创建后,从竖屏到横屏再到竖屏的过程中


    没用调用onSaveInstanceState和onRestoreInstanceState方法,也没有重新创建Activity configChanges的一些属性

    常用的是locale、orientation和keyboardHidden
    ×android4.0以上orientation要注意配置screensize,不然还是会调用onCreate
    使用configChanges:orientation时,就不会使用oSaveInstanceState和onRestoreInstanceState来恢复数据了,因为都没有销毁。。。

    Activity的启动模式
    Activity的LaunchMode

    任务栈是一个“后进先出”的栈结构,每次finish()处于前台的Activity就会出栈,直到栈为空为止,当栈中无任何Activity的时候,系统就会回收这个任务栈。

    • standard
      默认的模式,每次启动都会创建一个新的Activity到任务栈中。Activity A启动Activity B会让B进入A所在的任务栈中,就是这种特性导致,ApplicationContext没有任务栈,context启动standard的Activity时会发生错误。这时候需要在Intent中加入FLAG_ACTIVITY_NEW_TASK,这时实际上是以singleTask启动的。
      Actvity1启动Activity1



      销毁上面的Activity1


    • singleTop
      栈顶复用模式,若该Activity处于任务栈的栈顶,那么就不会重新创建该Activity。
      (Activity1为singleTop)
      Activity1启动Acticity1时:



      只调用onPause->onNewIntent->onResume
      销毁时:



      只有单个Activity在栈中
      Activity1启动Activity2再启动Activity1时:
      捕获.PNG
      会重新创建Activity1
      销毁时:
      销毁最上面的Activity1
      销毁Activity2
    • singleTask
      栈内复用模式。这种模式下,Activity在一个栈中存在,那么多次启动该Activity都不会重新创建实例,和sinleTop一样,系统会回调其onNewIntent。如果启动的Activity没有所需要的任务栈,就会先创建任务栈再创建Activity。singleTask默认具有clearTop的效果,具有该模式的Activity会让其之上的Activity全部出栈。
      Activity1处于栈顶时启动Activity1


      这里和singleTop是一样的

      Activity1启动Activity2再启动Activity1



      注意这里,由于不会生成新的Activity1,所以调用onRestart->onStart->onResume,而Activity2会直接被销毁。
    • singleInstance
      单实例模式。这是一种加强的singleTask模式,除了具备singleTask的特性之外,具有该模式的Activity只能单独位于一个任务栈中;比如Activity A是singleInstance模式的,当A启动后,系统会为它创建一个新的任务栈,后续的启动均不会创建新的Activity,除非这个任务栈被系统销毁了。
      这里可以这么理解,singleInstance会创建一个新的任务栈,这个任务栈中只有自己一个实例,启动其他Activity会重新创建一个任务栈,供其他的Activity使用。此时Activity的销毁顺序与创建顺序无关,和任务栈内Activity的顺序有关。当销毁时处在singleInstance所在的任务栈,那么该任务栈会被销毁,跳转到另一个任务栈的栈顶,再根据这个任务栈Activity的次序进行销毁。而当销毁工作处于另一个任务栈时,会先选择清空这个任务栈的所有实例,在跳转到唯一的singleInstance所在任务栈的实例。
    关于四个启动模式的流程图->http://www.jianshu.com/p/7a11ff292423
    LaunchMode的使用方法
    在manifests中activity下
    android:launchMode="singleInstance"
    或者在intent中addFlag
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
    这里第二种方法的优先级更高,而区别在于第一种方法不能使用FLAG_ACTIVITY_CLEAR_TOP,第二种不能设置singleInstance。

    这里书中还提到了TaskAffinity和AllowTaskReparenting两个属性
    TaskAffinity标识了Activity所需的任务栈的名字
    AllowTaskReparenting="true"时,例子如下:
    A启动B的ActivityC,ActivityC刚好是这个属性,此时C会在A的任务栈中。当按下home键再打开应用B时,会直接打开ActivityC,而不是默认的首页面。此时ActivityC会从A的任务栈转移到B的任务栈

    adb shell dumpsys activity命令可以详细的了解当前任务栈情况
    Activity的Flags
    • FLAG_ACTIVITY_NEW_TASK
      即singleTask
    • FLAG_ACTIVITY_SINGLE_TOP
      即singleTop
    • FLAG_ACTIVITY_CLEAR_TOP
      有此标记的Activity在启动时,在其上的所有Activity都将被销毁,一般会和singleTask一同出现,当被启动的Activity是standard模式时,该Activity及以上的Activity都会出栈,再重新创建新的Activity
    • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    有该标识的Activity将不会出现在历史Activity列表中,xml中等同于:
    android:exculdeFromRecents="true"```
    #####IntentFliter的匹配规则
    - 显式调用
    明确表示启动对象的包名类名
    - 隐式调用
    需要Intent匹配IntentFliter所设置的过滤信息
    - 一个Activity可以有多个IntentFliter,一个IntentFliter可以有多个action、category或是data。
    - 其中Intent需要同时匹配一个IntentFliter中的三种(action、category和data)信息。
    - 一个Activity中只要匹配一个IntentFliter就可以了。
    
    - #####Action
    action系统有预定义的,当然我们也能自己定义,其中intent中action必须与IntentFliter中一个action匹配。(没有就默认不匹配)还有一点就是action区分大小写
    - #####Category
    category系统有预定义的,当然我们也能自己定义。category与action不同的是:intent中没有category是默认匹配成功的。如果intent定义了category,则要求intent中所有的category都是intentFliter的category中的一个。
    - #####data
    data的匹配模式与action类似,都需要至少一个匹配。
    

    data的语法
    <data android:scheme="string"
    android:host="string"
    android:port="string"
    android:path="string"
    android:pathPattern="string"
    android:pathPrefix="string"
    android:mimeType="string"/>

    data由两部分组成,URI和mimeType。URI指定类似于路径的状态,mimeType指定媒体数据
    - URI的结构有mimeType前面的scheme、host、port、path、pathPattern、pathPrefix组成。
    

    <scheme>://<host>:<port>/{<path>|<pathPrefix>|<pathPattern>}
    对应:
    content://com.example.project:200/folder/subfolder/etc
    http://www.baidu.com:80/search/info

    - scheme:URI的模式,如http、file、content等,若没有指定scheme,URI是无效的。
    - Host:URIde主机名,URI中不能为空
    - Port:URI的端口号,scheme和host都指定了才有意义。
    - Path、pathPattern、pathPrefix:三个参数表述路径信息。
    

    Path指定完整路径
    pathPattern也指定完整路径,但是可以使用通配符"",""表示0或多个字符。由于正则表达式的规范,真实字符串中""要用"\"表示,""要用"\\"表示
    pathPrefix表示路径的前缀信息

    当没有指定URI时,URI默认为content和file。
    Intent添加data信息:
    

    如果要指定完整data信息,需要setDataAndType
    intent.setDataAndType(Uri.parse("file://abc"),"image/png");
    使用setData和setType会彼此擦除对方的值

    这里data比action特殊的还有一点,就是:
    

    <intent-filter...>
    <data android:scheme="file" android:host="www.baidu.com"/>
    ...
    </intent-filter>

    <intent-filter...>
    <data android:scheme="file"/>
    <data android:host="www.baidu.com"/>
    ...
    </intent-filter>

    上面的两种方法是一样的。
    当我们隐式启动一个Activity的时候,可以做一下判断,看是否能匹配到我们的隐式Intent,如果不做判断没找到对应的Activity系统就会抛出android.content.ActivityNotFoundException异常。
    采用PackageManager的resolveActivity方法或者Intent的resolveActivity方法,如果找不到匹配的Activity就会返回null,我们通过判断返回值就可以规避上述错误了。
    ######接收隐式意图的Activity必须有<category android:name="android.intent.category.DEFAULT"/>,这个category的作用在于上述两个方法只要不返回null,就能启动Activity。
    ######有一类action和category的共同作用是标明这是一个入口Activity,并且会出现在系统的应用列表中,少一个都没有任何意义,也不会出现在系统的应用列表中。
    

    <action android:name="android.intent.action.MAIN" />
    //最先启动的activity
    <category android:name="android.intent.category.LAUNCHER" />
    //桌面的图标,显示在程序列表中

    
    ####知识点总结的比较全,难听点就是笔记太啰嗦了吧,感觉都有点重要,整章的内容都快要都写进来了。
    ####这一章的内容不是特别多,但我还是写的有些杂乱,或许写多了,就好了吧

    相关文章

      网友评论

          本文标题:android开发艺术探索 笔记(一)

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