求导

  • content
    {:toc}

1.自定义view,必经之路

为什么要自定义view;

andorid系统内置的view无法实现我们的需求

处于性能考虑

自定义view某种情况下也要实现onLayout

​ 自绘和组合: 不知道怎么下手

数学功底

TextView是最难的view,内置的
StaticLayout

树形结构,window是虚拟的概念,是为了管理view来虚拟出来的

android的角度是顺时针的,

motionEvent里面有getX getRawX

getTop

ViewRoot,是个管理view的,

WindowManagerGlobal -> 里面创建ViewRootImpl (setView)

ViewRoot 中

requestLayout

performTraversals -> 计算host.measure host.layout host.draw()

addDisplay()

如何绘制wrap_content,绘制一个好的view树上

为了自己适应屏幕,measure,就是把各种尺寸得到一个具体像素,来绘制到屏幕上面来,如果绘制一个自定义树。

UNSPECIFIED: 这个多次measure来确定子布局的位置

EXACTLY

MeasureSpecs:避免过多的内存分配 ;MeasureSpec 是View的一个内部类
viewGroup#getChildMeasureSpec;

Measure这个过程会多次测量的

DecorView是根据屏幕大小来决定的

LayoutParams -》 是在LayoutInflater里面用到;自定义view generateLayoutParams

MarginLayoutParams 支持margin参数

自定义LayoutParams

getRootMeaurse -> performMeasure -> mView.measure() -> onMeasure()

除了UNSPACE都是用父类的那个测量宽度了

getMeaureWidth 和 getWidth 的区别:通常情况下是相同的

//frameLayout的规则代码

Math.max(0, specSize- padding) 可以绘制的剩余空间

measureChildWidthMargins

contentView 在一个线性布局里面,因为还有titlebar在上面

线性模具 resolveSizeAndState

自定义attrs也可以通过@bindingAdapter的方式

getWidth()和getMesureWidth()讲了嘛

SurfaceFling可以进行优化性能

启航 自定义View系列也不错

DecorView跟刘海屏有什么关系吗

从外往内递归,然后从内往外返回宽高

父如果自适应,那父的大小就是由子决定的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
SystemServer # startOtherServices 

wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager()); //这里直接new了一个phoneWindowManager

//...中间是启动activity的过程,直接跳过了

activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);

activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);


activity#attatch {
mWindow = new PhoneWindow(this, window, activityConfigCallback);
//把windowmanager设置进去了
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}

//这个winodow实际是PhoneWindow对象
Window#setWindowManager {
//创建了WindowManagerImpl,并且传进了 PhoneWindow对象,这里和service不一样的地方,所以可以显示对话框
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

然后跑到 ActivityThread#handleResumeActivity 进行了addView操作,因为onCreate的时候界面还没有显示出来
ActivityThread#handleResumeActivity {
//进行了addView
//这个就是获取了activity#attach获取的创建好的PhoneWindow的mWindowManager = mWindow.getWindowManager();
//这里用了 依赖倒置原则,vm其实本质是个WindowManagerImpl
ViewManager wm = a.getWindowManager();
wm.addView(decor, l);
}

然后接下来就
WindowManagerImpl # addView -》 global # addView
-》 ViewRootImpl # addView ...


~~//这里断了,不知道怎么调到 WindowManagerImpl # addView -》 global # addView~~~

activityManagerService 怎么socket通知Zygote创建进程的,这个socket在哪里发送的

最近看源码发现:怎么保护线程不死

ZygoteInit-> runSelectLoop方法里面while(true) -> socket#accept来进行阻塞

要么就是用Looper.prepare() -> Looper.loop() 这两个组合来进行维护这个线程不被释放

SystemServer;ActivityThread

我觉得吧,如果要到自己线程进行干事情的话,肯定是使用Looper这个组合。

​ ZygoteInit是通过sokect这种通信机制来进行等待AMS的请求 创建一个新的进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
zygoteInit# main {
forkSystemServer {

}
runSelectLoop {
//这个方法有等待,等待AMS的socket信号
acceptCommandPeer()
}
}


AMS # startProcessLocked
AMS # startProcessLocked(参数多)
AMS # startProcess {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}

马尔科夫模型

和算法相关的。

时间复杂度,空间复杂度

知道多少种算法 【深度优先遍历,广度优先遍历】

,回溯法,分治算法,贪心算法,动态规划

一个问题怎么想到用动态规划

问题得到问题规模增大导致的变化

递推式–状态转移方程

结合侓,,每天学一点算法,挺有意思的

朴素算法。逆波兰表达式,栈的典型应用,(编译原理)可能会用到

zero老师有没有管理经验

