Android

一、AMS服务启动

this = SysteServer
this.main -> run //The main entry point from zygote.
this.startBootstrapServices -> ActivityManagerService.Lifecycle

二、WMS与App的交互

Activity启动流程https://my.oschina.net/u/3336230/blog/1522704

从AMS-> startActivity 开始,一路略过Activity启动过程直达
ActivityThread.handleResumeActivity:

->decor.setVisibility(View.INVISIBLE);
  wm.addView(decor, l);  //wm 是WindowManagerImpl

->WindowManagerImpl.addView // WindowManagerGlobal.的代理

->WindowManagerGlobal.addView

->ViewRootImpl.setView // 获得WMS.WindowSession,APP与WMS跨进程通信通过IWindowSession
                       // IWindow.Stub用来WMS与APP(ViewRootImpl)通信

->ViewRootImpl.requestLayout

->ViewRootImpl.mTraversalRunnable

->ViewRootImpl.performTraversals // 开启真正的绘制,待细研究

->ViewRootImpl.performMeasure // Ask host how big it wants to be

->mView.measure //DecorView  ,传入的childWidthMeasureSpec,childHeightMeasureSpec为窗口的大小和mode
                //这里要说明的是对于ViewGroup的子类需要重写onMeasure方法,需要先(measureChildWithMargins)测
                //量其子类的最大宽高+padding,然后结合自身大小限制计算出合适的mMeasureSpec

                //View的子类重写onMeasure只需给出自己的大小和内容(背景图片,字体大小)比较后合适的值

->mView.layout

->mView.draw

三、MotionEvent传递、分发

Android事件这块分两部分:事件来源(InputReader从底层读取)、事件分发(在页面各View的传递)

MotoinEvent 是java层封装的数据结构,它的源数据结构是由InputReader从文件读取而来。

InputDispatcher线程负责分发事件到UI,这两个线程都是从InputManagerService初始化InputManager->start 时启动的

1、事件从底层分发到ActivityThread通过Handler,然后通过ViewRootImpl一路到

DecorView.dispatchTouchEvent.callback->Activity->

PhoneWindow.superDispatchTouchEvent->

DecorView.superDispatchTouchEvent->

ViewGroup.dispatchTouchEvent

java.lang.Throwable: stack dump
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at java.lang.Thread.dumpStack(Thread.java:496)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at com.jym.floatwinplugin.view.widget.FloatBallView.dispatchTouchEvent(FloatBallView.java:250)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.View.dispatchPointerEvent(View.java:7426)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3220)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3165)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4292)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4271)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4363)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.os.MessageQueue.nativePollOnce(Native Method)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.os.MessageQueue.next(MessageQueue.java:125)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.os.Looper.loop(Looper.java:124)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5041)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at    java.lang.reflect.Method.invokeNative(Native Method)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at   java.lang.reflect.Method.invoke(Method.java:511)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
05-09 11:58:50.623 11447-11447/com.float.mall W/System.err:     at dalvik.system.NativeStart.main(Native Method)

四、性能优化总结

1、界面绘制常识

UI在1s内显示60帧,那么这种比较细腻的界面显示不会感觉到卡顿。这就要求每帧画面需要在16ms内完成绘制。24 Fps 是人眼能感知的连续线性的运动,所以是电影胶圈的常用帧率。

影响绘制的因素:

垃圾回收是影响绘制的罪魁祸首之一,好消息是Android4.4 引进了新的 ART 虚拟机来取代 Dalvik 虚拟机,极大的提高了GC的回收效率,通常在2~3ms

UI线程是主线程,主线程大量的耗时操作会直接影响UI渲染,不过在 Android 5.0 版本里,Android 框架层引入了 “ Render Thread ” ,用于向 GPU 发送实际渲染的操作。这个线程减轻了一些 UI 线程减少的操作。但是输入、滚动和动画仍然在 UI thread,因为 Thread 必须能够响应操作。

2、性能优化工具

Hierarchy View 布局层次管理器,可以有效的分析复杂布局结构

