ContentProvider、ContentResolver、ContentObserver之间的关系
简单一句话来描述就是:使用ContentResolver来获取ContentProvider提供的数据,同时注册ContentObserver监听Uri数据的变化
描述一次网络请求过程(三次握手,四次挥手)
bitmap相关(Bitmap内存计算等)
Looper的架构
Handler里面有一个重要的成员变量Looper,Looper里面维护了一个MessageQueue(消息队列),当我们使用handler.post或者sendMessage相关的方法都是将消息Message放入到消息队列中。每一个线程都将拥有一个自己的Looper,顾名思义ThreadLocal是和线程绑定的。当我们有一个线程A使用sThreadLocal.set(Looper a),线程B使用sThreadLocal.set(Looper b)的方式存储,如果我们在线程B中使用sThreadLocal.get()将会得到Looper b的实例。所以我们每个线程可以拥有独立的Looper,Looper里面维护了一个消息队列,也就是每一个线程维护自己的消息队列。
当在主线程中时,在你的应用启动时系统便给我们创建了一个MainLooper存入了sThreadLocal中,所以平时我们使用Handler时,如果是在主线程中创建的,我们是不需再去创建一个Looper给Handler的,因为系统已经做了,所以当我们new Handler时,系统便将之前存入的Looper通过sThreadLoca中get出来,然后再去从对应的消息队列中读取执行。
而当我们在子线程中创建Handler时,如果直接new Handler运行时肯定会报错的,提示我们必须先调用Looper.prepare()方法,为什么呢?因为我们没有创建子线程对应的Looper放入sThreadLocal当中,而prepare方法就是new了一个Looper的实例通过
通过Handler有很多种发送消息的方式:
post(Runable run)
postDelayed
sendEmptyMessage()
…等等
其实无论是通过post的方式或者send的方式,最后都是通过
public final boolean sendMessageDelayed(Message msg, long delayMillis)
我们使用post传入的Runnable实例,也是通过:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
通过上面的方法,将Runnable的实例转换为Message的实例,然后调用通用的方法发送到消息队列中,最终会通过下面的方式放入队列:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在子线程中使用handler就意味着handler的实例是在子线程中去创建的。
Looper.prepare();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d(TAG," mHandler is coming");
handler_main.sendEmptyMessage(1);
}
};
mHandler.sendEmptyMessage(1);
Looper.loop();
如果在调用之前必须调用Looper.prepare()方法,这个是在当前线程中创建一个looper出来,如果是普通的应用场景可以直接使用HandlerThread,其中是带有Looper的。
第二点值得注意的就是,Looper.loop()这个方法是无限循环的,所以在Looper.loop()后边的程序代码块是无法执行到的。loop()方法的主要作用是一直不断的通过queue.next()方法来读取来自messagequeue中的msg,这个方法是block的状态,如果queue中没有消息的话会一直阻塞在这里。
关于Looper还有一个方法,当我们需要获取Looper实例时,可以直接在对应线程调用Looper looper = Looper.myLooper();来获取,默认情况下,系统只会给MainT
hread分配一个looper。
Callable、Future和FutureTask
Android系统服务 —— WMS与AMS
Popupwindow与Dialog的区别
(1)PopupWindow在显示之前必须设置宽高,Dialog无此限制
(2)PopupWindow默认不会响应物理键盘的back,除非显示设置了popup.setFocusable(true);而在点击back的时候,Dialog会消失
(3)PopupWindow不会给页面其他部分添加蒙层,而Dialog会
(4)PopupWindow没有标题,Dialog默认有标题,可以通过dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);取消标题
(5)二者显示的时候都要设置Gravity。如果不设置,Dialog默认是Gravity.CENTER
(6)二者都有默认的背景,都可以通过setBackGroundDrawable(new ColorDrawable(android.R.color.transparent));去掉
本质差别:
AlterDialog是非阻塞式对话框:AlterDialog弹出时,后台还可以做事情
PopupWindow是阻塞式对话框:PopupWindow弹出时,程序会等待,在PopupWindow退出前,程序一直等待,只有在调用dismiss方法后,PopupWindow退出,程序才会向下执行。
差别表现:
AlterDialog弹出时,背景是黑色的,但是当我们点击背景,AlterDialog会消失,证明程序不仅响应AlterDialog的操作,还响应其他操作,其他程序没有被阻塞,说明AlterDialog是非阻塞式对话框,PopupWindow弹出时,背景没有变化,但是当我们点击背景的时候,程序没有响应,只允许我们操作PopupWindow,其他操作被阻塞。
java对象生命周期
-
创建阶段(Created)
-
应用阶段(In Use)
-
不可见阶段(Invisible)
-
不可达阶段(Unreachable)
-
收集阶段(Collected)
-
终结阶段(Finalized)
-
对象空间重分配阶段(De-allocated)