Android debug-hwui-profile

本文目标

探索 gpu呈现模式 测量的是什么

基本用法

原生Settings

1
Settings -> 开发者选项 -> gpu呈现模式

命令行

1
setprop debug.hwui.profile visual_bars # false关闭

图形解释

1
2
3
4
蓝色: create/update DisplayList
紫色: 同步到render thread
红色: 将DisplayList转为gl命令调用
黄色: cpu等待gpu完成

profile时机

4.4.4_r1

涉及文件

1
HardwareRenderer.java

绘制

1
2
3
4
5
6
7
HardwareRenderer.drawProfileData() {
mProfileData 数据
for(i=0; i < getFrameCount()*elementCount; i+=elementCount)
mProfileShapes[] <- bar条rect
drawGraph() 画bar条
drawCurrentFrame() if(当前帧) 加深当前帧的bar条
drawThreadshold() 16ms水平线

查看更多

aapt 源码分析

概念

1
2
Resource Id 32位 = 8(packageId) + 8(typeId) + 16(nameId)
ResourceTable.cpp::makeResId()

framework-res典型调用

1
out/host/linux-x86/bin/aapt package -u -x -z  --pseudo-localize   -M frameworks/base/core/res/AndroidManifest.xml -S device/myvendor/overlay/frameworks/base/core/res/res -S frameworks/base/core/res/res -A frameworks/base/core/res/assets  --min-sdk-version 22 --target-sdk-version 22 --product phone --version-code 22 --version-name 5.1.1-2.0.16   -F out/target/common/obj/APPS/framework-res_intermediates/package-export.apk

流程

查看更多

PlantUML 基础

基本框架

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
@startuml

'comment

/' multiline
comments
'/

title First Page Title
' some diagram

newpage

' some other diagram

' legend 图注 left/center/right
legend center
XX Diagram
endlegend

' note left/left of/right/right of/over Alice
note left: First note

note right
Second note
end note

' == Divider ==

/' space
|||
||45|| == 45px
'/

@enduml

查看更多

Fresco 源码分析

SimpleDraweeView 显示流程

1
2
3
4
SDV: SimpleDraweeView
PDCBuilder: PipelineDraweeControllerBuilder
ADCBuilder: AbstractDraweeControllerBuilder
ADController: AbstractDraweeController

设置

1
2
3
4
5
6
7
8
9
10
11
SDV.setImageURI() {
controller = PDCBuilder.setUri(uri).setOldController(getController()).build()
setController(controller)
}
-> (PDCBuilder 父类 ADCBuilder).buildController()
-> PDCBuilder.obtainController() { 清空现在的listeners }
-> ADCBuilder.maybeAttachListeners(controller) {
只剩 ADCBuilder.mBoundControllerListeners, 此成员在 ADCBuilder ctor中赋值为null
}
-> (SDV 父类 DraweeView).setController()
-> DraweeHolder.setController()

触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
在 WindowManger系统 SDV.onAttach() 时
(SDV 父类 DraweeView).onAttach()
-> DraweeView.doAttach()
-> DraweeHolder.onAttach()
-> DraweeHolder.attachOrDetachController()
-> DraweeHolder.attachController()
-> AbstractDraweeController.onAttach()
-> ADController.submitRequest() {
若cache到, 直接调用 onNewResultInternal();
若无cache, mDataSource.subscribe(DataSubscriber), 在 onNewResultImpl()调用 onNewResultInternal() 或 onFailureInternal() }
-回调-> ADController.onNewResultInternal() {
mSettableDraweeHierarchy.setImage(drawable..)
isFinished: { getControllerListener().onFinalImageSet() }
否则: { getControllerListener().onIntermediateImageSet() }

获取

线程

1
2
3
Fresco.initialize()
-> ImagePipelineFactory.initialize(ImagePipelineConfig) { new ImagePipelineFactory() }
-> ImagePipelineFactory.ctor() { mThreadHandoffProducerQueue = DefaultExecutorSupplier.mLightWeightBackgroundExecutor }

提交到线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(父类 ADController).submitRequest()
-> PipelineDraweeController.getDataSource()
-> PDCBuilder.getDataSourceForRequest()
-> ImagePipeline.fetchDecodedImage()
-> ImagePipeline.submitFetchRequest() { ClosableProducerToDataSourceAdapter.create() }
-> (ClosableProducerToDataSourceAdapter 父类 AbstractProducerToDataSourceAdapter).ctor()
-> BitmapMemoryCacheGetProducer.produceResults()
-> ThreadHandoffProducer.produceResults()
-> ThreadHandoffProducerQueue.addToQueueOrExecute() { mExecutor.execute() }
-executor线程-> StatefulProducerRunnable ThreadHandoffProducer.statefulRunnable.onSuccess()
-> (BitmapMemoryCacheKeyMultiplexProducer 父类 MultiplexProducer).produceResults()
-> MultiplexProducer.startInputProducerIfHasAttachedConsumers()
-> BitmapMemoryCacheProducer.produceResults()
-> DecodeProducer.produceResults()
-> LocalImageProgressiveDecoder.ctor()
-> 父类 ProgressiveDecoder.ctor() { JobRunnable 此job被执行时 doDecode() }


AbstractDataSource.subscribe() {
mDataSourceStatus在ctor赋初始值 IN_PROGRESS:
mSubscribers.add(Pair(dataSubscriber, ADController.mUiThreadImmediateExecutor))
shouldNotify==false: 忽略 }

JobScheduler

duilib使用小结

版本: https://github.com/duilib/duilib master

环境: vs2013

基本内容

新建空的win32工程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <UILib.h>
class CDuiFrameWnd : public WindowImplBase
{
public:
virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); }
virtual CDuiString GetSkinFile() { return _T("duilib.xml"); }
virtual CDuiString GetSkinFolder() { return _T(""); }
};

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);

