当前位置:文档之家› Android UI Framework 柯博文

Android UI Framework 柯博文

Android UI Framework 柯博文
Android UI Framework 柯博文

Table of Contents

Android UI Framework 柯博文 (1)

ActivityManager (5)

ActivityManager的作用 (5)

ActivityManager的静态类图 (5)

Proxy模式 (6)

本地代理与远端代理的Binder (7)

动态序列图 (7)

Activity启动 (10)

总结 (11)

ActivityManager範例 (11)

WindowsManager (24)

另一個 WindowManager (25)

範例 (28)

Android 单元测试 (35)

Android 單元測試 範例 (39)

“Android UI Framework应用开发技术”课程大纲

第一天– Android应用

时间 內容 备注 第一天

UI框架

#。基于Android框架层与UI相关的API进行深度解析

#。活动工作机制

#。ActivityManager工作机制

#。WindowsManager工作机制

UI设计转化为代码

#。代码审查方法,针对UI原型设计编写源代码,不同开

发者会有不同的代码方案

#。单元测试:同一个开发者找到多个UI实现方案,如何

选择最优的方案

#。提升UI运行的效率数总方法扩展功能

#。提升UI的稳定性

優化用戶使用經驗

#. APP穩定性

#. 流暢性

#. 減少等待時間

#. 使用的方便性

#. 如何改進現有代碼的效率

#. 可靠性

開發模塊化

#. 系統劃分成若干模塊的過程

#. 多種屬性,

#. 反映內部特性模塊化是另一種處理複雜系統分解

#. 基本屬性:接口、功能、邏輯、狀態,功能、狀態與接口反映模塊的外部特性,邏輯反映它的內部特性。

#. 在利用UI Framework進行UI編程的經驗與常見的問題#. 經常出現內存溢出現象

#. Java garbage collection 問題與改善方法

#. ANR, Android no response 問題與改善方法

#. 如何解決UI Code編寫質量,提升Android應用的可靠性#.將UI編程與UI Framework深度結合。

#. 修改Android UI Framework

#. 自製UI Framework

#. 打包與分享UI Framework

#. 打包JAR

Android 單元測試

#. 穩定性測試

#. 速度測試

#. CPU 使用測試

針對問題點改善的幾種方法

#. 軟件寫法影響速度

#. 數種不常犯的不好寫法

#. 改善方法

#. JAVA 上不良的寫code 方法

ActivityManager

ActivityManager在操作系统中有重要的作用,本文利用操作系统源码,逐步理清ActivityManager的框架,并从静态类结构图和动态序列图两个角度分别进行剖析,从而帮助开发人员加强对系统框架及进程通信机制的理解。

ActivityManager的作用

参照SDK的说明,可见ActivityManager的功能是与系统中所有运行着的Activity交互提供了接口,主要的接口围绕着运行中的进程信息,任务信息,服务信息等。比如函数getRunningServices()的源码是: public List getRunningServices(int maxNum)

throws SecurityException {

try {

return (List)ActivityManagerNative.getDefault()

.getServices(maxNum, 0);

} catch (RemoteException e) {

// System dead, we will be dead too soon!

return null;

}

}

从中可以看到,ActivityManager的大多数功能都是调用了ActivityManagerNative类接口来完成的,因此,我们寻迹来看ActivityManagerNative的代码,并以此揭示ActivityManager的整体框架。

ActivityManager的静态类图

通过源吗,可以发现ActivityManagerNative类的继承关系如下:

public abstract class ActivityManagerNative extends Binder implements IActivityManager

继承自Binder类,同时实现了IActivityManager接口。

同样的,我们继续沿Binder和IActivityManager上溯,整理出如下图所示的类结构图。

在这张图中,绿色的部分是在SDK中开放给应用程序开发人员的接口,蓝色的部分是一个典型的Proxy 模式,红色的部分是底层的服务实现,是真正的动作执行者。这里的一个核心思想是Proxy模式,我们接下来对此模式加以介绍。

Proxy模式

Proxy模式,也称代理模式,是经典设计模式中的一种结构型模式,其定义是为其他对象提供一种代理以控制对这个对象的访问,简单的说就是在访问和被访问对象中间加上的一个间接层,以隔离访问者和被访问者的实现细节。

