Skip to content Skip to footer

《Android进阶之光》读书笔记

文章目录

第1章 Android新特性1.1. Android 5.0 新特性1.2. RecyclerView1.1.4. 3种Notification1.1.5. Toolbar与Palette1.1.6. Palette

1.2. Android6.0 新特性1.2.2. 运行时权限机制

1.3. Android7.0 新特性

第2章 Material Design2.2.Design Support Library 常用控件详解

第3章 View体系与自定义View3.1.View和ViewGroup3.2.坐标系3.3.View滑动3.4.属性动画3.6.View事件分发机制3.6.1.源码解析Activity的构成3.6.2.源码解析View的事件分发机制

View的工作流程3.7.3 View的measure流程

3.7.4.View的layout流程3.7.5 View的 draw 流程3.8.自定义View3.8.4.自定义ViewGroup

第4章 多线程编程4.1.线程基础4.1.1 进程与线程4.1.2.线程的状态4.1.3.创建线程4.1.4.理解中断4.4.5.安全终止线程

4.2.同步4.2.1.重入锁与条件对象4.2.3.同步代码块4.2.4.volatile

4.3.阻塞队列4.3.2.Java中的阻塞队列

4.4.线程池4.4.1 ThreaPoolExecutor4.4.2.线程池的处理流程和原理4.4.3.线程池种类

4.5.AsyncTask的原理

第5章 网络编程与网络框架5.1.网络分层5.2.三次握手5.3.HTTP协议原理5.3.2.HTTP请求报文5.3.3.响应报文

5.4.HttpClient与HttpURLConnection5.6.解析OkHttp5.7.解析Retrofit

第6章 设计模式第7章 事件总线第8章 函数响应式编程第9章 注解与依赖注入框架9.2.依赖注入原理ButterKnife

第10章 应用框架设计第11章 系统架构与MediaPlay框架

第1章 Android新特性

1.1. Android 5.0 新特性

MD 设计风格、支持多种设备、全新的通知中心、Overview、设备识别解锁、RecyclerView、CardView

1.2. RecyclerView

分割线:ItemDecoration

1.1.4. 3种Notification

普通Notification折叠式Notification(RemoteView)

notication.bigContentView = remoteViews

悬挂式Notification

builder.setFullScreenIntent()

Notification 显示等级

1.VISIBILITY_PUBLIC

2.PRIVATE

3.SECRET 在pin、password等安全锁和没有锁的情况下才显示

4.build.setVisibility()

1.1.5. Toolbar与Palette

步骤

1.style 去掉 Actionbar

2.Toolbar 布局

menu 覆写 onCreateOptionsMenu

1.1.6. Palette

提取颜色

Paletter.from(bitmap).generate(new Palette.PaletteAsyncListener())

1.2. Android6.0 新特性

应用权限指纹支持Doze电量管理

1.2.2. 运行时权限机制

普通权限和危险权限

1.ActivityCompat.checkSelfPermission

2.onRequestPermissionsResult

权限框架

1.PermissionsDispatcher

1.3. Android7.0 新特性

多窗口Data Server 流量保护机制Java 8支持后台省电禁用多窗口:android:resizeableActivity=“false”小于24:android:screenOrientation=“potraint”

第2章 Material Design

质感设计

2.2.Design Support Library 常用控件详解

Snackbar 使用TextInputLayout

1.设置错误

1.1.setErrorEnabled(true)

1.2.setError("错误信息")

FloatingActionButtonTabLayoutNavigationViewCoordinatorLayout

app:layout_scrollFalgs="scrill|enterAlways"

CollapsingToolbarLayout自定义Behavior

1. 自定义View监听CoordinatorLayout里滑动

2. 定义View监听另一个View的状态变化,例如View的大小、位置和显示状态等

第3章 View体系与自定义View

3.1.View和ViewGroup

所有控件的基类ViewGroup 自继承 View

3.2.坐标系

Android 坐标系:左上角的顶点作为Android坐标系的原点—getRawX()View坐标系

MotionEvent

1.getX--获取点击事件距离控件左边的距离,视图坐标。

2.getRawX--获取点击事件距离整个屏幕顶边的距离,绝对坐标。

3.3.View滑动

layout()

//跟随手指移动的View

public class CustomerView extends View {

private int lastX;

private int lastY;

public CustomerView(Context context) {

this(context, null);

}

public CustomerView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public CustomerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

int x = (int) event.getX();

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

lastX = x;

lastY = y;

break;

case MotionEvent.ACTION_MOVE:

int offsetX = x - lastX;

int offsetY = y - lastY;

layout(getLeft() + offsetX,

getTop() + offsetY,

getRight() + offsetX,

getBottom() + offsetY);

break;

default:

break;

}