Lint 给XML布局和代码不合理处提示

  • 包含无用的分支,建议去除;
  • 包含无用的父控件,建议去除;
  • 警告该布局深度过深;
  • 建议使用 compound drawables ;
  • 建议使用 merge 标签;

Systrace 可以直观看到流程执行耗时的地方,但使用麻烦

Track 可以直观的跟踪到每个函数的耗时

OverDraw APP开发者选项中开启,过度绘制的UI会显示不同颜色

  • 没颜色:没有过度绘制,即一个像素点绘制了 1 次,显示应用本来的颜色;
  • 蓝色:1倍过度绘制,即一个像素点绘制了 2 次;
  • 绿色:2倍过度绘制,即一个像素点绘制了 3 次;
  • 浅红色:3倍过度绘制,即一个像素点绘制了 4 次;
  • 深红色:4倍过度绘制及以上,即一个像素点绘制了 5 次及以上;

    原因是视图相互重叠和每个View都有相同背景

StirctMode  严格模式,检查主线程有耗时操作会在手机闪烁红框

3、不合理的XML布局

由于UI显示出来是在解析、测量布局之后才开始显示,所以布局层次太深会导致时间变长

4、优化建议

  • 避免复杂的view层级,寻找最优方案布局
  • 避免使用RelativeLayout,它是个耗时的布局,需要测量两次,随着嵌套越多,性能会越差。确实需要可以用GridLayout代替
  • 不要使用绝对布局 AbsoluteLayout 
  • 使用</include> 标签重用可复用的布局
  • 使用merge标签
  • 尽量避免使用layoutweight,使用它的linearLayout会绘制子组件两次
  • ViewStub懒加载不常用布局
  • 主线程不要做耗时操作

五、Binder

Binder也不是Android自己开发的,它的前身是OpenBinder。

Binder模型包含四部分,client、server、serverManager、binder驱动,其中真正实现IPC通信的是binder驱动部分。

传统的linux进程通信方式有管道、socket、system V IPC等。

IPC

数据拷贝次数

共享内存

0

Binder

1

Socket/管道/消息队列

2

binder只发生一次拷贝的奥秘在于binder驱动的实现,它实现了mmap(物理存储介质的文件系统)的调用。在/dev/binder文件,采用mmap开辟一块缓冲区,并且这块内存会映射到用户空间和内核空间,并且统一由binder驱动管理。

六、Android绘制过程

ViewRootImpl

//绘制过程一言以蔽之,即Acitivty的顶层View是DecorView,setContentView把view放到了DecorView的id为content的子
//view里,Activity中有个PhoneWindow,和WindowManagerImpl(实际上是WindowManagerGlobal的代理)。
//在ActivityThread的handleResumeAcitivity方法中
//WindowManagerImpl.add  DecorView
//WindowManagerGlobal.add DecorView
//ViewRootImpl.mView = DecorView
//ViewRootImpl在performTraversals通过Surface locak一块Raw buffer为Canvas传给decorView的draw方法

public final class ViewRootImpl implements ViewParent{

    final IWindowSession mWindowSession;
    final W mWindow; // 通过调用mWindowSession传给WMS
    View mView; // DecorView
    Surface mSurface = new Surface();// 操作一块Raw buffer(内存或显存),被SurfaceFlinger管理抛到屏幕

    private boolean draw(...){
       drawSoftware();
    }
    private boolean drawSoftware(...){
       canvas = mSurface.lockCanvas(dirty);
       mView.draw(canvas);
    }
}

Surface

// Surface使用的不是java层new 的这个无参Surface,而是使用的wms中new的一个参数为SurfaceSession的Surface
// 之后图像数据会以FrameBuffer和pageflipping的方式一帧一帧经过SurfaceFlinger混合后显示出来

七、常用第三方框架

1、网络框架

okhttp、retrofit出自Square公司

2、异步处理

Rxjava、EventBus

3、图片加载

Glide、Picasso出自Square

4、性能优化

Leakcanary

Blockcanary

转载于:https://my.oschina.net/u/3336230/blog/1595118

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值