1.ViewGroup开始测量自己的尺寸

​ 1.尺寸值,200dp, match_parent,wrap_content

2.为每个子view计算测量的限制信息

3.把上一步确定的限制信息,传递给每个子view

​ 树形递归过程,子view调取自己的measure过程

4.viewGroup 获取每个子view测量的尺寸,wrap_content
5.ViewGroup根据自身的情况计算自己的尺寸

6.保存自身的尺寸

类图+时序图 ; 多动手

getWidth 和 getLayoutParams().width的区别:
getLayoutParams()返回的是xml布局里面设置的。getLayoutParams().width返回的是xml里面android:width的值。是在onMeasure之前的值。
getwidth返回的是onMeasure之后的值。

18670301864

Wrap_content怎么确定控件的高度和宽度的,

绘制完了才有的getHeight的值

measure之后,wrap_content,match_parent都有值了

performLayout -> decroVIew (View的layout).layout -> setFrame

view里面尽然有onLayout

onLayout:基本都是if else 加坐标计算

​ 根据规则确定子view的位置

​ 流程:

​ 1.遍历子view,for

​ 2.确定自己的规则

​ 3.子View的测量尺寸 l ,t, b,r left,top,bottom,right

​ 4.left,top,bottom,right

​ 5.child.layout

如何去阅读源码

1带着问题去看:找到什么东西

2点到为止:不要太在意细节

3看方法,方法名,返回值,参数,

问题: 控件的wrap_content,match_patent怎么确定的

控件在onLayout的时候为什么不用getHeight/getWidth而是用getMeasureHeight/getMeasureWidth,

layoutParams getwith, 和控件的getWidth的区别-》layoutParams getwith相当于xml布局里头的layout_width
而getWidth是 mRight - mLeft,

1.时间复杂度,

n 表示数据规则

O(f(n)) 表示运行算法所需要

二分查找法 O(logn)

寻找数组 O(n)

细节上的优化

归并排序 算法时间复杂度 O(nlogn)

O(n^2 + nlogn) n的规模是一样的情况下就是 O(n^2)

快速排序算法,可能会退化成O(n^2) 平均情况是 nlogn

![image-20190615102246363](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615102246363.png)

多开一个辅助的数组 O(n)

多开一个辅助的二维数组:O(n)

多开一个常量O(1)

递归调用是有空间代价的

Assert(n >= 0)

![image-20190615102827840](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615102827840.png)

递归的深度多少,就是多少空间复杂度

递归的深度是多 O(m) 级别的空间复杂度,m是深度

![image-20190615103301021](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615103301021.png)

![image-20190615103350803](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615103350803.png)

for循环里面先进行 int j+1; j<n 这个判断后才会往下走,然后走完就j++

选择排序

For(int j=0, j<n ;j++) {

For(int j=0, j<10000 ;j++) { //这个10000不算入时间复杂度上

}

}

![image-20190615103800925](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615103800925.png)

![image-20190615104015935](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615104015935.png)

![image-20190615104235105](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615104235105.png)

n 除以 xx 等于1,然后就是logn

![image-20190615104546622](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615104546622.png)

O(sqrt(n)) 根号n 判断是否是个素数

具体问题,具体分析。

二分查找法基本就是递归查找法

binarySearch 二分查找

![image-20190615110649958](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615110649958.png)

pow (double x, int n)

![image-20190615110944775](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615110944775.png)

————]————————-

![image-20190615133355295](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190615133355295.png)

二分查找法

没有没有bug的二分查找法在1962年

l+(r-l)/2 -> 通过减法来进行

考虑边界情况,是否为空,是否不在集合中

如何写出正确的程序:

明确变量的含义 , 循环不变量, 小数据量调试

forceClosed, —> true 就是个闭合的 false就是开口的

getLength 获取具体的长度

getSegment 路径的片段

是否截取上次的

getPosTan 路径上的某点坐标,起始点的坐标

弗兰克尔在 追寻生命的意义 中说过

环境可能是无法改变的,唯一可以改变的是自己的态度

我们所处的环境就是一个巨大的鸟笼

我们无时无刻都生活在这个鸟笼中

有太多的人想要飞出这个笼子寻找自由

但不是每个人都能像安迪那样长出丰满的羽翼

所以固化的生活成了我们大部分人的常态

onTouchEvent来进行判断

mCacheViews —默认大小 2

每次移除第一个

pool 的大小是5个

onLayout 布局里面

mChangeScrap 与 mAttachedScrap

mCachedViews

mViewCacheExtension

RecyclerViewPool

什么时候回收,什么时候复用

滑动快的时候,多创建的ViewHolder是怎么回事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RecyclerView#OnTouchEvent的move事件中
RecyclerView#scrollByInternal
LayoutManager#scrollHorizontallyBy
LayoutManager#scrollBy
LayoutManager#fill

LayoutManager#fill (回收和复用)
layoutManger#layoutChunk {
layoutState.next(recycler);
}
recycler(RecyclerView.recycler已经回到了RecyclerView中
).getViewForPosition(mCurrentPosition) {
getScrapOrCachedViewForId中经过
mAttachedScrap
mViewCacheExtension
mRecyclerPool
}

onCreate

onBind

getViewForPosition

ItemTouchHelper 来进行RecyclerView的拖动View

ItemTouchHelper的使用

Callback callback = new C()

ItemTouchHelper touch = new ItemTouchHelper(callback)

touch.attachToRecyclerView(rv)

15怎么来的可以解析一下不

onChidrenDraw 就是 RecyclerView onDraw回调的

recyclerView.getChildCount是4个,而不是8个,指的是显示的个数是4个

只要子view把事件消耗了,中间的view,就没有UP事件了,可能有move事件

平滑滚动:

自定义布局的流程:

​ 1.自定义属性:声明,设置,解析获取自定义值

​ 2.测量:在onMeasure中 MeasureSpac.AT_MOST/EXACTIY

​ 自身的宽与高/child的宽高

3.布局:onLayout

4.绘制:onDraw方法 绘制分割线什么的

5.处理LayoutParams

6.触摸反馈:滑动事件

onDispatchDraw???

互联网思维啊(迭代思想)

1
2
3
//要想滑动必须消耗事件
//onTouchEvent里面返回true,才有后续的move和up事件
//就是说不返回true的话,就没有move和up事件了

实现滑动,然后再实现阻尼效果,然后实现滑动选择器。这些都跟滑动有关

厉害的人很早就开始厉害了

拥有强烈的成功欲望

拥有说干就干的行动力

都是深度学习的机器

都善于坚持

都愿意延迟满足

[袁阔成评书网]

Xfermode

UNSPECIFIED 部分测试

wrap_content往往会传个携带父类大小的size给子类

​ 然后往往是小于父类这个值得

相当于padding是什么时候有效:是在测量的时候有效吗

​ measureChild(child, Wspec, Hspec)

textView放大镜 zero老师最拿手textView

控件滑动起来:1.view的scrollBy scrollTo方法实现滑动

​ 2.通过动画来给view添加位移效果,实现滑动

​ 3.通过改变view的LayoutParams,让view重新布局,从而重新滑动

wps visio

professional visio

相当于canvas坐标移动了50

移动的是画布

相当于原点变成了(50,50)

//移动的是画布

canvas.translate(mLeft-sx,mTop-sy)

6中方式实现移动~

最终的两种移动方式:layout参数;移动动画布

压力信号-》 InputWindowManager 最初的是InputManagerService?

然后传到窗口的activity

事件的分发流程

事件的监听流程

事件的记忆机制:如果已经返回true了,就不会给其他的view了

每一个viewGroup都是事件的分发节点,维护了一个TouchTarget的链表

记录哪个子View的消耗该时间的

截获机制:action_down事件一定可截获的,

非down时间,若子类

分裂机制:

设置gravity,事件的几种机制

如何重构

版本冲突解决:

https://blog.csdn.net/qq_32452623/article/details/81323193

1
2
3
4
5
6
7
androidTestImplementation ('com.android.support.test:runner:1.0.2'){
exclude group: 'com.android.support'
}
androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.2'){
exclude group: 'com.android.support'

}

本身来进行消耗:dx < dy dy> min 排除误操作

1
finalChild

曾经有伟人说过,30岁之前做加法,因为不知道自己能做什么,30岁之后要做减法,做有把握的事

滑动的是内容

长按会影响,滑动效果,会有滑动跳动

realHeight - 父布局高度

computeScroll

invalidate如果没 invalidate完,就不会再调用了

postInvalidate如果

这里和属性动画那一块内核倒是很像

plos

sourceTree

git区块链算法:

集中式,只有服务器有一份,服务器连接不上

​ 就commit和回滚都不能做了

分布式,本地也有一份管理

​ 分布式的话每一个人本地都是一份完整的代码版本,即使服务器版本比你低,也会进行分享覆盖的

​ 文件的形式进行存储,快照就是当前文件的copy

Fetch是拉新分支 刷新本地分支的状态, 就可以看到本地的分支可以远程分支一样了

gitk&

git后缀的那个文件里面会保存你的详细信息,以及版本的详细信息,存在暂存区和本地仓库中,版本那个比较貌似是tree,文件blob的形式

git status

Git add —all 到了暂存区

Git commit -m