结合上面的类结构图,其中ActivityManager是一个客户端,为了隔离它与ActivityManagerService,有效降低甚至消除二者的耦合度,在这中间使用了ActivityManagerProxy 代理类,所有对ActivityManagerService的访问都转换成对代理类的访问,这样ActivityManager 就与ActivityManagerService解耦了。这就是代理模式的典型应用场景。

为了让代理类与被代理类保持一致的接口,从而实现更加灵活的类结构,或者说完美的屏蔽实现细节,通常的作法是让代理类与被代理类实现一个公共的接口,这样对调用者来说,无法知道被调用的是代理类还是直接是被代理类,因为二者的接口是相同的。

这个思路在上面的类结构图里也有落实,IActivityManager接口类就是起的这个作用。

以上就是代理模式的思路,有时我们也称代理类为本地代理(Local Proxy),被代理类为远端代理(Remote Proxy)。

本地代理与远端代理的Binder

我们再来看一下Binder类的作用,Binder的含义可能译为粘合剂更为贴切,即将两侧的东西粘贴起来。在操作系统中,Binder的一大作用就是连接本地代理和远端代理。Binder中最重要的一个函数是:

public final boolean transact(int code, Parcel data, Parcel reply,

int flags) throws RemoteException {

……

boolean r = onTransact(code, data, reply, flags);

if (reply != null) {

reply.setDataPosition(0);

}

return r;

}

它的作用就在于通过code来表示请求的命令标识,通过data和reply进行数据传递,只要远端代理能实现onTransact()函数,即可做出正确的动作,远端的执行接口被完全屏蔽了。

当然,Binder的实现还是很复杂的,不仅是类型转换,还要透过Binder驱动进入KERNEL层来完成进程通信,这些内容不在本文的范围之内,故此处不再深入解析相应的机制。此处我们只要知道Binder 的transact()函数实现就可以了。

到此为止,我们对ActivityManager的静态类结构就分析完了,但这还不足以搞清在系统运行中的调用过程,因此,我们以下图的序列图为基础,结合源码探索一下ActivityManager运行时的机制。

动态序列图

我们以ActivityManager的getRunningServices()函数为例,对上述序列图进行解析。 public List getRunningServices(int maxNum)

throws SecurityException {

try {

return (List)ActivityManagerNative.getDefault()

.getServices(maxNum, 0);

} catch (RemoteException e) {

// System dead, we will be dead too soon!

return null;

}

}

可以看到,调用被委托到了ActivatyManagerNative.getDefault()。

static public IActivityManager asInterface(IBinder obj)

{

……

return new ActivityManagerProxy(obj);

}

static public IActivityManager getDefault()

{

……

IBinder b = ServiceManager.getService("activity");

gDefault = asInterface(b);

return gDefault;

}

从上述简化后的源码可以看到,getDefault()函数返回的是一个ActivityManagerProxy对象的引用,也就是说,ActivityManager得到了一个本地代理。

因为在IActivityManager接口中已经定义了getServices()函数,所以我们来看这个本地代理对该函数的实现。

public List getServices(int maxNum, int flags) throws RemoteException {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

……

mRemote.transact(GET_SERVICES_TRANSACTION, data, reply, 0);

……

}

从这个代码版段我们看到,调用远端代理的transact()函数,而这个mRemote就是ActivityManagerNative的Binder接口。

接下来我们看一下ActivityManagerNative的代码,因为该类是继承于Binder类的,所以transact的机制此前我们已经展示了代码,对于该类而言,重要的是对onTransact()函数的实现。

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)

throws RemoteException {

switch (code) {

case GET_SERVICES_TRANSACTION: {

……

List list = getServices(maxNum, fl);

……

return true;

}

……

}

return super.onTransact(code, data, reply, flags);

}

在onTrasact()函数内,虽然代码特别多,但就是一个switch语句,根据不同的code命令进行不同的处理,比如对于GET_SERVICES_TRANSACTION命令,只是调用了getServices()函数。而该函数的实现是在ActivityManagerService类中,它是ActivityManagerNative的子类,对于该函数的实现细节,不在本文中详细分析。