return true;

}

}

offsetLeftAndRight()与offsetTopAndBottom()

@Override

public boolean onTouchEvent(MotionEvent event) {

int x = (int) event.getX();

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

lastX = x;

lastY = y;

break;

case MotionEvent.ACTION_MOVE:

int offsetX = x - lastX;

int offsetY = y - lastY;

offsetLeftAndRight(offsetX);

offsetTopAndBottom(offsetY);

break;

default:

break;

}

return true;

}

}

LayoutParams()

1. final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();

params.leftMargin = getLeft() + offsetX();

...

setLayoutParams(params);

2. (ViewGroup.MarginLayoutParams)getLayoutParams()

params.leftMargin = getLeft() + offsetX();

动画

//1.

android:duration="1000"

android:fillAfter="true">

android:fromXDelta="0"

android:toXDelta="300"/>

this.setAnimation(AnimationUtils.loadAnimation(context,R.anim.translate));

//2.

ObjectAnimator.ofFloat(this, "translationX", 0, 300).setDuration(3000).start();

scrollTo和scrollBy()

1.scrollTo:移动到一个具体坐标点

2.scrollBy:移动增量dx、dy

3.((View)getParent).scrollBy(-offsetX,offsetY)

4.注意:效果是瞬间完成的。

Scroller

1.并不能实现View滑动,要配合View的computeScroll()

2.在computeScroll()中不断让View进行重绘,计算滑动持续时间,算出View滑动位置,调用scrollTo()方法进行滑动。

3.4.属性动画

帧动画:View动画(视图动画):AlphaAnimation、Rotate、Translate、Scale–>不具备交互性ObjectAnimator

0.ObjectAnimator.ofFloat(view,"translationX",200)

1.translationX、translationY

2.rotaiton、rotationX、rotationY->旋转

3.PrivotX、PrivotY->旋转 缩放

4.alpha

5.x、y:View对象最终位置

ValueAnimator

1.不提供动画效果,数值发生器

2.ValueAnimator的AnimatiorUpdateListener

3.动画监听

3.1.animator.addListener(new Animator.AnimatorListener)(star、repeat、end、cancel)

3.2.animator.addListener(new Animator.AnimatorListenerAdapter(){

end // 只监听end

})

组合动画–AnimatorSet

1.play()

2.after(Animator):之后

3.after(Long):延迟

4.before(Animator):之前

5.with(Animator):同时

6.set.play(a1).with(a2).after(3)

7.set.playTogether(a1,a2) 同时执行

组合动画–PropertyValuesHolder

1.PropertyValuesHolder:多个动画一起执行

2.ObjectAnimator.ofPropertyValuesHolder(Object,PropertyValuesHolder...)

3.

PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);

ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(holder);

animator.setDuration(1000).start();

7.在xml中使用属性动画

android:duration="3000"

android:propertyName="scaleX"

android:valueFrom="1.0"

android:valueTo="1.0"

android:valueType="floatType"

>

Animator animator = AnimatorInflater.loadAnimator(this.getContext(), R.animator.demo);

animator.setTarget(this);

animator.start();

3.6.View事件分发机制

3.6.1.源码解析Activity的构成

1.setContentView()->getWindow()(Window).setContentView()->getWindow()返回一个mWindow,实际在Activity的attach中创建一个PhoneWindow对象,PhonwWindow会创建DecorView作为窗口的根View,DecorView包含一个Titlle,一个ContentView

2.Activity->PhoneWindow->DecorView(TitleView+ContentView)

3.6.2.源码解析View的事件分发机制

1.把事件封装成MotionViewEvent,传递给View的层级

2.三个重要方法:dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouchEvent(消费)

3.OnTouchListener中的OnTouch()方法高于onTouchEvent(Event)

1.View事件分发机制

1.

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

···

//1.判断是否是Down事件 是一个新的事件序列

if (actionMasked == MotionEvent.ACTION_DOWN) {

cancelAndClearTouchTargets(ev);

//mFirstTouchTarget 置空

resetTouchState();

}

final boolean intercepted;

//View没有拦截当前事件 交由子View处理

if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {

//FLAG_DISALLOW_INTERCEPT 禁止ViewGroup拦截Down之外事件 通过requestDisallowInterceptTouchEvent

final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;

if (!disallowIntercept) {

intercepted = onInterceptTouchEvent(ev);

ev.setAction(action);

} else {

intercepted = false;

}

} else {//ViewGroup 拦截了当前事件

intercepted = true;

}

