PROCEDURE


  • 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可以用来做桌面的小挂件,步骤为:

Created with Raphaël 2.1.0 start 写layout 写<appwidget-provider> 写extends AppWidgetProvider in-onUpdate():setRemoteView-->setPendingIntent-->appwidgetManager.updateAppWidget in-onReceive():设置自己的action处理逻辑 register-in-AndroidManifest(APPWIDGET_UPDATE)

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 即可
  • 判断内存泄漏可以查看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,然后就可以随心所欲的在里面挑着使用了。
  • 一个方法在父类中没有被调用,如果还是有相应的效果的话,那么就是在子类里面做了处理了,并且还没有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())
Created with Raphaël 2.1.0 start ContextImpl.registerReceiver() ReceiverDispatcher保存BroadReceiver和Binder的映射关系(BroadcastReceiver是系统组件,跨进程跨不过去,裤裆太低了。。。)然后IPC发送到AMS AMS把BroadcastReceiver放到自己的队列里面包存起来 end
  • 发送/接受broadcast
Created with Raphaël 2.1.0 start ContextImpl.sendBroadCastReceiver() AMS根据intent搞一个BroadcastQueue来保存符合的receivers BroadcastReceiver发消息给ApplicationThread App..Thread里面scheduleRegisteredReceiver()调用ReceiverDispatcher.InnerReceiver(真正的receiver,与Binder区分) InnerReceiver.performReceive给ActivityReceiver的Handler发消息,Handler调用receiver.onReceive end

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值