- AS使用monitor(DDMS)观察method time,View Hierarchy,Heap.(只有View Hierarchy还比较好用,其余的都不如AS自带的)
- laytou中某个单独的地方使用ViewStub对与initView函数执行方法时间长度优化非常有限,几乎可以无视.
- Android的View有两块内容:View的绘制(measure->layout->draw,View和ViewGroup两套不同流程)和事件分发(dispatchTouchEvent,View和ViewGroup不同)
- View的layoutparam(width,margin,height,weight,etc)在父容器的measureChildren中被使用;View的padding和”wrap_content”在自己的onDraw中被使用;
11.2 18:42 5
- LeakCanary查看内存泄漏结果(结合AS的dump heap然后查看dump出来的文件进而确认泄露对象),不过分析内存泄漏是手工活,不容易.
- RemoteView的基本用法:set Notification–>notify;set RemoteView–>set Notification–>notify;更新RemoteView需要remoteView.setTextViewText这种方法来修改.
18:39 3
- RemoteViews可以用来做桌面的小挂件,步骤为:
18:38 2
- RemoteViews内部
- RemoteViews通过Binder方式实现(内部保存多次修改Action然后一次IPC传输过去,减少IPC次数)
- RemoteViews.apply可以填充一个layout生成View,reapply用来更新View
- RemoteViews.Action.apply()可以修改View的属性(setTextViewText这种主要代码在这个函数中)
- 如何在两个不同的APP中传输自定义View???getResources.getIdentifier()+remoteViews.reapply???
- 去除overdraw最重要的就是去除ViewGroup的background,或者用clipRect制定不绘制部分(不过自定义View里面才会用到这个)
- git
- git rebase –onto cA cB cC
gcb temp//git checkout -b temp
可以new一个叫做temp的分支,把cB-cC(不包含cB,包含cC)之间的commit rebase到cA上,HEAD位于temp的最新commit(cC). - git rebase 后冲突的话,处理完文件后
git add conflict_file
git rebase –continue 即可
- git rebase –onto cA cB cC
- 判断内存泄漏可以查看heap内存,在app里面多次操作后heap无限持续增长,就是泄漏了.
10.8 10:49(for yesterday) 4
- ViewPagerAdapter.getCount返回MAX会导致adapter.notifyDataSetChanged后ANR,但是如果notify后在设置一次Adapter,即mAdapter.notifyDataSetChanged();mViewPager.setAdapter(mAdapter);就可以不ANR了
- 尝试看ViewPager.populate()发现没有看懂源码
- heap dump得到的结果中ShallowSize是直接占据空间,RetainedSize是释放了这个object后,GC会释放掉的空间(被这个object唯一持控的)
11.9 9:49(for yesterday) 2
- Drawable
- StateListDrawable
<selector>
<item/>
<item/>
</selector>
- LayerDrawable:可以用其他的Drawble通过设置padding合成新的Drawble
<layer>
<item/>
<item/>
</layer>
- InsetDrawable用来给一个Drawable加一层,然后可以设置该Drawable的距离上下左右的边距
<inset>
<item/>
</inset>
- 最重要的还是LevelStateDrawable,这个可以设置不同的Drawable,当然有别的实现方式(例如构造一个Drawable数组然后再代码里面动态设置),不过这个更方便,至少使用起来方便,设置若干个Drawable,然后就可以随心所欲的在里面挑着使用了。
- StateListDrawable
- 一个方法在父类中没有被调用,如果还是有相应的效果的话,那么就是在子类里面做了处理了,并且还没有super。(比如onActivityResult)。
- 接收浏览器Scheme的可以是一个activity,并且这个activity只负责最基础的“接待”工作,就是不要做太多的逻辑。
- 如果在onClick之类的事件方法里面释放了某个object,需要注意当多次快速点击(第一次还没有执行完,就开始第二次),可能会on a null reference(第一次里面释放了,第二次又对那个object进行访问)
11.10 8:04(for yesterday) 4
- fragment生命周期[onAttach->onCreate->onCreateView->onActivityCreated]->onStart->onResume->onPause->onStop->[onDestroyView->onDestroy->onDetach],如果在前面做了操作又在后面进行不恰当的引用(例如onDestroyView中赋值null而在onDestroy中尝试引用),就会出错。
11.12 10:23(for 11.10) 1
- drawPath如果path首尾相连的话,Paint.Style==FULL的话,就会把线围起来的区域涂色了。
- Effective Java
- java的内存分配是一门学问,例如子类constructor里面会调用parent.contructor(这是符合逻辑的,虽然第一眼看上去有点奇怪,但是想想肯定是对的,如果子类不持有一个parent的对象(方法、属性等),那么子类肯定不能调用parent的这些。C++面向对象那本书上应该说了的,我忘了。)
- 单例的几种形式
直接实例对象:private Object singleton = this();
lazy new:if(singleton == null) singleton = this();
线程安全:if(singleton == null) synchronize(singleton){singleton = this();}
防止反射产生多个对象:private Object(){if(single != null) throw new RuntimeException();}
抵御序列化产生多个对象://implements Serializable时重写 private Object readResoleve(){return singleton;}??????????????????????这样子可以吗?序列化写到磁盘上,然后在读的时候读到的不是只有相同的属性吗?这样子读入内存的是一个新的对象(理论上说是这样的),但是呢,JRE在解析这个对象的时候要调用一个方法(Object.readResolve()),这个方法返回的才是最终结果,通常来说这个方法JRE会自己新建一个对象返回,但是这里重写了,所以外部的那个方法就不能用了。问题来了。如果这时候singleton是null呢?我待会写篇测试报告。
抵御序列化产生多个对象2://enum枚举好像是可以避免这个问题的。具体不了解,不详写。
11.12 12:16(for 11.11) 4
11.12 11.13 0
- 阅读第三方框架源码往往都是徒劳,源码阅读方法需要改进。
11.15(for 11.14) 痛苦地要给-1了 0
- View自定义属性如果不写<attr foramt=”xxx”/>就会报错误unable to find attribute xxx。
- View的measuredWidth 和 width(mRight - mLeft)如果不相同,一个原因就是因为layout()的时候,不是严格按照measureWidth来进行layout的(比如说super.layout(l,t,r+100,b);这样).View绘制流程measure->layout–>draw
- Activity的动画overridePaddingTransition(start_ainim,end_anim).需要在startActivity(intent)或者是finish()后调用。
- 有一个ListAnim的东西,设置了之后list的所有children都会调用这一anim(可以设定执行顺序).
11.15 20:41 2
- ObjectAnimator
- ObjectAnimator.ofInt(view,str_property_name,start_value,end_value);anim.setDuration(time);anim.start();
- property_name在View中必须设置有getter和setter(getProperty_name & setProperty_name),如果View中已经有了这两个方法(但是并不是实际的getter和setter),那么:1.重写这两方法(通常不可行)。2.加wrapper,即ViewWrapper.setProperty_name和ViewWrapper.getProperty_name(),在里面完成getter和setter的逻辑。3.使用ValueAnimator,addUpdateListener里面重写animatorUpdateListener在每次update的时候进行View的属性设置.
- 用的是反射
- 有些框架你想往里面加东西很困难(根本看不懂框架内容,设置的太多了)。这时候可以考虑删减原来框架内容,就是直接修改框架代码,把那些用不到的都删除了,剩下的就很容易懂了。
11.17 8:54(for 11.16) 4
- onIntercept返回true的话就开始执行onTouchEvent(没有onTouchListener的话)。
WindowManager
- WindowsManager.addView可以在Window的任何地方(通过WindowManager.LayoutParams设置)显示一个view;通过LayoutParams还可以设置View的显示flag(设置View可点或者View在锁屏时候显示)和type(级别,高级别会覆盖低级别的view,大致分为应用type,系统type等,例如SYSTEM_ERROR是一个系统级别的type,不过需要在manifest里面申请权限.)
- WindowManagerImpl是桥接模式,在里面实际调用了WindowManagerGlobal中的方法。
2016年11月17日18:42:54 3
- WIndow
- 在WindowManagerGlobal中实现add,remove,update等操作.
- Activity与Window
- Activity的流程操作在ActivityThread中
- mDecor是一个DecorView
- ActivityThread.performLaunchActivity()开始activity,会调用Activity.attach(),attach里面新建一个PhoneWindow
- 在setContentView中调用mWindow.setContentView()[在里面新建DecorView然后添加contentView然后回调activity.onContentChanged,该方法默认为空]添加view,ActivityThread.handleResumeActivity里面调用onResume,在里面会WindowManager.addVIew(mDecor).
- Dialog与Window
- Dialog constructor中会PolicyManager.makeNewWinow新建一个mWindow.
- Dialog.show()里面调用WindowManager.addView(mDecor)
- 一些Window需要应用token,如果Context为Application,会产生问题,Activity才有token。如果是系统级别的Window,不需要应用token不会出问题。可以用Dialog.getWindow.setType(xxx)来设置级别,需要在manifest中声明权限。
- Toast与Window
- Toast主要内容是Binder,因为Toast有一个NotificationManagerService保存系统当前的toast队列,然后ManagerService等待toast显示然后循环队列,通知Toast线程进行显示或者隐藏toast。
- Toast显示/隐藏用的也是WindowManager.addView()和removeView()
- 对于Window和View的关系,仍然不是十分的清楚明白。
2016年11月21日19:01:49 4
- WIndow是一个辅助View的功能类。
- Activity的start流程
- startActivity最终都调用到startActivityForResult
- activity在start的时候要先经过ActivityManagerService(设置启动uid等),ActivityStackSupervisor(不知道做了什么)和ActivityStack(不知道做了什么)
- activity在ApplicationThread.sheduleLaunchActivity()被发到handler里面
- activity在ActivityThread的Handler中初始化performLaunchActivity()
- 在performLaunchActivity里面,获取activity的信息,新建activity(通过classLoader),新建application(单例对象,classLoader),新建activity的context,调用activity.attach()
- attach里面绑定contextImpl和activity,并且完成相关的window的添加。
2016年11月22日18:15:44 3
Service的启动流程:
- start
-ContextImpl
-ActivityManagerService
-AMS.ActivityServices
-ApplicationThread
-ActivityThread
-Service.attach()
-Service.onCreate() - bind
-ContextImpl
-ServiceDispatcher
-AMS
-ApplicationThread
-ActivityThread
-Service.onBind()
-AMS.publishService()
-ServiceDispatcher
-ServiceConnection.onServiceConnected() - 虽然看了一些,但是感觉还是没有联系起来这部分知识,只是知道了activity和service的启动都要经过IPC到AMS(之前还会进行一些全局操作,例如活动栈或者是系统维护的一些数据结构等)然后交给ApplicationThread来sendMessage到ActivityThread然后进行实际处理。
2016年11月24日10:19:03(for 11.23) 3
BroadcastReceiver:
- 注册(registerReceiver())
- 发送/接受broadcast
JVM的一些知识:
- JVM的内存分区
- Method Area:保存class/static variables/constants等信息
- Heap:几乎全部的对象实例存储区
- Stack:不同于常说的堆栈的“栈”(这个说法里面的表示的只有变量存储功能),JVM Stack包含多个stack frame(每一个表示一个method,stack frame里面包含了局部变量表、方法的退出信息(return)、还有变量之间的动态链(编译原理上讲过,已经不记得了)等)。
- Program Counter:就是字节码指针,表示当前指向的代码语句字节码行号。
- JVM包含两种代码(Java生成的字节码和本地的native代码(不是java代码,C或者C++))
2016年11月24日18:45:30 5
- draw
- paint.meaureText可以用这个paint绘制出来的str的长度(px)。
- canvas.drawRoundRect绘制圆角矩形
- radius的意思是半径
- Scroller
- scroller配合computeScroll一起用,在computeScroll里面根据scroller的currX和finalX设置view绘制的关键参数,并且postInvalidate。
- scroller fling以后,scroller的FinalX会变成fling的距离而不是屏幕上的x坐标(例如x快速从20滑到1000,假设fling的距离应为200,那么scroller的finalX和初始x不是1200和1000,而是200和0)
- scroller如果要fling的话需要配合VelocityTracker
- scroll
- 自定义view要用scrollTo/scrollBy的话,在onDraw里面要绘制的内容就应该比view的width/height要大,而且每次onDraw的时候都要把所有东西都绘制一遍
- 不用view的scrollTo/scrollBy的话,大概模式是有一个变量表示标尺坐标x(例如x为要绘制的内容的中间点或者是左上角等),根据x的值的不同,可以在onDraw确定要绘制的内容,即有一个V = f(x),V为要绘制的内容,这样可以不全都绘制,只绘制要显示的那个区域(外面的没必要绘制),但是数学计算通常比较复杂。然后在onTouchEvent里面实现修改x。
- Handler
- Handler包括Message,Looper。
- ThreadLocal<Object>是线程相关变量,代码里面同一个ThreadLocal变量,不同线程访问的时候是不同的
java
final ThreadLocal<Boolean> b = new ThreadLocal<>();
b.set(true);
new Thread(new Runnable() {
@Override
public void run() {
b.set(false);
//b在这里为false。
}
}, "Thread#1").start();
//b在这里为true
2016年11月29日13:17:04(for 11.28) 4
- javascript
- 访问对象用o[‘pName’]
- 删除对象属性用delete o[‘pName’]
- 数组长度用a.length
- webStorm里面设置JS的语言(有好几种选择,ECMA%&^%^$^%^*)
- Handler
- Looper循环调用messageQueue.next()
- messageQueue.next()在没有消息/下一个消息的时间还没到的时候会阻塞
- messageQueue.next在Looper.quit后返回null(quitSafely不会立即变)。loop到null以后就结束,looper线程也才会终止
- Handler处理消息的顺序:msg.callback(就是post的内容)-》handler.mCallback-》handler.handlerMessage。所以不想重写handlerMessage,就setCallback。
- ActivityThread自己有MainLooper,对应的handler为ActivityThread.H,用来处理四大组件的启动停止。
- ApplicationThread是一个Binder用来和AMS通信,AMS处理完了以后再通知ApplicationThread,然后ApplicationThread再给H发信息,H进行处理。
2016年11月30日20:08:21 4