鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 手机系统开发 > android > >

Android工具HierarchyViewer 代码导读(3)

来源:互联网 作者:佚名 时间:2012-11-14 14:39
在上文中,我们讲解了如何把HierarchyViewer的项目导入到Eclipse中,以便更高效阅读代码。本文将讲解HierarchyViewer的后台代码,建议大家可以先阅读Android工具HierarchyViewer代码导读(1) -- 功能实现演示一文, 其中的代码演示了HierarchyViewer的主要功能

在上文中,我们讲解了如何把HierarchyViewer的项目导入到Eclipse中,网站空间,以便更高效阅读代码。本文将讲解HierarchyViewer的后台代码,建议大家可以先阅读<Android工具HierarchyViewer代码导读(1) -- 功能实现演示>一文, 其中的代码演示了HierarchyViewer的主要功能。而本文就是讲解HierarchyViewer是如何实现功能的。

 

把复杂的代码讲解清楚一般都不是很容易的事情,为了不把本文写成流水帐,文章将尽量集中在HierarchyViewer后台代码的主要脉络上,许多细节需要读者自己去阅读,那是必须的。

 

MVC模式

HierarchyViewer采用典型的MVC模式设计。

当打开HierarchyViewer,进入主界面时,其对应的MVC模式是:HierarchyViewerDirector.java是Controller,DeviceSelectionModel.java是Model,DeviceSelector是View,如下图所示:

image

 

当双击某个Acitivity,进入浏览层次图界面时,其对应的MVC模式是:HierarchyViewerDirector.java是Controller,TreeViewModel.java是Model,Views是TreeViewController.java、TreeViewOverview.java、PropertyViewer.java、TreeViewer.java、LayoutViewer.java:

image

 

HierachyViewerDirector.java(即Controller)通过DeviceBridge.java来和Android设备通信,而DeviceBridge.java具体是通过AndroidDebugBridage.java和DeviceConnection.java来和设备通信。如下图所示:

image

 

AndroidDebugBridge.java : AndroidDebugBridge.java是ADB API,位于ddmlib项目中。 它实现了命令行版adb一样的功能,在HierarchyViewer中主要用到其连接设备,forward端口,启动ViewServer等操作。

DeviceConnection.java: 负责和ViewServer通信,向ViewServer发送命令并接受其返回的信息。从而获取Activity列表、控件层次结构图、截图等。

 

入口点

后台代码的入口点在HierarchyViewerApplication.java的createContents method中:

@Override protected Control createContents(Composite parent) { // create this only once the window is opened to please SWT on Mac mDirector = HierarchyViewerApplicationDirector.createDirector(); mDirector.initDebugBridge(); mDirector.startListenForDevices(); mDirector.populateDeviceSelectionModel(); //... ... }

以上代码做了如下工作:

1,服务器空间,HierarchyViewerApplicationDirector.createDirector() -- 创建一个HierarchyViewerDirector对象

2,mDirector.initDebugBridge() -- 初始化AndroidDebugBridge

3,mDirector.startListenForDevices() -- 把mDirctor注册为AndroidDebugBridge的监听者(HierarchyViewerDirector继承了IDeviceChangeListener接口),当有设备连接、断开、改变时,mDirctor将接收到事件。

4,mDirector.populateDeviceSelectionModel() -- 获取当前已经连接的设备列表,处理并显示它们。

 

阅读populateDeviceSelectionModel()函数你会发现, 其中获取到当前已经连接的所有设备列表后,是通过deviceConnected函数来“处理”这些设备;当有新设备连接触发设备连接事件时,也是通过deviceConnected函数来“处理”它。

 

启动并连接设备的ViewServer,获取Activities并显示列表

HierarchyViewerDirector的deviceConnected 方法,是对IDeviceChangeListener接口方法的实现,我们来看它是如何“处理”一台和adb建立连接的设备的:

public void deviceConnected(final IDevice device) { executeInBackground("Connecting device", new Runnable() { public void run() { if (DeviceSelectionModel.getModel().containsDevice(device)) { windowsChanged(device); } else if (device.isOnline()) { DeviceBridge.setupDeviceForward(device); if (!DeviceBridge.isViewServerRunning(device)) { if (!DeviceBridge.startViewServer(device)) { // Let's do something interesting here... Try again // in 2 seconds. try { Thread.sleep(2000); } catch (InterruptedException e) { } if (!DeviceBridge.startViewServer(device)) { Log.e(TAG, "Unable to debug device " + device); DeviceBridge.removeDeviceForward(device); } else { loadViewServerInfoAndWindows(device); } return; } } loadViewServerInfoAndWindows(device); } } }); }

在这个方法中做了如下事情:

1)DeviceBridge.setupDeviceForward(device) -- 把该设备的4939端口映射到本地端口。 HierarchyViewer维护一个列表 --sDevicePortMap,它记录哪个设备被映射到了哪个本地端口。

2)DeviceBridge.isViewServerRunning(device) -- 判断该设备的ViewServer是否打开。

3)DeviceBridge.startViewServer(device) -- 打开ViewServer。

4)loadViewServerInfoAndWindows(device) -- 1)获取该设备ViewServer信息,比如版本信息等 2)获取该设备其所有活动的Activities(在HierarchyView源代码中,Activities总是被命名为Windows)。

(如果读者不明白以上函数的意义,再次建议阅读<功能实现演示>)

 

让我们"Step Into”,来看看loadViewServerInfoAndWindows方法:

private void loadViewServerInfoAndWindows(final IDevice device) { ViewServerInfo viewServerInfo = DeviceBridge.loadViewServerInfo(device); if (viewServerInfo == null) { return; } Window[] windows = DeviceBridge.loadWindows(device); DeviceSelectionModel.getModel().addDevice(device, windows, viewServerInfo); if (viewServerInfo.protocolVersion >= 3) { WindowUpdater.startListenForWindowChanges(HierarchyViewerDirector.this, device); focusChanged(device); } }

 

1,DeviceBridge.loadViewServerInfo(device) -- 读取ViewServer信息。

2,DeviceBridge.loadWindows(device) -- 发送 “LIST”命令给ViewServer,读取设备所有活动的Activities。

3,DeviceSelectionModel.getModel().addDevice(device, windows, viewServerInfo) -- 更新DeviceSelectionModel数据,然后该Model将通过事件通知Views来更新显示。

 

我们到哪了?

在以上代码完成后,HierarchyViewer完成了主界面的加载,已经连接的设备及其活动的Activities显示出来了:

20120729215028656

读取Activity的控件层次图

网友评论
<