一、静态注册 ,在Manifest文件的application
节点中配置广播接收者java
<receiver android:name=".MyBroadCastReceiver">
<!-- android:priority属性是设置此接收者的优先级(从-1000到1000) -->
<intent-filter android:priority="20">
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
复制代码
二、动态注册,经过Context
对象的registerReceiver
方法注册广播android
//new出上边定义好的BroadcastReceiver
MyBroadCastReceiver yBroadCastReceiver = new MyBroadCastReceiver();
//实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//注册广播
myContext.registerReceiver(smsBroadCastReceiver,intentFilter,
"android.permission.RECEIVE_SMS", null);
复制代码
区别:静态注册的为常驻型广播,即便应用程序关闭了,若是又信息广播来,程序也会被系统调用执行。而动态注册的广播不是常驻型,广播被取消注册或者应用程序关闭后都不能接收安全
一、有序广播:按照优先级,一级一级向下传递,接收者能够修改广播数据,也能够终止广播事件。app
二、无序广播:全部接收者都会接收事件,不能被拦截跟修改。ide
一、使用Context
的startService
方法启动函数
onCreate()
--->onStartCommand()
--->onDestroy()
oop
二、使用Context
的bindService
方法启动布局
onCreate()
--->onBind()
--->onUnBind()
--->onDestroy()
this
一、在外部使用stopService
方法,若是使用bindService
的方式启动,则使用unbindService
方法中止spa
二、在Service
内部(onStartCommand
方法内)使用stopSelf
onStartCommand
方法的返回值一、START_NOT_STICKY
:“非粘性的”。使用这个返回值时,若是在执行完onStartCommand
方法后,服务被异常kill掉,系统不会自动重启该服务
二、START_STICKY
:若是Service进程被kill掉,保留Service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试从新建立Service,因为服务状态为开始状态,因此建立服务后必定会调用onStartCommand(Intent,int,int)方法。若是在此期间没有任何启动命令被传递到Service,那么参数Intent将为null。
三、START_REDELIVER_INTENT
:重传Intent。使用这个返回值时,系统会自动重启该服务,并将Intent的值传入。
继承于Service
,启动方式与Service
的传统启动方式同样,不一样点在于内部有一个线程来处理耗时操做,当任务执行完成时服务会自动中止。
standard
:标准模式,默认的启动模式,不论是否已经存在实例都会生成新的实例
singleTop
:栈顶复用模式,若是发现有对应Activity的实例正位于栈顶,则直接打开此页面,再也不生成新的实例,同时onNewIntent
方法会被执行,onCreate
跟onStart
方法都不会执行。不然跟standard
模式同样继续生成新的实例。
singleTask
:站内复用模式,若是栈内存在对应Activity的实例就会复用这个Activity,复用时会将它上面的Activity所有出栈,同时onNewIntent
方法也会被执行。
singleInstance
:单例模式,该模式具有singleTask模式的全部特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具备全局惟一性。以singleInstance模式启动的Activity在整个系统中是单例的,若是在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
app启动的过程有两种状况,第一种是从桌面launcher上点击相应的应用图标,第二种是在activity中经过调用startActivity来启动一个新的activity。
Luncher.startActivitySafely()
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher { ...... void startActivitySafely(Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { ...... } catch (SecurityException e) { ...... } } ...... } 复制代码
Activity.startActivity
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks { ...... @Override public void startActivity(Intent intent) { startActivityForResult(intent, -1); } ...... } 复制代码
Activity.startActivityForResult
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks { ...... public void startActivityForResult(Intent intent, int requestCode) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode); ...... } else { ...... } ...... } 复制代码
Instrumentation.execStartActivity
public class Instrumentation { ...... public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { ...... } try { int result = ActivityManagerNative.getDefault() .startActivity(whoThread, intent, intent.resolveTypeIfNeeded(who.getContentResolver()), null, 0, token, target != null ? target.mEmbeddedID : null, requestCode, false, false); ...... } catch (RemoteException e) { } return null; } ...... } 复制代码
这里的
ActivityManagerNative.getDefault
返回ActivityManagerService
的远程接口,即ActivityManagerProxy
接口
ActivityManagerProxy.startActivity
class ActivityManagerProxy implements IActivityManager { ...... public int startActivity(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeTypedArray(grantedUriPermissions, 0); data.writeInt(grantedMode); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(onlyIfNeeded ? 1 : 0); data.writeInt(debug ? 1 : 0); mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); int result = reply.readInt(); reply.recycle(); data.recycle(); return result; } ...... } 复制代码
ActivityManagerService.startActivity
Context是一个抽象基类,翻译为上下文,也能够理解为环境,提供一些程序运行基础信息。
Context有两个子类,ContextWrapper
是上下文功能的封装类,而 ContextImpl
则是上下文功能的实现类。而 ContextWrapper
又有三个直接的子类, ContextThemeWrapper
、Service
和Application
。其中,ContextThemeWrapper
是一个带主题的封装类,而它有一个直接子类就是Activity,因此Activity和Service以及Application的Context是不同的,只有Activity须要主题,Service不须要主题。Context一共有三种类型,分别是Application、Activity和Service。这三个类虽然分别各类承担着不一样的做用,但它们都属于Context的一种,而它们具体Context的功能则是由ContextImpl
类去实现的,所以在绝大多数场景下,Activity、Service和Application这三种类型的Context都是能够通用的。不过有几种场景比较特殊,好比启动Activity,还有弹出Dialog。出于安全缘由的考虑,Android是不容许Activity或Dialog凭空出现的,一个Activity的启动必需要创建在另外一个Activity的基础之上,也就是以此造成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),所以在这种场景下,咱们只能使用Activity类型的Context,不然将会出错。
Activity
构造的时候会初始化一个Window( PhoneWindw
)PhoneWindow
有一个 RootView
,这个RootView
是一个ViewGroup,是最初始的根视图RootView
经过 addView
方法来一个个添加 View
View的绘制流程:onMeasure
-> onLayout
-> onDraw
第一步:onMeasure
测量视图大小,从顶层父View到子View递归调用 measure
方法,measure
方法又回调 onMeasure
方法。
第二步:onLayout
肯定View位置,进行页面布局。从顶层父View向子View递归调用 layout
方法的过程,即父View根据上一步 measure
获得的布局大小和布局参数,将子View放在合适的位置上。
第三步:onDraw
绘制视图。主要步骤为①:绘制背景,②:绘制本身,③:绘制子View,④:绘制滚动条
ViewGroup 包含 dispatchTouchEvent
、onInterceptTouchEvent
、onTouchEvent
三个相关方法,View包含 dispatchTouchEvent
、onTouchEvent
两个相关方法。
Activity
接收到Touch事件时,将遍历子View进行Down事件分发,分发的目的是为了找到真正处理本次完整触摸事件的View,这个View会在 onTouchEvent
返回true。onTouchEvent
事件。触发的方式是调用 super.dispatchTouchEvent
函数,即调用父View的dispatchTouchEvent
方法。Android的主线程不能进行耗时操做,子线程不能进行更新UI,因此就有了Handler,它的做用就是实现线程之间的通讯。
Handler整个流程中主要有四个对象:Handler
、Message
、MessageQueue
、Looper
。经过将要传递的消息放在Message
中,Handler
经过 sendMessage
方法将消息放入 MessageQueue
中,Looper
对象会不断的调用loop()
方法不断从 MessageQueue
中取出 Message
交给 Handler
进行处理。
内存泄漏跟内存溢出的区别:
内存泄漏的缘由:
Handler引发的内存泄漏:
将Handler声明为静态内部类,就不会持有外部类的引用,其生命周期就跟外部类无关。若是Handler内部要使用Context,则可使用弱引用的方式。
单例模式引发的内存泄漏:
Context是ApplicationCotnext,ApplicationCotnext的生命周期与app一致,不会致使内存泄漏.
非静态内部类建立实例引发的:
建立为静态实例
非静态匿名内部类引发的:
将匿名内部类修改成静态的
注册/反注册未成对使用引发的内存泄漏
注册广播接受器、EventBus等,记得解绑
资源对象没有关闭引发的内存泄漏
在这些资源不使用的时候,记得调用相应的相似close()、destroy()、recycler()、release()等方法释放
集合对象没有及时清理引发的内存泄漏
一般会把一些对象装入到集合中,当不使用的时候必定要记得及时清理集合,让相关对象再也不被引用
内存泄漏检测:LeakCanary
ANR全名"Application not responding",即应用无响应。产生的缘由: