目录
一、Activity与Fragment
- Activity各种情况下的生命周期:onCreate,onStart,onResume,onRestart, onPause,onStop,onDestory.
- Activity与Fragment之间生命周期比较
- Activity的四种启动模式对比
- Activity状态保存与恢复:复写onSaveInstanceState和onRestoreInstanceState
- Fragment状态保存startActivityForResult是哪个类的方法,在什么情况下使用?总结起来就是:从哪里发起调用,最终就会走到哪里。
1.用getActivity方法发起调用,只有父Activity的onActivityResult会调用,Fragment中的onActivityResult不会被调用;
2.直接发起startActivityForResult调用,当前的Fragment的onActivityResult,和父Activity的onActivityResult都会调用;
3.用getParentFragment发起调用,则只有父Activity和父Fragment的onActivityResult会被调用,当前的Fragment的onActivityResult不会被调用。
这里2和3的前提是如果父activity中重写了onActivityResult,父Activity的onActivityResult中必须添加super.onActivityResult()。
- 如何实现Fragment的滑动:ViewPager
- fragment之间传递数据的方式?
- 通过所在Activity中的set, get 方法;
- 利用bundle 和setArguments进行参数传递;
- EventBus; EventBus原理
二、Service
1. Service 启动方法与生命周期:
1. startService启动类型的服务: onCreate()- >onStartCommand()->Service running--调用context.stopService() ->onDestroy() 。
2. bindService 绑定类型的服务: onCreate()->onBind()->Service running--调用>onUnbind() -> onDestroy()
2. Service与Activity之间通信的几种方式:
- 在startService 时,把数据通过Intent传递过去;
- bindservice时,实现ServiceConnection;
- 注册Callback的方式;
3.IntentService
一个继承自Service的抽象类,里面封装了Handler和HandlerThread,子线程运行。所有任务结束后能自动销毁。
4.service保活
- onStartCommand 中返回START_STICKY;
- 在onDestory中启动该服务;
- 同时开启两个进程和服务;
AIDL
- 使用方法;
- 客户端与服务端挂了怎么办?DeadObjectException,
客户端deadObject异常处理 :注册死亡代理DeathRecipient,当binder死亡后,系统会回调binderDied方法 。
服务端如何知道客户端挂了:客户端在注册时把客户端的binder传给服务端,并调用binder.linkToDeath注册死亡代理(在服务端处理),当客户端挂了时,服务端就知道了。
当binder断开连接后,系统会回调onServiceDisconnected,然后我们可以重连服务。
inout等参数作用:理解AIDL中的in,out,inout
三、ContentProvider
- ContentProvider的原理:ContentProvider原理分析_blueberry_mu的博客-CSDN博客_contentprovider原理 ,难点主要在获取ContentResolver的获取流程。
- ContentProvider、ContentResolver、ContentObserver 之间的关系:使用ContentResolver来获取ContentProvider提供的数据,同时注册ContentObserver监听Uri数据的变化
- ContentProvider 是如何实现数据共享的?
- getContentResolver:返回的ContentResolver是在ContextImpl 中创建,一个ApplicationContentResolver对象;
- 调用增删改查方法时,是调用acquireProvider(返回一个IContentProvider 对象)的增删改查方法;
- 调用ActivityManagerService.getContentProvider方法---startProcessLocked---ActivityThread.installProvider---ContentProvider.onCreate;
- ContentProvider的权限管理(解答:读写分离,权限控制-精确到表级,URL控制)
四、BroadcastReceiver
- 请描述一下广播BroadcastReceiver的理解,广播使用的方式和场景。
BroadcastReceiver.onReceive() 中不可以
开启新的线程来进行耗时的操作。在BroadcastReceiver.onReceive()方法收到广播,开启一个线程,接着它返回也就是执行完毕后,系统会认为BroadcastReceiver不在处于活动状态。因此不在需要起托管进程(除非其他应用程序组件处于活动状态,如Activity,Service)。因此系统可能随时终止进程来回收内存,并且这样会终止进程中运行的线程。- BroadcastReceiver,LocalBroadcastReceiver 区别:LocalBroadcastReceiver用于内部传递消息,更高效安全,只能动态注册。依托LocalBroadcastManager使用。 原理:借助一个静态单例类LocalBroadcastManager。静态保证了他一旦创建就基本上与application一样的生命周期。他持有 所有register到他里面的broadcast的引用。因此需要利用他发广播时,就可以立即拿到这个broadcast引用 调用 这个broadcast对象的onReceive方法。
- BroadcastReceiver与EventBus比较:广播资源消耗高、需要Context,能用于跨进程。EventBus调用灵活,不依赖Context;使用简单,Subscriber 即可。但逻辑性不是很好,适合统一进程。
五、一些View
六、Context问题
ApplicationContext和ActivityContext的区别:ApplicationContext 不应该用于界面相关的地方,ActivityContext 可能使得对象不能及时被释放,从而引发内存泄漏。
进程和 Application 的生命周期:
在大多数情况下,每个Android应用程序都在自己的Linux进程中运行。当需要运行某些代码时,将为应用程序创建此过程,并且该过程将一直运行,直到不再需要它为止,并且 系统需要回收其内存以供其他应用程序使用。
七、Handler
Handler实现原理
Handler机制和底层实现:handler通过sendMessage把消息发送到MessageQueue里面,enqueueMessage函数解析 参考如下:
boolean enqueueMessage(Message msg, long when) {
//这里处理的普通消息必须是包含Handler的,下面会提及一个同步屏障消息,它其中不包含Handler
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//存在已经消费过的标记,不在继续添加
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
//如果Queue已经退出,则将消息recycler
msg.recycle();
return false;
}
//标记使用状态
msg.markInUse();
//设置延迟时间
msg.when = when;
//mMessage是一个全局变量,代表MessageQueue的头节点
Message p = mMessages;
//头节点为空 或者 等待时间小于头节点 那么都放在队列的前端
if (p == null || when == 0 || when < p.when) {
//给msg的上一个节点赋值,这里将头节点设置为下一个,当前msg为头节点
msg.next = p;
//给头节点赋值
mMessages = msg;
} else {
Message prev;
for (;;) {
//比较时间,将消息按照时间进行排列
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
}
//将消息插入合适的位置
msg.next = p;
//这里也就是一个排队的逻辑
prev.next = msg;
}
}
return true;
}
原文链接:https://blog.csdn.net/wcy0312808/article/details/90295965
Looper中有个for循环不断调用queue.next读取消息(nativePollOnce),底层采用的是pipe/epoll机制,无消息时会释放CPU从而不会导致阻塞。 最终调用Message.target.dispatchMessage ,里面具体实现如下:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
handler.post(...) //第一优先级:执行post所传递的Runnable参数.run()
new Handler(callback) //第二优先级:执行构造方法传来的callback匿名内部类handleMessage(msg)
handlerMessage(msg)//第三优先级:调用Handler的handlerMessage()方法
- Handler、Thread和HandlerThread的差别
- handler发消息给子线程,looper怎么启动? 调用Loop.prepare() 与Loop.loop()。
- 关于Handler,在任何地方new Handler 都是什么线程下? - 不传参数时,在什么线程下new,就和什么线程绑定。在子线程new时,要调用Loop.prepare();Loop.loop()