clone checkout add commit push

unmodify已经被管理了 不需要进行add操作

Untracked (追踪)没有被管理起来的文件 —> stage

文件的4中状态

你们的分支管理有按照git flow管理吗
develop
feature/
release/
bugfix/
master

更换远程仓库

git remote add

git的权威文档

https://git-scm.com/book/zh/v2

alicode这个比较好,免费的

git remote add origin https://gitee.com/zhousaito/adadfa.git

git branch -vv 当前处于哪个分支

Fetch 是拉取远程仓库信息 到 本地仓库,pull 是拉取远程分支代码到当前分支

Git config core.ignorecase false 不要忽略大小写

git config core.ignorecase false

https://github.com/github/gitignore

objects里面存了blob文件和tree,tree比较计算版本信息

git status 多执行这个命令

git diff 比较没有提交的修改的文件

git diff --staged

git diff --cached

git push —set-upstream origin master

git branch

gitk 命令 需要自己安装

git branch -D

HEAD 指针

Rebase 会有多次冲突的 ,分支上的历史就没了

merge的话,分支的还有

git checkout –conflict=diff3 conflicts/testfile

git checkout –ours conflicts/testfile

OverScroller

视图动画

>补间动画(旋转,平移,缩放,透明)
>
>帧动画
>
>​    AnimationDrawable对象来添加,这样可以通过代码来实现
>
>​    
>
>插值器:缓动函数
>
>​    startOffset
>
>
>
>触摸反馈动画
>
>转场动画  [ 共享元素的动画]
>
>视图状态动画
>
>矢量图动画
>
>约束布局
>
>揭露动画
>
>Spring动画
>lottie-android
>
>
>

属性动画

draw:

![image-20190702201748578](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190702201748578.png)

设置绘制风格

抗锯齿

绘制路径效果 setPatchEffect 绘制虚线

setShader

setStyle 设置画笔的填充风格

setTextAlign 文字对齐方式

setTextScaleX 设置文字水平拉伸比例

setStokeCap 画笔形状

setStrokeJoin 画笔转弯处的连接风格

Canvas.

drawArc (也可以画圆吗)

drawCircle

drawOval 椭圆

drawRoundRect 圆角矩形

convas.drawPicxture (画图片) 一般webView

stroke会把圆占地面积变大

![image-20190702203410555](/Users/zhousaito/Library/Application Support/typora-user-images/image-20190702203410555.png)

​ path.close()

​ android 顺时针为正,跟数学的坐标角度相反

​ useCenter 这个为true就可以画扇形,

​ 如果useCenter为false,如果fill就会直接封过去

moveTo lineTo

shader 渐变器

线性渐变,弧形渐变

LinearGradient

skew扭曲

Canvas.scale 画布是可以缩放的

Canvas.clipRect 获取裁剪

Xfermode玩不动

保存与回滚 (就跟栈一样,每次保存就保存在栈里面

最后,restore,然后就相当于弹栈)

裁剪和平移不一样

裁剪不会改变坐标的,平移会改变坐标的

canvas相当于一个图层

setShadowLine 设置阴影

文字测量

Staticlayout 来进行测试

mPaint.setStrokeCap(Paint.cap.round) //画出椭圆的效果

mPaint.setTestAlign()

方法一、

//来进行得到text的一个rect

mPaint.getTextBounds()

(ract.top + ract.bottom)/2

方法二、

Ascent descent

mPaint.getFontMetics(founmetric)

(founmetric.ascent + fontMetrics.descent)/2 来计算

自定义view,大小要通过onMeasure来确定的
应为放在scrollView里面,会变白,是因为没有重写onMeasure方法

列个Android坑大全

文字有默认间距

多行文字绘制:StaticLayout

丘比特之线

对于大部分中文英文,distance用top和bottom计算,有偏差,字体被偏下了一点点,应该用ascent和descent计算
部分国家的特殊字符的上下高度会超过descent,ascent,用top和bottom计算

一个基于 Python 的简单服务

一行代码搞定服务器

python -m SimpleHTTPServer

Python3 -m http.server

视频剪辑这一类, 自定义view,

breakText 做多行绘制

裁剪画布 可以做出多种类型的图片出来
绘制bitmap

D:\android9\development\samples\ApiDemos\src\com\example\android\apis\graphics

官方demo
要个手写签名

canvas的底层原理matrix

canvas的操作原理

横着 乘以 竖着

matrix.set 会清空上次的操作

旋转,如果没设置就是(0,0),可以进行设置

局部缩放 matrix.setScale()

扭曲 -》可以做翻页 扭曲做3d效果

preTranslate

postRotate

rgba 还是 argb

安徽数学会学到高数和微积分