// onInterceptTouchEvent 不会每次都调用

2.

if (newTouchTarget == null && childrenCount != 0) {

···

final View[] children = mChildren;

//遍历ViewGroup子元素,如果子元素能够处理事件,交由子元素处理

for (int i = childrenCount - 1; i >= 0; i--) {

final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i,customOrder);

final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);

if (!canViewReceivePointerEvents(child)

|| !isTransformedTouchPointInView(x, y, child, null)) {

//判断触摸点位置是否在子View上,是否播放动画,不符合继续遍历

ev.setTargetAccessibilityFocus(false);

continue;

}

newTouchTarget = getTouchTarget(child);

if (newTouchTarget != null) {

newTouchTarget.pointerIdBits |= idBitsToAssign;

break;

}

resetCancelNextUpFlag(child);

//如果有子View,则调用子View的dispathTouchEvent,如果没有 直接super View中的dispatchOnTouchEvent(如果onTouchListener不为null,并且onTouch为true,事件被消费,)

if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {

mLastTouchDownTime = ev.getDownTime();

1.View中的onTouchEvent()

只要View的CLICKABLE和LONG_CLICKABLE有一个为true,onTouchEvent消费这个事件

点击事件分发的传递规则

public boolean dispatchTouchEvent(MotionEvent ev){

boolean resule = false;

if(onInterceptTouchEvent(ev)) {

resule = super.onTouchEvent(ev);

}else{

result = child.dispatchTouchEvent(ev);

}

return result;

}

1.自上而下分发,为true拦截,false不拦截

2.自下而上传递,底层View的onTouchEvent 为 false->往上传递

2.具体见下图

View的工作流程

指的是measure、layout、drawDecorView 加载到Window中

1.Activity的startActivity

2.ActivityThread的handleLuanchActivity

3.handlLuanchActivity中performLuanchActivity来创建Activity(调用onCreate方法,完成DecorView创建)

4.handlLuanchActivity中handleResumeActivity(onResume)

5.handlLuanchActivity中得到DecorView和WM(接口继承ViewManager)

->WM中的addView方法

->(WindowManagerImpl)

->WindowManagerImpl中的addView

->WindowManagerGlobal中的addView方法

->创建ViewRootImpl,setView将DecorView传进去

3.ViewRootImpl的performTraversals

1.ViewTree开始View的工作流程

2.performMeasure、performLayout、performDraw

理解MeasureSpec

1.View的内部类,View规格尺寸(宽、高)

2.32位int值,高2位代表SpecMode(测量模式),低30位代表SpecSize(测量大小)

3.MeasureSpec 受自身LayoutParams和父容器的MeasureSpec共同影响

4.DecorView中的MeasureSpec根据自身的LayoutParams和窗口大小决定的

模式名称简介UNSPECIFIED未指定模式想要多大就多大AT_MOST最大模式wrap_contentEXACTILY精确模式match_parent、具体值

3.7.3 View的measure流程

measure 用来测量View的宽高,分为View的measure流程和ViewGroup的measure流程,ViewGroup的measure流程(完成自己的测量、遍历调用子元素的measure方法)View的measure方法

1. onMeasure -> setMeasureDimension(测量宽高)、getDefaultSize(getSuggestedMinimumWidth)

2. getDefaultSize 中 AT_MOST 和 EXACTLY (wrap_content 和 match_parent)效果一样 所以继承 View 要重写 onMeasure 方法

3. getSuggestedMinimumWidth->如果View没有设置背景,返回mMinWidth,如果设置了,返回mMinWidth和Drawable最小宽度之间的最大值

ViewGroup的measure方法

1. 不仅测量自身,还要遍历调用子view的measure方法

2. 没有定义onMeasure,定义了measureChildren

3. measureChildren -> measureChild() -> child.getLayoutParams获取LayoutParents属性,获取MeasureSpec并调用

子元素measure方法测量->getChildMeasureSpec

4. 定义了getChildMeasureSpec中如果父容器 MeasureSpec为AT_MOST,子元素的LayoutParams属性为WRAP_CONTENT->子元素也是AT_MOST,SpecSize为父容器SpecSize - padding,和子元素设置LayoutParams为MATCH_PARENT 效果一样,所以需要在LayoutParams属性为WRAP_CONTENT 指定默认 宽高

3.7.4.View的layout流程

1. 确定元素的位置,ViewGroup中的layout用来确定子元素位置,View中layout 用来确定自身位置

2. layout(l,t,t,b)->setFrame->onLayout()(View 和 ViewGroup 中均没有实现onLayout方法)

3.7.5 View的 draw 流程

1. 如果需要,绘制背景->drawBackgroup

2. 保存当前canvas层

3. 绘制view的内容-> onDraw(canvas)(空实现)

4. 绘制子view -> dispatchDraw(canvas)(空实现) ViewGroup->遍历调用 drawChild->调用View的draw方法,判断是否有缓存,没有正常绘制,有利用缓存显示

5. 如果需要,绘制view的褪色边缘,类似阴影效果

6. 绘制装饰,比如滚动条 -> onDrawForegroup-> 绘制ScrollBar以及其他装饰,并将它们绘制在视图内容上层

3.8.自定义View

自定义View->继承系统View(TextView)、继承View(注意padding、wrap_content)自定义ViewGroup->继承系统ViewGroup(LinearLayout)、继承ViewGroup自定义组合控件

3.8.4.自定义ViewGroup

VelocityTracker 测量滑动速度

public class HorizontalView extends ViewGroup {

private int lastX;

private int lastY;

private int lastInterceptX;

private int lastInterceptY;

private int currentIndex = 0; //当前子元素

private int childWidth = 0;

private Scroller mScroller;

private VelocityTracker mTracker; //滑动速度

public HorizontalView(Context context) {

this(context, null);

}

public HorizontalView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public HorizontalView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init() {

mScroller = new Scroller(getContext());

mTracker = VelocityTracker.obtain();

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

int childCount = getChildCount();

int left = 0;

View child;

for (int i = 0; i < childCount; i++) {

child = getChildAt(i);

if (child.getVisibility() != View.GONE) {

int width = child.getMeasuredWidth();

childWidth = width;

child.layout(left, 0, left + width, child.getMeasuredHeight());

left += width;

}

}

}

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

boolean intercept = false;

int x = (int) event.getX();

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

intercept = false;

//还在执行滚动

if (!mScroller.isFinished()) {

mScroller.abortAnimation();

}

break;

case MotionEvent.ACTION_MOVE:

int dx = x - lastInterceptX;

int dy = y - lastInterceptY;

if (Math.abs(dx) - Math.abs(dy) > 0) {

intercept = true;

} else {

intercept = false;

}

break;

case MotionEvent.ACTION_UP:

intercept = false;

break;

default:

break;

}

lastX = x;

lastY = y;

lastInterceptX = x;

lastInterceptY = y;

return intercept;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

int x = (int) event.getX();

int y = (int) event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//还在执行滚动

if (!mScroller.isFinished()) {

mScroller.abortAnimation();

}

break;

case MotionEvent.ACTION_MOVE:

int dx = x - lastX;

scrollBy(-dx, 0);

break;

case MotionEvent.ACTION_UP:

int distance = getScrollX() - currentIndex * childWidth;

if (Math.abs(distance) > childWidth / 2) {

if (distance > 0) {

currentIndex++;

} else {

currentIndex--;

}

} else {

mTracker.computeCurrentVelocity(1000); //获取水平速度

float xV = mTracker.getXVelocity();

if (Math.abs(xV) > 50) { //水平速度大于 50

if (xV > 0) {

currentIndex--;

} else {

currentIndex++;

}

}

}

currentIndex = currentIndex < 0 ? 0 : currentIndex > getChildCount() - 1 ? getChildCount() - 1 : currentIndex;

smoothScrollTo(currentIndex * childWidth, 0);

mTracker.clear();

break;

default:

break;

}

