Activity生命周期
onCreate()->Created->onStart()->Started->onResume()->Resumed
继续:在这种状态下,Activity处于前台,且用户可以与其交互(又称为运行态,在调用onResume()方法后)。
暂停:在这种状态下,Activity被在前台中处于透明状态或者未覆盖整个屏幕的另一个Activity一部分阻挡。暂停的Activity不会接收用户输入,并且无法执行任何代码。
停止:在这种状态下,Activity被完全隐藏并且对用户不可见;它被视为处于后台。停止时,Activity实例及其诸如成员变量等状态信息将保留,但它无法执行任何代码。
其他状态(创建和开始)是瞬态,系统会通过调用下一个生命周期回调方法从这些状态快速移到下一个状态。也就是说,在系统调用onCreate()之后,会快速调用onStart(),紧接着快速调用onResume()。
当半透明Activity打开时(比如对话框样式中的Activity),上一个Activity会暂停。只要Activity仍然部分可见但目前又未处于焦点之中,它会一直暂停。但是,一旦Activity完全被阻挡并且不可见,它便停止。
Fragment生命周期
Fragment is added->onAttach()->onCreate->onCreateView->Activity-onCreate->onActivityCreated->Activity-onStart->onStart->Activity-onResume->onResume->onPause->Activity-onPause->onStop->Activity-onStop->onDestroyView->onDestroy->onDepatch->Activity-onDestroy。
fragment和activity生命周期
单独考虑Fragment的话,Fragment is added->onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDepatch.
fragment生命周期
Service生命周期
Start Service: onCreate()->onStartCommand()->ServiceRunning->onDestroy()->Service shut down
Bind Service: onCreate()->onBind()->Clients are bound to service->onUnbind()->onDestroy()->Service shut down
Activity四种启动模式
标准模式(Standard)、栈顶复用模式(SingleTop)、栈内复用模式(SingleTask)、单实例模式(SingleInstance)。
任务栈是一种后进先出的结构。位于栈顶的Activity处于焦点状态,当按下back按钮的时候,栈内的Activity会一个一个的出栈,并且调用其onDestory()方法。如果栈内没有Activity,那么系统就会回收这个栈,每个APP默认只有一个栈,以APP的包名来命名.
Standard:每次启动Activity都会创建一个新的Activity实例,并且将其压入任务栈栈顶,而不管这个Activity是否已经存在。Activity的启动三回调(onCreate()->onStart()->onResume())都会执行。
singleTop:这种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,所以它的启动三回调就不会执行,同时Activity的onNewIntent()方法会被回调.如果Activity已经存在但是不在栈顶,那么作用与standard模式一样。
singleTask:创建这样的Activity的时候,系统会先确认它所需任务栈已经创建,否则先创建任务栈.然后放入Activity,如果栈中已经有一个Activity实例,那么这个Activity就会被调到栈顶,onNewIntent(),并且singleTask会清理在当前Activity上面的所有Activity.(clear top)
singleInstance:加强版的singleTask模式,这种模式的Activity只能单独位于一个任务栈内,由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。
四大组件的激活
ContentProvider和BroadcastReceiver不用显式关闭。(BroadcastReceiver生命周期只有十秒左右)
动态注册的广播需要取消注册unRegister。
Android消息处理机制(Handler、Message、MessageQueue、Looper)
消息处理机制本质:一个线程开启循环模式持续监听并依次处理其他线程给它发的消息。一个线程开启无限循环模式,不断遍历自己的消息列表,如果有消息就挨个拿出来做处理,如果列表没消息,自己就阻塞(wait,让出cpu资源给其他线程)
Handler通过handleMessage()来处理UI。
handler.sendMessage(Message msg)发送消息,进入到线程的MessageQueue中,Looper的loop()不断尝试从MessageQueue中取出待处理消息,最后分发回Handler的handleMessage中,Looper.prepare()创建Looper对象。
ThreadLocal
线程本地存储区,每个线程都有自己的私有的本地存储区域, 不同线程之间彼此不能访问对方的TLS区域。
Binder线程
具体是指Application Thread,在App进程中接受系统进程传递过来的信息的线程(在主线程进入死循环之前创建了这个线程)。
总结
当我们调用handler.sendMessage()方法发送一个Message时,实际上这个Message是发送到与当前线程绑定的一个MessageQueue中,然后与当前线程绑定的looper将会不断从MessageQueue中取出新的Message,调用msg.target.dispatchMessage(msg)方法将消息分发到与Message绑定的handler.handleMessage()方法中。
一个Thread对应多个handler,一个Thread对应一个looper和MessageQueue,handler和Thread共享looper和MessageQueue,Message只是消息的载体,将会被发送到与线程绑定的唯一的MessageQueue中,并且被与线程绑定的唯一的looper分发,被与其自身绑定的handler消费。
事件分发机制
Android事件分发流
Android事件分发流如果没有对控件里面的方法进行重写或更改返回值,而直接用super调用父类的默认实现,那么整个事件流向应该是从Activity->ViewGroup->View从上往下调用dispatchTouchEvent方法,一直到叶子节点View的时候,再由View->ViewGroup->Activity从下往上调用onTouchEvent方法。
对于dispatchTouchEvent返回false的含义:事件停止往子View传递和分发同时开始往父控件回溯(父控件的onTouchEvent开始从下往上回传直到某个onTouchEvent return true),事件分布机制就像递归,return false的意义就是递归停止然后开始回调。onTouchEvent return false就是不消费事件,并让事件继续往父控件的方向从下往上流动。
ListView
RecycleBin机制(这个机制是ListView能够实现成百上千条数据都不会OOM的重要原因)
RecycleBin是AbsListView的一个内部类。RecycleBin当中使用mActiveViews这个数组来存储View,调用这个方法后就会根据传入的参数来将ListView中的指定元素存储到mActiveViews中。
mActiveViews当中所存储的View,一旦被获取了之后就会从mActiveViews当中移除,下次获取同样位置的时候将返回null,所以mActiveViews不能被重复利用。
AsyncTask
AsyncTask是基于异步消息处理机制的,封装好的。
1、onPreExecute()后台任务开始执行之前调用。
2、doInBackground()这个方法的所有代码都会在子线程中进行,可调用publishProgress来更新UI元素。
3、onProgressUpdate()对UI进行操作。
4、onPostExecute()利用返回的数据来进行一些UI操作。
SQLite
通常不会操作SQLiteDatabase这个类,而是自己创建一个继承SQLiteOpenHelper的子类来实现数据库操作。
目的:1)为了以后如果数据库升级不至于要改动太多代码,已实现封装;
2)为了我们使用更方便。
SQLiteOpenHelper有两个抽象方法,OnCreate和OnUpgrade(用于数据库升级)
如果数据库已存在,而版本号比上次创建的数据库版本号高,就调用OnUpdate,用于升级。
自定义View
1、自定义属性的声明和获取(分析需要的自定义属性)
在res/values/attrs,xml定义声明,在Layout文件中进行使用,在View的构造方法中进行获取。
2、测量onMeasure()
3、布局onLayout(ViewGroup)
4、绘制onDraw()
5、onTouchEvent()
6、onInterceptTouchEvent(ViewGroup)
7、状态的恢复和保存
LayoutInflater,主要是用于加载布局的。setContentView()方法内部也是调用LayoutInflater来加载布局的。LayoutInflater.from(Context )获取到LayoutInflater实例。
View三步走(onMeasure、onLayout、onDraw)
onMeasure计算视图大小,默认会调用getDefaultSize获取视图大小。可以通过setMeasureDimension方法定制测量方式,可通过getMeasuredWidth()和getMeasuredHeight()获取视图测量出的宽高,onMeasure方法实际就是用于更新内部变量mMeasuredWidth和mMeasuredHeight的值。
ViewRoot的performTraversals()方法会在measure后继续执行,并调用View的layout()方法来执行此过程。
layout()方法先用setFrame()方法判断视图大小是否发生变化,以确定有没有必要对当前的视图进行重绘,然后调用onLayout()方法,默认是个空方法。而ViewGroup中的onLayout()是个抽象方法,即它的继承类都有重写这个方法,像LinearLayout。RelativeLayout都进行了重写。
getMeasuredWidth和getWidth的区别:1、getMeasuredWidth是在measure过程结束获取到的,getWidth要在layout结束才能获取到;
2、getMeasuredWidth的值是通过setMeasuredDimension()进行设置的,而getWidth得到的值是通过layout()方法传入的参数得到。
draw()方法对视图进行绘制,onDraw方法是对视图内容进行绘制,默认是个空方法,因为每个View内容部分不相同,所以交给子类自己实现。可调用invalidate()方法通知进行视图重绘。
如果要加载一个布局文件,可以用LayoutInflater.from()获取到LayoutInflater实例,然后调用inflate方法加载R.layout,xml布局文件,最后调用LinearLayout的addView方法将它添加到LinearLayout中。View必须存在于布局中,Layout-width和Layout-height才有意义。不然无法设置控件大小,在Activity中指定布局文件时,其实是自动在布局文件最外层嵌套了一个FrameLayout。
网友评论