ANR
根本原理,是系统把各种消息事件丢给应用的时候,会带一个延时消息,如果事件及时处理,则取消延时消息,否则在延时消息执行时,系统报应用ANR。
Looper
消息通知流程和原理
根据消息处理时间(Message.when),将消息按照执行时间从先到后放到MessageQueue合适的位置(队列头是最早能被执行的消息)。
先调nativePollOnce休眠,不过一开始传给epoll_wait的休眠时间是0,所以会立刻唤醒返回。然后取出查看Message.when,如果小于等于当前时间,直接返回。如果大于当前时间,则计算需等待时间,通过nativePollOnce传给epoll_wait休眠。到了时间epoll_wait就会被唤醒,从而返回该message。
消息队列为空时,给nativePollOnce传入-1,epoll_wait无限期休眠(因为没有系统的延时消息,所以不会ANR)。有消息进来时,往epoll监听的fd写消息,从而唤醒epoll,java层解除阻塞从消息队列取消息。
Looper中的fd
Looper不仅可以监听用于系统消息通知的mWakeEventFd,还支持通过addFd函数增加监听的fd,epoll_wait监听到事件后,根据事件对应的fd,做不同的处理。每个添加的fd,都有自己对应的response回调处理。
for (int i = 0; i < eventCount; i++) {
//获取事件对应的fd
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
//这是消息队列的fd
if (fd == mWakeEventFd) {
if (epollEvents & EPOLLIN) {
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
}
} else {
//这里是自定义的fd
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
将代码放入UI线程执行
非UI线程,我们可以通过Activity.runOnUiThread(Runnable runable)方法,把自定义Runnable放到UI主线程中执行。其原理就是通过UI线程中绑定了UI线程Looper的Handler,把Runnable封装成Message给post到UI线程消息队列:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
Runnable被放进Message的callback中
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
当Message被Looper从消息队列中取出并交给Handler处理,Handler会判断Message是否具有callback,如有,则处理:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
线程间专递
A activity -> B activity -> fragment再一路back键
A: OnCreate -> onStart -> onResume -> onPause
B:onCreate onStart onResume
A:onStop
B:onPause
F:onAttach onCreate onCreateView onActivityCreated onStart onResume onPause onStop onDestroyView onDestroy onDetach
B:onRestart onStart onResume onPause
A:onRestart onStart onResume
B:onStop onDestroy
A:onStop onDestroy
Activity常见标签
theme / exported / launchMode / intent-fliter / process / noHistory
launchMode四种模式使用场景
standard:默认模式
singleTop:例如通知栏多条消息都会跳转到同一个页面时
singleTask:app主页,需要长时间存在且用户很有可能多次跳转过去的页面
singleInstance:电话拨号盘页面,通过自己的应用或者其他应用打开拨打电话页面 ,只要系统的栈中存在该实例,那么就会直接调用。
intent-fliter
Action:代表一个Intent的标识
Data:可以在Activity中通过getData获取
category:标识这个activity能够handle的intent
Extras: putExtra后Activity可以通过getExtra获取
IntentService
IntentService是后台服务类,我们在外部组件中通过Intent向IntentService发送请求命令,之后IntentService逐个执行命令队列里的命令,队列里的命令将会被顺序执行,最后执行完队列的所有命令后,服务也随即停止并被销毁。
ContentProvider
ContentProvider为其他应用程序提供了访问本应用程序的接口,其他应用程序可以通过ContentResolver来操作ContentProvider提供的数据,保证了被访数据的安全性。
sql也有增删改查的方法,单sql只能操作本应用下的数据库。
Service的两种启动方式区别
startService:如果没有stopService,Service会一直在后台运行
bindService:如果所有bind的进程都销毁了,就会自动调用onUnbind -> onDestroy。
如果先bindService再调startService: onCreate -> onBind -> onStartCommand 这时stopService无效,必须先unBindService
网友评论