lastX = x;

lastY = y;

return true;

}

@Override

public void computeScroll() {

super.computeScroll();

if (mScroller.computeScrollOffset()) {

scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

postInvalidate();

}

}

//弹性滑动指定位置

public void smoothScrollTo(int dx, int dy) {

mScroller.startScroll(getScrollX(), getScrollY(), dx - getScrollX(), dy - getScrollY(), 1000);

invalidate();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSize = MeasureSpec.getSize(heightMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

measureChildren(widthMeasureSpec, heightMeasureSpec);

//如果没有子元素,宽高设置 0

if (getChildCount() == 0) {

setMeasuredDimension(0, 0);

} else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {

View childOne = getChildAt(0);

int childWidth = childOne.getMeasuredWidth();

int childHeight = childOne.getMeasuredHeight();

setMeasuredDimension(childWidth * getChildCount(), childHeight);

//如果宽度AT_MOST,则宽度为所有子元素宽度的和

} else if (widthMode == MeasureSpec.AT_MOST) {

int childWidth = getChildAt(0).getMeasuredWidth();

setMeasuredDimension(childWidth * getChildCount(), heightSize);

//高度AT_MOST 高度为第一个元素的高度

} else if (heightMode == MeasureSpec.AT_MOST) {

int childHeight = getChildAt(0).getMeasuredHeight();

setMeasuredDimension(widthSize, childHeight);

}

}

}