Activity启动

在经过前文的学习以后,我们一起来整理一下Activity的启动机制。就从Activity的startActivity()函数开始吧。

startActivity()函数调用了startActivityForResult()函数,该函数有源码如下:

public void startActivityForResult(Intent intent, int requestCode) {

……

Instrumentation.ActivityResult ar =

mInstrumentation.execStartActivity(

this, mMainThread.getApplicationThread(), mToken, this,

intent, requestCode);

……

}

可见,功能被委托给Instrumentation对象来执行了。这个类的功能是辅助Activity的监控和测试,在此我们不详细描述,我们来看它的execStartActivity()函数。

public ActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, Activity target,

Intent intent, int requestCode) {

……

try {

int result = ActivityManagerNative.getDefault()

.startActivity(whoThread, intent,

intent.resolveTypeIfNeeded(who.getContentResolver()),

null, 0, token, target != null ? target.mEmbeddedID : null,

requestCode, false, false);

checkStartActivityResult(result, intent);

} catch (RemoteException e) {

}

return null;

}

在这个函数里,我们看到了前文熟悉的ActivityManagerNative.getDefault(),没错,利用了ActivityManagerService。通过前文的线索,利用Proxy模式,我们可以透过ActivityManagerProxy,通过Binder的transact机制,找到真正的动作执行者,即ActivityManagerService类的startActivity()函数,并沿此线索继续追踪源码,在startActivityLocked()函数里边看到了mWindowManager.setAppStartingWindow的语句调用,mWindowManager是WindowManagerService对象,用于负责界面上的具体窗口调试。

通过这样的源码追踪,我们了解到了Activity启动的底层实现机制,也加深了对Proxy模式和Binder 机制的理解。从而为学习其他框架打下了基础。

总结

本文从静态类结构和动态类结构两个角度分析了ActivityManager的框架,兼顾了Binder机制和代理模式在进程间通信的机理,对帮助开发人员深化操作系统的结构和框架具有一定的指导作用。

ActivityManager範例

範例: ActivityManagerTool

2.0api. android.app, activity api. ActivityManager doc,

windows app. app process.

ActivityManager device con figuration attributes,process memory information,recently launched tasks,running application processes,running service,running tasks:

:

Java代码

1.ActivityManager activityManager = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);

2.

3.ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();

4.

5.Debug.MemoryInfo[] processMemoryInfo = activityManager.getProcessMemoryInfo(processIds);

6.

7.List runningServiceInfos = activityManager.getRunningServices(MaxValue);

8.

9.List runningTaskInfos = activityManager.getRunningTasks(MaxValue);

, ,( , process).

application, Task android.Manifest.permission.GET_TASKS. , app :

1. app

2, listitem

3, detail:

4, stop:

stop runningAppProcess stop

:stop stop app, stop runningAppProcess app improtance, importance<500stop.

5, about, , :

app RunningAppProcess. android android.widget.TabHost ,android.widget.Toast Toast,android.content.DialogInterface .

ActivityManagerTool.java

package wdq.study.android.example.activitymanager;

import java.util.List;

import java.util.Vector;

import android.app.ActivityManager;

import android.app.AlertDialog;

import android.app.TabActivity;

import android.app.ActivityManager.RunningAppProcessInfo;

import android.content.DialogInterface;

import android.content.Intent;

import android.os.Bundle;

import android.os.Process;

import https://www.doczj.com/doc/0515729661.html,youtInflater;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.TabHost;

import android.widget.Toast;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.AdapterView.OnItemLongClickListener;

import android.widget.AdapterView.OnItemSelectedListener;

public class ActivityManagerTool extends TabActivity implements

OnItemSelectedListener, OnItemClickListener, OnItemLongClickListener { /** Called when the activity is first created. */

ConstantVO constant = new ConstantVO();

Vector vec = new Vector();

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

TabHost tabHost = getTabHost();

LayoutInflater.from(this).inflate(https://www.doczj.com/doc/0515729661.html,yout.main,

tabHost.getTabContentView(), true);

tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("RunningAppProcess")

.setContent(R.id.view1));

tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("RunningService")

.setContent(R.id.view2));

tabHost.addTab(tabHost.newTabSpec("tab3").setIndicator("About")

.setContent(R.id.view3));

ListView runningapps = (ListView) findViewById(R.id.view1);

ActivityManager activityManager = (ActivityManager) this

.getSystemService(ACTIVITY_SERVICE);

List runningappPrcessinfos = activityManager

.getRunningAppProcesses();

//Vector vec = new Vector();

for (RunningAppProcessInfo info : runningappPrcessinfos) {

RunningAppProcessVO vo = new RunningAppProcessVO();

vo.importance = info.importance;

vo.processName = info.processName;

vo.pid = info.pid;

vo.importanceReasonCode = info.importanceReasonCode;

vo.importanceReasonComponent = info.importanceReasonComponent;

vo.importanceReasonPid = info.importanceReasonPid;

vo.lru = info.lru;

vo.pkgList = info.pkgList;

vo.uid = info.uid;

vec.add(vo);

}

ArrayAdapter runningAppsAdapter = new ArrayAdapter(

android studio 控件常用属性

android studio 控件常用属性 下面是RelativeLayout各个属性 1.android:layout_above="@id/xxx" --将控件置于给定ID控件之上 2.android:layout_below="@id/xxx" --将控件置于给定ID控件之下 3. android:layout_toLeftOf="@id/xxx" --将控件的右边缘和给定ID控件的左边缘对齐 4.android:layout_toRightOf="@id/xxx" --将控件的左边缘和给定ID控件的右边缘对齐 5. android:layout_alignLeft="@id/xxx" --将控件的左边缘和给定ID控件的左边缘对齐 6.android:layout_alignTop="@id/xxx" --将控件的上边缘和给定ID控件的上边缘对齐 7.android:layout_alignRight="@id/xxx" --将控件的右边缘和给定ID控件的右边缘对齐 8.android:layout_alignBottom="@id/xxx" --将控件的底边缘和给定ID控件的底边缘对齐 9.android:layout_alignParentLeft="true" --将控件的左边缘和父控件的左边缘对齐 10. android:layout_alignParentTop="true" --将控件的上边缘和父控件的上边缘对齐 11. android:layout_alignParentRight="true" --将控件的右边缘和父控件的右边缘对齐 12.android:layout_alignParentBottom="true" --将控件的底边缘和父控件的底边缘对齐 13.android:layout_centerInParent="true" --将控件置于父控件的中心位置 14.android:layout_centerHorizontal="true" --将控件置于水平方向的中心位置 15.android:layout_centerVertical="true" --将控件置于垂直方向的中心位置 android:layout_width 设置组件的宽度 android:layout_height 设置组件的高度 android:id 给组件定义一个id值,供后期使用 android:background 设置组件的背景颜色或背景图片 android:text 设置组件的显示文字 android:textColor 设置组件的显示文字的颜色 android:layout_below 组件在参考组件的下面 android:alignTop 同指定组件的顶平行

Android应用开发基础习题集

任务一 Android开发环境的搭建 第一部分知识回顾与思考 1.Android的四层架构分别包括哪几层分别起到什么作用 答:Linux内核层(Linux Kernel):基于Linux内核,内核为上层系统提供了系统服务。 系统库层(Libraries):系统库基于C/C++语言实现,通过接口向应用程序框架层提供编程接口。 应用框架层(Application Framework):为开发者提供了一系列的Java API,包括图形用户界面组件View、SQLite数据库相关的API、Service组件等。 应用程序层(Applications):包含了Android平台中各式各样的应用程序。 第二部分职业能力训练 一、单项选择题(下列答案中有一项是正确的,将正确答案填入括号内) 1.Android四层架构中,应用框架层使用的是什么语法( C ) A.C B.C++ C.Java D.Android 2.Android四层架构中,系统库层使用的是什么语法( B ) A.VB B.C /C++ C.Java D.Android 3.应用程序员编写的Android应用程序,主要是调用( B )提供的接口进行实现。 A.应用程序层 B.应用框架层 C.应用视图层 D.系统库层 二、填空题(请在括号内填空) 1.在Android智能终端中,有很多应用如拍照软件、联系人管理软件,它们都属于Android的(应用程序)层。 2.为了让程序员更加方便的运行调试程序,Android提供了(模拟器),可以方便的将程序运行其上,而不要实际的移动终端。 3.为了支持Java程序运行,我们需要安装(JDK)。 三、简答题 1.简述Android开发环境安装的步骤。 答:下载并安装JDK,配置JDK的环境变量; 从Anroid官网上下载Android开发组件(包含Eclipse和Android SDK、ADT); 安装Android开发环境(包括配置Android SDK的环境变量、打开Eclipse通过菜单设定Android SDK 路径)。 2.简述Android应用程序创建和运行的步骤。 答:通过菜单创建Android应用程序,设置应用程序名、Android版本等基本信息。

Android常用控件

《Android基础应用》 Android常用控件 ?本章任务 ?使用Android开发使用时间组件 ?使用Android开发使用进度条组件 ?使用Android开发创建底部选项卡 ?本章目标 ?了解Android的组件层次结构 ?掌握常用的日期时间类控件 ?掌握常用的几个容器组件 1.Android组件的层次结构 UI组件都是View的子类,View有很多子类,它们之间存在树状的继承关系View及其子类结构图

TextView及其子类结构图

ViewGroup及其子类结构图 其下的子类一般作为容器或布局来使用 FrameLayout及其子类结构图 其下的子类通常作为容器或布局来使用

2.时间控件 2.1日期时间选择器 DatePicker组件可用于输入日期,TimePicker组件可用来选择时间,只能输入小时和分,默认12小时制 DatePicker ●使用onDateChangedListener监听器来获取用户的日期选择 ●使用init对组件进行初始化 ●使用getYear,getMonth,getDayOfMonth方法获得用户选择的年,月,日 TimePicker ●使用onTimeChangedListener监听器获取用户的时间选择 ●使用setIs24HourView设置是否以24小时制显示 ●使用getCurrentHour获得当前的小时数 ●使用getCurrentMinute获得当前的分钟数 示例

示例的实现结果

2.2时钟组件 AnalogClock组件用来以表盘的方式显示当前时间,该表只有时针和分针,DigitClock组件以数字的方式显示当前时间可以显示时分秒,由于DigitClock继承TextView,可以使用TextView 的属性 示例

android常用控件大全

android常用控件大全 在Android中使用各种控件(View) DatePicker-日期选择控件 TimePicker-时间选择控件 ToggleButton-双状态按钮控件 EditText-可编辑文本控件 ProgressBar-进度条控件 SeekBar-可拖动的进度条控件 AutoCompleteTextView-支持自动完成功能的可编辑文本控件 MultiAutoCompleteTextView-支持自动完成功能的可编辑文本控件,允许输入多值(多值之间会自动地用指定的分隔符分开) ZoomControls-放大/缩小按钮控件 Include-整合控件 VideoView-视频播放控件 WebView-浏览器控件 RatingBar-评分控件 Tab-选项卡控件 Spinner-下拉框控件 Chronometer-计时器控件 ScrollView-滚动条控件 在Android中使用的Layout FrameLayout:里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角 LinearLayout:里面可以放多个控件,但是一行只能放一个控件

TableLayout:这个要和TableRow配合使用,很像html里面的table AbsoluteLayout:里面可以放多个控件,并且可以自己定义控件的x,y的位置 RelativeLayout:里面可以放多个控件,不过控件的位置都是相对位置 (Android界面布局好像还可以直接引用一些view,如ScrollView等) 常用控件: 1,EditText 主要函数:setText/getText设置/获取文本内容,setHint设置缺省显示内容; 2,RadioGroup,RadioButton RadioButton的isChecked()判断是否被选中 获取选中RadioButon的ID:设置 RadioGroup.setOnCheckedChangeListener方法 publiconCheckedChanged(RadioGroupgroup,intcheckedId)//checkedId 是选中RadioButton的ID 3,CheckBox isChecked()判断是否被选中 setOnCheckedChangeListener方法监视选中状态改变情况 4,Spinner a,显示数据 1),硬编码加载 通过setAdapter方法设置类型为 ArrayAdapter(Contextcontext,inttextViewResId,String[]objects) textViewResourceId:显示内容的ViewID默认设置为 https://www.doczj.com/doc/0515729661.html,yout.simple_spinner_item

Android应用开发基础习题

-- 任务一Android 开发环境的搭建 第一部分知识回顾与思考 1.Android 的四层架构分别包括哪几层?分别起到什么作用? 答:Linux 内核层(Linux Kernel ):基于Linux 内核,内核为上层系统提供了系统服务。 系统库层(Libraries ):系统库基于C/C++ 语言实现,通过接口向应用程序框架层提供编程接口。 应用框架层(Application Framework ):为开发者提供了一系列的Java API,包括图形用户界面组件

View 、SQLite 数据库相关的API 、Service 组件等。 应用程序层(Applications ):包含了Android 平台中各式各样的应用程序。 第二部分职业能力训练 一、单项选择题(下列答案中有一项是正确的,将正确答案填入括号内) 1.Android 四层架构中,应用框架层使用的是什么语法?(C)A .CB .C++C.Java D.Android 2.Android 四层架构中,系统库层使用的是什么语法?(B)A .VBB.C /C++C.Java D .Android 3.应用程序员编写的Android 应用程序,主要是调用(B)提供的接口进行实现。 A .应用程序层DCB.应用框架层.应用视图层.系统库层

二、填空题(请在括号内填空) 1.在Android 智能终端中,有很多应用如拍照软件、联系人管理软件,它们都属于Android 的(应用程 序)层。 2.为了让程序员更加方便的运行调试程序,Android 提供了(模拟器),可以方便的将程序运行其上, 而不要实际的移动终端。 程序运行,我们需要安装(Java 3.为了支持)。JDK 三、简答题 1.简述Android 开发环境安装的步骤。 答:下载并安装JDK ,配置JDK 的环境变量; 从Anroid 官网上下载Android 开发组件(包含Eclipse 和

实验二 android基本控件实验

实验二 android基本控件实验 【目的】 熟悉Android常用控件的基本操作,掌握它们的基本使用方法。了解控件之间的构成关系,熟悉适配器的使用原理。 【要求】 1、了解控件的继承关系; 2、掌握适配器的使用; 3、掌握信息提示的实现机制; 4、实现基本界面。 【原理】 1.控件类之间的关系 android.view.View类(视图类)呈现了最基本的UI构造块。View类是Android中的一个超类,几乎包含了所有的屏幕类型,主要负责绘制和事件处理。 Android中控件类的扩展结构如图所示。 View有众多的扩展者,它们大部分是在android.widget包中,这些继承者实际上就是Android 系统中的“控件”。View实际上就是各个控件的基类,创建交互式的图形用户界面的基础。View的直接继承者包括文本视图(TextView)、图像视图(ImageView)、进度条(ProgressBar)等。它们各自又有众多的继承者。每个控件除了继承父类功能之外,一般还具有自己的公有 方法、保护方法、XML属性等。 在Android中使用各种控件的一般情况是在布局文件中可以实现UI的外观,然后在Java文件中实现对各种控件的控制动作。控件类的名称也是它们在布局文件XML中使用的标签名称。

2.控件通用行为和属性 View是Android中所有控件类的基类,因此View中一些内容是所有控件类都具有的通用行为和属性。 提示:由于Java语言不支持多重继承,因此Android控件不可能以基本功能的“排列组合”的方式实现。在这种情况下,为了实现功能的复用,基类的功能往往做得较强,作为控件的祖先类,View所实现的功能也是最多的。 控件类经常在布局文件中使用,因此其可以使用XML属性(XMLAttributes),和Java代码经常具有对应关系。 View作为各种控件的基类,其XML属性所有控件通用,XML属性及其对应的方法如表1所示。 表1 View中的XML属性及其对应的方法 其中,android:id表示控件的标识,通常需要在布局文件中指定这个属性。View中与控件标识相关的几个方法如下所示: public int getId() // 获得控件的id(int类型)

Android基础-控件的使用

创建控件并添加监听器的过程: 1.xml中定义控件(

相关文档 最新文档