CDuiFrameWnd duiFrame;
duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
duiFrame.CenterWindow();
duiFrame.ShowModal();
return 0;
}

xml布局

duilib.xml 需要同步到exe目录

查看更多

LibGDX 实现 动态中文/freetype 加载

1
2
3
4
5
1. JSON读取
Skin.getJsonLoader() -> new Json() -> json.setSerializer()
读json文件size属性, new FreeTypeBitmapFontStub()
FreeTypeBitmapFontStub extends BitmapFont
FreeTypeBitmapFontStub.data instanceof FreeTypeBitmapFontData
1
2
3
4
5
6
7
8
2. Label初始化
new Label() -> Label.setStyle() {
FreeTypeFontManager.isFreeTypeFont(style.font)==true {
data.setSize(style.fontSize)
new FontInfo(data.getSize())
font = FreeTypeFontManager.getInstance().refresh(style.font==stub, newInfo)
}
cache = new BitmapFontCache(font) // cache里的 font == 第一次refresh出来的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3. 更新文字
Label.setText() -> Widget.invalidateHierarchy()
-> Label.invalidate() { needsLayout=true; sizeInvalid=true }
渲染 -> draw() -> Widget.validate() -> Label.layout()
-> computeSize() -> cache.requireSequence(text) {
FreeTypeFontManager.isFreeTypeFont(this.font) == true:
this.font = FreeTypeFontManager.getInstance().refresh(this.font, curFontInfo) }
-> FreeTypeFontManager.refresh(font, newInfo) {
isStub == false
newInfo不含在当前子串里:
getFont(newInfo.size)
-> (FreeTypeFontGenerator)generator.generateFont(sizePixel, sequence, flip==false)
-> FreeTypeFontGenerator.generateData(size, chars, flip, packer==null)
-> FreeTypeFontGenerator.generateData(parameter) {
parameter.packer == null:
ownsAtlas = true
data.regions[i] = new TextureRegion(tex=new Texture()) // new出来的texture
return data
}
}

LibGDX skin load 源码分析

1
2
3
构造函数里设置 SkinLoader
AssetManager.ctor() { setLoader(Skin.class, new SkinLoader(resolver==new InternalFileHandleResolver())) }
-> AssetManager.setLoader(Skin.class, suffix==null, SkinLoader)
1
2
3
4
5
6
用户程序调 load
AssetManager.load(fileName, Skin.class)
-> AssetManager.load(fileName, Skin.class, parameter==null) {
getLoader(Skin.class, fileName);
loadQueue.add(new AssetDescriptor(fileName, Skin.class, parameter))
}
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
48
49
用户程序调 finishLoading
AssetManager.finishLoading() { while(!update()) ThreadUtils.yield() }
-> AssetManager.update() { nextTask(); updateTask(); }
AssetManager.nextTask() { assetDesc = loadQueue.removeIndex(0); addTask(assetDesc) or inc ref }
AssetManager.updateTask() { task.update(); addAsset(fileName, type, task.getAsset()) }
-> AssetLoadingTask.update() { handleSyncLoader() or handleAsyncLoader() }
SkinLoader 是 AsynchronousAssetLoader, 这里会调用 handleAsyncLoader()
-> AssetLoadingTask.handleAsyncLoader() {
// 执行多次, 因为submit到线程池中, 被调 call().
// SkinLoader.getDependencies() 加入装载 TextureAtlas 的依赖
exec0:
dependenciesLoaded == false && depsFuture == null:
depsFuture = (AsyncExecutor executor).submit(this)
exec1:
dependenciesLoaded == false && depsFuture.isDone():
dependenciesLoaded = true
可能的exec2:
loadFuture == null && !asyncDone:
loadFuture = executor.submit(this)
// 会在线程池中执行 AssetLoadingTask.call() -> 即本loader的 loadAsync()
最后的exec:
asyncDone:
asset = asyncLoader.loadSync(manager, fileName, resolve(loader, assetDesc), params)
}

SkinLoader.loadSync() { new Skin(atlas).load(file) }
-> Skin.load(skinFile) { getJsonLoader().fromJson(Skin.class, skinFile) }
-> Json.fromJson(type==Skin.class) { this.readValue(type, null, new JsonReader().parse(file)) }

JsonReader.parse(file) { JsonReader.parse(file.reader("UTF-8")) }
-> JsonReader.parse(Reader reader) -> JsonReader.parse(data, 0, offset)

FileHandle.reader(charset) { return new InputStreamReader(read(), charset) }
FileHandle.read() { return new FileInputStream(file()) }
FileHandle.file() { return java.io.File }

Skin.getJsonLoader(skinFile) { return 匿名Json新类 }
匿名Json类.readValue(Skin.class, null, jsonData) {
jsonData.isString() == false:
super.readValue(Skin.class, elementType==null, jsonData)
}

Json.readValue(Skin.class, elementType==null, jsonData) {
jsonData.isObject() == true:
typeName == null: className = null
serializer = classToSerializer.get(Skin.class) // 在Skin.java匿名类中有SetSerializer
serializer.read(this, jsonData, type)
}
-> 匿名Json类.read() { for(valueMap) readnamedObjects(json, ClassReflection.forName(valueMap.name()), valueMap) }

RecyclerView 源码分析

版本: 25.1.0

Scroll

调用顺序

1
2
3
4
RecyclerView#requestChildFocus()
-> RecyclerView#requestChildRectangleOnScreen()
-> LayoutManager#requestChildRectangleOnScreen()
-> RecyclerView#smoothScrollBy(int, int)

回调

添加/删除

1
addOnScrollListener/removeOnScrollListener (OnScrollListener)

调用

ScrollListener.onScrolled()

1
2
3
4
5
6
7
8
9
10
11
12
<- RecyclerView.dispatchOnScrolled()
1. <- RecyclerView.scrollByInternal()
1.1 <- scrollBy(x, y)
1.1.1 <- RV.LayoutManager.requestChildRectangleOnScreen() { dx!=0 || dy!=0 }
1.1.2 <- RV.LayoutManager.performAccessibilityAction() { vScroll != 0 || hScroll != 0 }
1.2 <- RV.onTouchEvent() ACTION_MOVE 触摸移动
1.3 <- RV.onGenericMotionEvent() SOURCE_CLASS_POINTER ACTION_SCROLL 鼠标滚轮
2. <- RecyclerView.dispatchLayoutStep3() { dispatchOnScrolled(0,0) } layout引起的 item range changed
3. <- RV.ViewFlinger.run() {
hresult=LayoutManager.scrollHorizontallyBy(); 线性布局 会调到 LinearLayoutManager.scrollBy()
vresult=LayoutManager.scrollVeriticallyBy();
(hresult != 0 || vresult != 0) dispatchOnScrolled() }

RV.smoothScrollBy()

1
-> RV.ViewFlinger.smoothScrollBy()

查看更多