第4章 多线程编程

4.1.线程基础

4.1.1 进程与线程

进程:系统进行资源分配和调度的基本单位线程:操作系统调度的最小单元

4.1.2.线程的状态

1. New:新建

2. Runnbale:可运行

3. Blocked:阻塞

4. Waiting:等待、wait 方法

5. Timed waiting:超时等待

6. Terminated:终止

4.1.3.创建线程

继承Thread,重写run()实现Runnbale,实现run()实现Callable,重写call()–>提供返回值、能够抛出异常

public class DemoCallable implements Callable {

@Override

public String call() throws Exception {

return "Hello";

}

private void test() {

DemoCallable callable = new DemoCallable();

ExecutorService service = Executors.newSingleThreadExecutor();

Future future = service.submit(callable);

try {

System.out.println(future.get()); //阻塞,直到返回结果

} catch (Exception e) {

e.printStackTrace();

}

}

4.1.4.理解中断

interrupt 用来请求线程Thead.currentThread().isInterrupted() 判断线程是否中断注意不要捕获InterruptException 不做处理

1.Thread.currentThread.interrupt()来设置中断状态

2.直接抛出异常

4.4.5.安全终止线程

使用 interrupt()设置标志位

4.2.同步

4.2.1.重入锁与条件对象

ReentrantLock条件对象:Condition,一把锁对象拥有多个相关的条件对象。

1.condition.await() 阻塞当前线程,并放弃锁

2.signalAll、singnal

4.2.3.同步代码块

synchronized(obj)

4.2.4.volatile

线程A 本地内存 主内存 本地内存 线程B

原子序、有序性、可见性作用:防止指令重排(保证有序性)、修改对其他线程可见,但是不保证原子性使用:状态标志、双重检查模式(DCL)

4.3.阻塞队列

阻塞队列常用于生产者(往队列里头添加元素)和消费者场景(队列拿元素)常见场景:1. 队列没有数据,消费者自动阻塞;2.队列填满数据,生产者自动阻塞。

4.3.2.Java中的阻塞队列

ArrayBlockingQueue:数组组成的有界阻塞队列、FIFO、不保证线程公平访问队列LinkedBlockingQueue:链表组成有界阻塞队列、FIFO、维持一个数据缓冲队列PriorityBlockingQueue:支持优先排序的无界、默认升序DelayQueue:支持延迟获取元素的无界SynchronousQueue:不存储元素LinkedTransferQueue:链表组成无界LinkedBlockDeque:链表组成的双向

public class Blocking {

private int queueSize = 20;

private ArrayBlockingQueue mQueue = new ArrayBlockingQueue<>(queueSize);

public static void main(String[] args) {

Blocking blocking = new Blocking();

Consumer consumer = blocking.new Consumer();

Producer producer = blocking.new Producer();

producer.start();

consumer.start();

}

class Consumer extends Thread {

@Override

public void run() {

while (true) {

try {

mQueue.take();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

class Producer extends Thread {

@Override

public void run() {

while (true) {

try {

mQueue.put(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

4.4.线程池

4.4.1 ThreaPoolExecutor

ThreadPoolExecutor(int corePoolSize, //核心线程数

int maximunPoolsize, //允许创建最大线程数

long keepAliveTime, //非线程闲置超时时间,设置allowCoreThreadTimeout也会作用在核心线程上

TimeUnit unit, // keepAliveTime 时间单位

BlockingQueue workQueue, //任务队列

ThreadFactory threadFactory, //线程工厂

RejectedExecutionHandler handler //饱和策略

)

RejectedExecutionHandler:

1.AbordPolicy:无法处理新任务

2.CallerRunsPolicy:用调用者线程处理新任务

3.DiscardPolicy:不能执行,删除

4.DiscardOldestPolicy:丢弃最近任务,并执行当前任务

4.4.2.线程池的处理流程和原理

提交任务,判断线程数是否达到核心线程数,没达到,就创建核心线程处理,达到,执行下一步判断任务队列,没满,加入任务到任务队列,满了,执行下一步。判断线程是够达到最大线程线程数,没有,创建非核心线程处理,达到了,执行饱和策略,默认抛出RejectedExecutionException

4.4.3.线程池种类

FixedThreadPool:可重用固定线程数,只有核心线程CacheThreadPool:没有核心线程SingleThreadExecutor:单个工作线程ScheduledThreadPool:定时和周期、DelayedWorkQueue

4.5.AsyncTask的原理

泛型参数核心方法3.07.0Params、Progress、ResultonPreExecutor、doInBackgroup、onProgressUpdate、onPostExecute核心线程5,最大线程128,时间1s,LinkedBlockingQueue、容量10,最多只能执行138个任务,139会执行饱和策略、并行执行串行执行、SerialExecutor+THREAD_POOL_EXECUTOR(线程池)+Handler 、想要并行(task.executeOnExecutor)

第5章 网络编程与网络框架

5.1.网络分层

应用层(HTTP、FTP)、传输层(TCP、UDP)、网络层、数据链路层、物理层

5.2.三次握手

TCP保证传输可靠性

第一次握手第二次握手第三次握手建立连接,客户端发送连接请求报文段,SYN seq = x服务器收到客户端SYN,设置 SYN seq=y,ACK = x +1客户端收到服务端SYN+ACK

第一次

第一次握手:建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。 [3]

第二次

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。 [3]

第三次

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

四次挥手

(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。

(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。

(3) 服务器关闭客户端的连接,发送一个FIN给客户端。

(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

5.3.HTTP协议原理

应用层的面向对象协议。HTTP1.1、SPDY协议特点:C/S、灵活、无状态

5.3.2.HTTP请求报文

请求行、请求报头、空行、请求数据GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS

5.3.3.响应报文

状态行、响应报头、空行、响应正文100(收到请求)、200(请求成功)、300(重定向)、400(客户端错误)、500(服务器错误)请求报头:Host、User-Agent、Accept、Accept-Encoding、Accept-Language、Transfer-Encoding响应报头:Location、Server实体报头:Content-Type、Content-Length、Content-Launguage、Content-Length、Expires、Last-Modified

5.4.HttpClient与HttpURLConnection

5.6.解析OkHttp

OkHttpClient、Request、CallOkHttpClient.newCall(request)->RealCall->enqueue->Dispatcher(最终请求都是由此完成-enqueue)Dispatcher:主要控制并发的请求拦截器->发送请求->HttpEngine->缓存(有:缓存系统,无:网络请求)->ResponseOkhttp的复用连接池,支持5个并发socket连接,keepALive时间为5分钟自动回收连接:引用计数是否为0来实现自动回收连接。连接池复用核心:Deque来存储连接,通过put、get等对Deque进行操作,判断连接对象StreamAllocation来进行自动回收连接

5.7.解析Retrofit

基于OkHttp实现的create、动态代理

第6章 设计模式

6原则:单一、开放封闭(扩展开发、修改关闭)、里式替换(使用基类地方能够使用子类)、依赖倒置(高层不依赖低层、抽象不依赖细节)、迪米特(最少知识)、接口隔离(一个类对另一个类依赖建立在最小接口上)创建型设计模式、结构型设计模式、行为型设计模式

第7章 事件总线

第8章 函数响应式编程

第9章 注解与依赖注入框架

注解:是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取、并执行相应的处理。分类:标准注解(Override、Deprecated、SuppressWarnings、SafeVarargs)、元注解(Taget、Inherited-注解可以被继承、Documented-文档、Retention-保留策略、Repeatable-多次使用)运行时注解:反射(getDeclaredMethods、getAnnotation)编译时注解:AbstractProcessor(AutoService)

9.2.依赖注入原理

IOC:控制反转依赖注入(DI):IOC容器在运行期间,动态将某种依赖注入到对象中。构造方法注入、Setter方法注入、接口注入

ButterKnife

ButterKnifeProcessor 注解处理器 略

第10章 应用框架设计

MVC 模式:模型-视图-控制器MVP:Model、Presenter、ViewMVVM:Model、ViewModel、View

第11章 系统架构与MediaPlay框架

应用层、应用框架层、系统运行库层(C/C++、Android运行时库)、硬件抽象层(HAL)、Linux内核层http://androidxref.com 访问系统源码Source Insights

Copyright © 2088 我的世界杯_瑞奇马丁世界杯主题曲 - msdc8.com All Rights Reserved.
友情链接