activity 和 生命周期 :流程
activity是android的一个基本的组件。讨论生命周期,taskstack等等的话题的时候。就不得不去看一下android framework层的源码了。
生命周期,实际就是系统调用android代码的时候做的回调函数,复写之后,就会和android app运行为一体。简单的来说,和activity有关的类有很多。其中和生命周期有关的,就是管理activity的类。包括activityThread,activityManagerNative,activityManagerService 和activityStack:
activityThread: 每一个java程序都有一个main函数,android也不例外。每一个app都是一个进程,这里既是一个app的起始点。gui的编程无非就是在循环中不断的读取消息,然后处理消息。这里的消息包括了各种系统定义的消息,还有ui的消息。activityThread里面有一个H内部类(就是Handler),这里面就定义了各种的消息处理,包括各个生命周期函数的方法调用消息:LAUNCH_ACTIVITY,PAUSE_ACTIVITY等等。
tip:为什么会有H内部类?假如有了这个疑问,就是没有体会gui编程的本质。消息循环,android开发我感觉弱化了这一概念。假如没有消息循环,窗口就不能判断各种事件,不能作出处理。细想一下,只有响应式的这种设计,才是gui编程的基本原理。没有其他可以代替。所以Handler处理的消息机制是android ui运行的基本ok,这个毋庸置疑了。H存在是合理的不可替代的。为什么会有activityThread?他的出现实际上就是作为消息循环的框架出现的。管理了框架中的各个元件的管理和生成,android4大基本组件activity,service,provider都在activityThread中管理。所以activityThread存在是必然的。
activityManagerNative和activityManagerService:他两个出于不同的包里面,一个是core的app下,一个是services的am包下。来说一下,activityManagerService是zygote创建系统服务,也就是说这个服务和我们的android app是两个进程之间。android的ipc通信使用的是binder机制。这个机制也是android的核心之一,也就是通过activityManagerNative调用了activityManagerService里面的方法,调用了系统功能。
tip:他两的存在性就不必强调了,多任务系统的进程通信一直都是值得关注的问题。而binder机制提供了这种功能。这两个类的作用就是使得app和系统更加有序的交互。
activityStack:栈,是的这个就是activity栈,他也在系统服务包中,说明这个栈管理的是所有的activity的功能。所有的存在的activity都会存储在这个栈中,里面有历史栈,resume栈等,保存着各种的activity操作信息。
tip:activitystack由于android程序一般都是占满屏幕的,所以切换不易,必须要有一种操作的规律和习惯。栈是人们潜意识中很认可的一种结构,android是基于linux支持多进程很好。windowphone7.5的时候就一般了,而且操作很不习惯。玩了很久才弄明白。但不得不说metro风格确实是一大亮点。
解释完这些,我们就了解了android activity的生成过程,细想一下,是通过intent开开启activity的,调用了startActivity,有一个activity的默认操作类Instrumentation来调用了activityManagerNative,然后通过binder调用activityManagerService的方法调用activitystack的管理方法添加activity,启动actvityThread,然后发送消息给H进行显actvity。
在说说生命周期,整个期间是如何进行回调的?其中的调用过程十分复杂,我想我必须研究的足够的时候在写其中的奥妙,可是还是没有完。遇到了一个问题就是在oncreate中想得到view的宽高。网络上有很多方法,但是只有知道系统的调用原理和流程,才会理解为什么那样做。
首先不说如何解决?说一下为什么oncreate中得不到view的宽高?都知道view绘制有3步:测量,布局,绘制。也就是oncreate的时候view就没有做这几个步骤。那setcontentview中做了什么?
回到生命周期:
onreate和ondestory中是指activity被创建了,也就是初始化的时候的回调,这个时候做的都是初始化工作,setcontentview也仅仅就是解析xml然后进行了view的创建。但是布局和大小信息都不确定。
onstart和onstop中指的activity被显示,这个看似是很鸡肋的,我们都没有多使用过,确实,这个时期,就是显示了actvity的窗口,activity可视了。这时候可以layout测绘了?没有,这时候显示的是除了我们setcontentview里面布局之外的东西,也就是有一个actionbar和一个白色背景,当然这要看你的布局是怎么定义的了。这算什么意思?这些布局不都是一起的吗?为什么没有我设置的?细细想,还确实不是一起的,先不谈phonewindow和decorview,我们定义过titlebar没有?没有,这是系统的,实际上这一时期是为了显示activity的,不做其他的。
onresume和onpause指activity在可以交互,坑爹的时刻到了,大多数人认为这个时期一定是加载了我们的布局,实际上在这个时期是要使得布局和前台进行交互,但是在布局测绘之前系统回调了onresume,导致很多人认为onresume之前一定有layout的测绘信息,这个是错误的。你可以查看源码activityThread中关于handleResumeActivity里面的源码,最后调用了activity的makeVisible进行了view的显示。也就是说这一个时刻仅仅是告诉我们actvity要到前台交互的时候了,千万不可和布局的东西混为一谈。
这也就说明了为什么会出现之前的问题,这时候怎么办?所有生命周期的函数都没有在layout的时候调用的,没有生命周期的函数,我们还有回调函数,其实view有一个getViewTreeObserver,可以再viewtree的回调函数中进行值的获取,这种方式是可行的,也就是等到测绘layout之后在进行取值,当然还有一种就是自己进行测绘,利用measure,有的人说不行,实际上他根本就不会使用measure,MeasureSpec是其中的关键,他如何利用一个int来表示了模式和大小两个状态,不明白一共有3种模式,一味的递参数(0,0)那么只能呵呵了。这种方式是可行的,我会在以后view的绘制中专门叙述这些概念。
其实我是想说另一种方式,我在网上没有看到,可能有人实现过。就是使用view.post来进行一个把runnable的方法放到主线程中运行,这个方法可行吗?其关键就是这个代码什么时候执行?是立刻?不是,既是在oncreate中使用这个也会在onresume之后运行,这实际上把一个消息放入消息循环中,由于消息队列是阻塞式的,当执行完所有的显示activity的方法之后才会执行这个消息。做了大量的实验。证明这一点事毋庸置疑的,所以我认为系统创建的消息包括launchactvity和resumeactivity的一些消息一定是view.post这条消息之前的,实际上我尝试源码中的证据,你可以看到的是只看到了H.LAUNCH_ACTIVITY这一个消息(虽然也有H.RESUME_ACTIVITY但是在初始创建期间不会调用),也就是说这个消息处理函数handleLaunchActivity里面执行完了oncreate,就接着执行了onstart和onresume一系列的生命周期函数,并不是每一个回调都作为一个消息。这的理由是合理的:1.你不必使用多个消息,应为这个过程本身就是连续的(当然我指的连续不是代码上的连续,而是逻辑上的连续)。2.这也就是解释了为什么在oncreate里面提交的消息,会在onresume之后执行。
当然这个问题就算解决了,应该思考的不是这个问题,而是android的这些生命周期的是如何协调的?可以看到生命周期是和用户交互最为紧密的。我会在研究源码的同时把后续blog写出来。
activity 和 生命周期 :流程的更多相关文章
- Android之Activity的生命周期
PS:写一发关于Activity的生命周期,也算是面试的重点内容. 学习内容: 1.Activity的生命周期 2.面对多种情况的时候Activity的生命周期 3.onSaveInstanceSta ...
- 浅谈Android中Activity的生命周期
引言 我想对于Android开发人员来说,Activity是再熟悉不过了,今天我们就来探讨下Activity的生命周期.熟悉的掌握Activity对于开发健壮的Android应用程序来说至关重要.下面 ...
- Activity 和 生命周期: 创建
了解了整体的android创建流程之后,就分析一下到底这个过程中做了什么? activity创建中开始时由activityStack中的realstartActivityLocked函数中调用了act ...
- activity的生命周期详解
刚在看mars老师的视频,看到activity的生命周期,就看了一下,总结了一下.下面是各函数的调用时机 为了更清楚的看清楚工作的具体过程,举例如下: ,建立两个activity,一个main,一个a ...
- Activity的生命周期和启动模式
Activity的生命周期分析 典型情况下的生命周期.是指在用户参与的情况下,Activity所经过的生命周期的改变. 异常情况下的生命周期.是指Activity被系统回收或者由于当前设备的Confi ...
- Android开发艺术1之Activity的生命周期
作为<Android开发艺术探索>这本书的第一篇博客,我就多说几句.本系列博客旨在对书中相关内容进行解读,简化,提供一个入门到提高的流程.不敢说书评,也不能说教程,只希望对有些人有帮助就好 ...
- Android开发之漫漫长途 Ⅰ——Android系统的创世之初以及Activity的生命周期
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>中的相关知识,再次表示该书 ...
- Android开发艺术探索笔记——第一章:Activity的生命周期和启动模式
Android开发艺术探索笔记--第一章:Activity的生命周期和启动模式 怀着无比崇敬的心情翻开了这本书,路漫漫其修远兮,程序人生,为自己加油! 一.序 作为这本书的第一章,主席还是把Activ ...
- Android开发学习之路--Activity之生命周期
其实这篇文章应该要在介绍Activity的时候写的,不过那个时候还不怎么熟悉Activity,还是在这里详细介绍下好了.还是参考下官方文档的图吧: 从上面的流程,我们可以看出首先就是打开APP,开始执 ...
- Activity 之生命周期
Activity 之生命周期 本文内容: 1. Activity 介绍 2. Activity 的生命周期 2.1 生命周期图 2.2 常见情况下生命周期的回调 2.3 关于生命周期常见问题 2.4 ...
随机推荐
- 各版本Office办公软件下载
各版本Office办公软件下载:http://pan.baidu.com/share/home?uk=1174874628
- matlab各格式数据读取与保存函数
数据处理及matlab的初学者,可能最一开始接触的就是数据的读取与保存: %matlab数据保存与读入 function datepro clear all; %产生随机数据 mat = rand(, ...
- PBcR - 纠错及组装算法
单分子测序reads(PB)的混合纠错和denovo组装 我们广泛使用的PBcR的原始文章就是这一篇 原文链接:Hybrid error correction and de novo assembly ...
- 项目中关于ajax jsonp的使用
项目中关于ajax jsonp的使用,出现了问题:可以成功获得请求结果,但没有执行success方法总算搞定了,记录一下 function TestAjax() { $.ajax({ ...
- 20145224&20145238 《信息安全系统设计基础》第二次实验
20145224&20145238 <信息安全系统设计基础>第二次实验 课程:信息安全系统设计基础 班级:1452 姓名:陈颢文 荆玉茗 学号:20145224 20145238 ...
- Mac下安装Node.js
今天介绍一下Mac下Node.js的下载安装方法,后面我们安装Bootstrap.Angurlar和jQuery等都是通过Node.js的npm方式的. 1.在必应中搜索“node.js mac”,第 ...
- “不支持一个STA线程上针对多个句柄的WaitAll。”的解决方案
一.异常提示 不支持一个 STA 线程上针对多个句柄的 WaitAll. 出错界面如下图: 二.解决方法 先直接上解决方案吧.其实解决方法很简单如下面的代码直接把main函数的[STAThread]属 ...
- osg,vtk,ogre的区别
osg使用过一年,阅读过一部分源代码,vtk也断续使用过三四年了,ogre研究的比较深入,基本上比较熟悉它的整体结构,说说个人的看法 vtk是一个算法库,里面包括了很多挺不错的算法,如果做有限元云图, ...
- row_number() OVER(PARTITION BY)函数介绍
OVER(PARTITION BY)函数介绍 开窗函数 Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个 ...
- oracle sql
show user desc 'table' SELECT DISTINCT SELECT * FROM emp WHERE comm is NOT NULL; SELECT * FROM emp W ...