<?xml version="1.0" encoding="UTF-8"?><!-- generator="WordPress/2.7.1" -->
<rss version="0.92">
<channel>
	<title>hkbarton - Undefined Life</title>
	<link>http://hkbarton.sacredfir.com</link>
	<description>Undefined Life</description>
	<lastBuildDate>Mon, 26 Apr 2010 02:12:39 +0000</lastBuildDate>
	<docs>http://backend.userland.com/rss092</docs>
	<language>en</language>
	
	<item>
		<title>新的开始</title>
		<description>已经很长时间没有更新这里了，因为这段时间我和我的朋友们一直在酝酿着一个很重要的计划，现在我们已经准备好了。

接下来的很长一段时间，我的生活将发生变化，而现在，我将迎来一个新的开始。未来会面对更多的压力和挑战，结果也还是个未知数，但我知道现在更重要的是行动。

2010，新的开始，暂且在这里留下一个记号，希望1年后能给自己交出一份满意的答卷。 </description>
		<link>http://hkbarton.sacredfir.com/?p=105</link>
			</item>
	<item>
		<title>[Android研究手记3]组件间的交互和进程间IPC通信</title>
		<description>在Android中窗体与窗体之间如何互相调用和交换数据？窗体（Activity）和后台的服务（Service）如何通信？基于Unix（Linux）的系统都有一个很优秀的传统，就是倡导非常轻便的进程间通信（IPC）机制；倡导进程通过IPC来互相协作；倡导功能单一，小巧而强壮的进程，而不是又大又复杂的“万金油”。同样，在Android中我们可以将我们的Activity和Service放在不同的进程中运行，我们可以在我们的Task 中加载其他进程的Activity，这些机制都鼓励我们“尽量利用已有的功能，利用IPC和包含这些已有功能的程序协作，来完成一个完整的应用”，例如在我们的程序中充分利用Google Map的相关窗体和服务。所有这些都建立在一套轻便好用的IPC机制上。

Android的组件和进程间通信都建立在一种基于称为Intent的消息基础之上。Intent就是一种消息，它包含了两个重要的内容：1. 消息的目的，即这个消息是发给哪个组件的？（消息的目的中不会包含“消息是发给哪个进程”这样的信息，这里Android有意淡化进程的概念，而只让我们关心组件，因为了解太多关于进程的具体信息会加大复杂度，而又如何做到进程间的消息传递呢？下文会说到一种Android中关于这点比较特别的设计方式，我认为是一种简捷有用又符合手机特点的设计）；2. 消息所携带的数据内容，即需要传递给目标的数据。下面是一个简单的利用Intent来启动一个Service并向其传递数据的代码示例：

Intent serviceIntent = new Intent(context, svrMain.class);
serviceIntent.putExtra("Network_Report", networkStatus);
context.startService(serviceIntent);

上面的代码首先构造了一个Intent对象，并在构造的时候指定了这个Intent的目的地，即“svrMain.class”，表示这个Intent是要传递给一个类名叫svrMain的Service。然后向这个Intent中放入了一个数据，数据的key为“Network_Report”，value为一个叫networkStatus的int类型变量，用来指明当前网络的状态。最后我们使用系统提供的上下文API，将这个Intent传递给指定的Service。

Intent的消息目的地分为两种模式，一种是显式的，一种是隐式的。我们上面的例子中看到的就是一个显式消息的例子。显式消息直接指定消息目的地组件的类元信息，例如上面例子中svrMain就是我们写的一个类名为svrMain的Service，class操作符就是获取其类元信息。这种模式的消息由于已经确切知道了消息目标的确切信息，所以只适用于同一进程内的不同组件之间通信，例如打开一个子窗体，和同一进程中的service通信等。对应的，隐式消息就一般用于跨进程的通信了，隐式消息没有确定的消息目的地，除了数据外，隐式消息只是包含了一些用于表征消息特征的描述字段。而一些需要收到某种特定特征消息的某个程序中的某个组件，需要通过在其所在程序的AndroidMainifest.xml中注册一种被称为intent-filter的消息特征筛选器，然后Android系统会按照一定的匹配规则来匹配发出的消息特征和所有拥有响应这种特征的intent-filter的组件（无论是同一进程内的组件还是不同程序中的组件），匹配到的组件就会接受到相应的消息。前面的描述多少有些拗口，我们举个实际的例子来说明，如果我们想开启一个子窗体（无论这个窗体来自同一进程还是不同进程），我们除了使用显式消息外，我们还可以使用隐式消息：

Intent openSomeDiagIntent = new Intent();
openSomeDiagIntent.setAction("edwin.demo.fooActivity");
this.startActivity(openSomeDiagIntent);

上面的隐式消息不包含具体的目的地，而是仅包含一个名位“Action”的特征字符串，Action就是上文所说的Intent特征的一种。从字面上来理解，可以理解为这个消息所代表的是完成某一个动作的含义，由action来标明动作的名字。所有能够处理这种动作的Activity都可以收到该消息。对应的，可能在同一个程序或者另外的某个程序的AndroidMainifest.xml中声明了下面这样的一个Activity：

&#60;activity android:name=".fooActivity"&#62;
&#60;intent-filter&#62;
&#60;action android:name="edwin.demo.fooActivity" /&#62;
&#60;/intent-filter&#62;
&#60;/activity&#62;

那么这就表示这个Activity能够收到并处理action为“edwin.demo.fooActivity”的消息。所以上面的代码串起来的效果就是，打开了这个名为.fooActivity的窗口，无论这个窗口是在当前的进程中还是另外的一个程序中。

除了Action这种消息特征外，Intent还有category，data这两个特征描述属性。Category同样是一个字符串，从字面上理解就是“消息的分类特征”。从程序上看其和Action的不同在于，一个Intent只能有惟一的一个Action名称，但是却可以包含多个Category字符串；一个Intent-Filter可以包含多个Action节点但至少要包含一个，另一方面一个Intent-Filter可以包含零到多个Category节点。Android在做Intent-Filter匹配的时候，Intent的Action属性匹配到Intent-Filter中的任何一个action节点，就表明拥有这个Intent-Filter的组件能够处理这种消息；而对于Category来讲一个Intent中的所有的Category都必须存在于Intent-Filter中的Category节点中时，才表明匹配成功。Data属性可以描述一个Intent所要传递的数据类型和URI，每一个Intent只能包含一个Data属性。其中数据的类型使用MIME类型描述方式来描述，例如video/mpeg表示编码格式为mpeg的视频，这里也可以使用通配符，例如video/*表示任意格式的视频文件类型；数据的URI由scheme（协议），host，port，path四部分组成：scheme://host:port/path，例如http://test.com:8080/file/file1 或者content://edwin.demo.contentProvider:100/forder/content1，其中path部分也是可以支持通配符的。Data属性是一个很有用的描述特征，例如下面这样的一个包含data节点的Intent-Filter：

&#60;activity android:name=".actHttpVideoMan"&#62;
&#60;intent-filter&#62;
&#60;action android:name="edwin.demo.actHttpVideoMan.Main" /&#62;
&#60;data android:scheme="http" android:type="video/*" /&#62;
&#60;/intent-filter&#62;
&#60;/activity&#62;

它表示窗体actHttpVideoMan能够处理来自web服务器的视频文件。这样的filter有什么作用呢？最典型的情况就是配合浏览器工作。浏览器在打开一个链接的时候首先会尝试显示这个链接对应的html页面，如果这个链接不是一个html页面，而是一个视频文件或者其他浏览器本身不能处理的格式的话，浏览器会使用隐式消息尝试开启一个能够处理这种数据格式的Activity来处理，浏览器发出的隐式消息就是一个包含data属性，其中URI scheme为http，数据类型为video/*的消息，如果有能够匹配这个intent的组件，例如我们上面的那个activity，浏览器就会启动这个窗体，接着这个窗体会根据data属性指定的URI去播放在线视频，如果没有可以处理这个intent的Activity，浏览器才会调用下载管理器下载文件。

隐式消息这个设计简单有效，它忽略了进程的细节，让IPC在一个更高的更接近人脑思维模式的层次工作，让系统中的不同进程协作看起来就像是同一程序中的协作一样，这种简单的IPC机制在很大的程度上鼓励我们和其他进程协作，通过协作的进程来完成一个复杂的任务，而不是把什么功能都做到一个大而全的程序里面。不过上文还有一些细节没有提到，例如如果一个intent有多个可匹配的处理组件，系统如何处理？这就要分响应消息的组件类型来说了，如果是service，那么这些service都可以启动并处理消息，如果是Activity，则android会弹出一个对话框让用户进行选择。比如我们安装了多个可以处理在线视频的软件，当我们在浏览器中点击一个在线视频的链接时，系统会让用户选择使用哪个软件来观看。另外大家一定会想到安全性的问题，如果不同进程间的组件可以通过隐式消息互相通信，那我们的程序不是可以轻易调用到其他的程序或者系统中的一些敏感程序的组件，这样会不会很不安全呢？其实Android在安全方面有一个统一，完备和轻便的安全策略模型，Intent的安全自然是被考虑在内的，关于android的安全模型我会在后续的系列blog中专门说明。

最后，除了Intent这种基于消息的进程内和进程间通信模型外，android中也有一种相比起来稍显笨重一些的IPC机制，它采用类似远程方法调用的方案，通过接口定义文件AIDL来定义一个IPC接口，然后通过接收方实现接口，调用方调用接口的本地代理实现来完成IPC。这种模型只适用于Activity和Service间的通信，之所以需要这种稍显重量的模式，是因为Activity除了发送intent去启动一个service外，可能还需要能够在Service的运行过程中连接到service，对Service发送一些控制请求。例如音乐播放程序，其后台的播放服务往往独立运行，以方便我们在使用其他程序界面时也能听到音乐。同时这个后台播放服务也会定义一个控制接口，包含比如播放，暂停，快进之类的方法，任何时候播放程序的界面都可以通过使用bindService API连接到播放服务，获取这个接口的包含IPC细节的实现代理，通过这组控制接口方法对其进行控制，这时这种IPC的方案就显的更方便更直观一些了。有关使用AIDL这种IPC的更详细描述，Google的官方文档已做了详细的讲解。

下篇预告：《[Android研究手记4] Service的运行时生命周期模型》 </description>
		<link>http://hkbarton.sacredfir.com/?p=93</link>
			</item>
	<item>
		<title>难用到令人抓狂的w3c标准DOM解析API</title>
		<description>被.Net毒害太深，以至于离开.Net就发现自己原来是个菜鸟，一件在.net中可以很简单完成的事情，到了java下面可能就要让你抓狂。要解析Xml，Android提供的jar中包含了最基本的w3c DOM API和标准的SAX（Simple API for XML），因为常年沉侵在.Net的温床中，导致了对这些标准API的从来不闻不问，当使用到这些API时，也就只有抓狂了。。。没有XPath支持不说，看看下面这个Xml片段在标准DOM API中的Node结构便知道抓狂的含义了：

&#60;root&#62;
&#60;!--xxx--&#62;
&#60;sub&#62;123&#60;/sub&#62;
&#60;/root&#62;

首先，DOM里的Node不是在.net理解中的&#60;a&#62;&#60;/a&#62;这个叫一个node，任何xml中的元素都是node，&#60;a&#62;&#60;/a&#62;只是一种type为ELEMENT_NODE的node，此外还有很多type的node，常用的还有TEXT_NODE，上面XML片段的Node模型如下（*表示缩进）：

root (NodeType: ELEMENT_NODE)
****\n (NodeType: TEXT_NODE，抓狂1：&#60;root&#62;后面的换行符\n也是一个Node！一个文本类型的Node，标准API中可以用getNodeValue()得到“\n”)
****&#60;!--xxx--&#62; (NodeType: COMMENT_NODE)
****\n (NodeType: TEXT_NODE，还是\n)
****sub (NodeType: ELEMENT_NODE)
********123 (NodeType: TEXT_NODE，抓狂2：&#60;sub&#62;中的文字也是一个node，getNodeValue()得到"123"。这个文字不是sub节点的nodeValue，而是一个新的node，sub节点的nodeValue会直接返回null)
****\n (NodeType: TEXT_NODE，sub节点后的换行符)

如果之前不了解w3c标准DOM API，很抱歉，上面的知识得花费你个把小时调试你才能学会。幸运的是除了标准API，我们还有更多的选择，DOM4J就是一个不那么让人抓狂的开源XML解析工具包。 </description>
		<link>http://hkbarton.sacredfir.com/?p=83</link>
			</item>
	<item>
		<title>[Android研究手记2]Activity的运行时生命周期模型</title>
		<description>由于在Android中，进程的生命周期大多数时候是由系统管理的；另外也由于手机应用的一些特殊性，所以我们需要更多的去关注各个Android Component的运行时生命周期模型。（所谓手机应用的特殊性主要是指这样2点： 1. 手机应用的大多数情况下我们只能在手机上看到一个程序的一个界面 ，用户除了通过程序界面上的功能按钮来在不同的窗体间切换，还可以通过Back键和Home键来返回上一个窗口，而用户使用Back或者Home的时机是非常不确定的，任何时候用户都可以使用Home或Back来强行切换当前的界面。 2. 往往手机上一些特殊的事件发生也会强制的改变当前用户所处的操作状态，例如无论任何情况，在手机来电时，系统都会优先显示电话接听界面。）了解这些Component的生命周期模型一方面是让我们对软件在手机中的运行情况做到心中有数，更重要的，对于程序开发来说，生命周期中的每一个关键事件都会有我们可以覆写于各种Component对应基类型的事件处理方法，了解各Component的生命周期就是让我们在开发程序时明白我们该怎样去编写各种事件的处理代码。例如Activity的Create，就会有对应的事件处理函数onCreate，我们可以从Activity基类覆写这个事件处理函数完成我们需要的相关事件处理：

public class actMain extends Activity {
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
…… //我们的事件处理代码
}
……
｝

这篇Post我们就来看看最常用的Activity的运行时生命周期模型（Service的运行时生命周期模型在下一篇讲述了如何启动一个Service并和其通信后再做描述）。 Activity的生命周期模型在Google提供的官方文档上有比较详细的一个图示（请自行翻墙查看）。其一共包含7个我们需要关心的关键事件，下面对其分别详细说明（文字中的粗体字表示后文中会经常用到的概念在第一次出现时会给出解释，之后后文不再详细说明）：

1.	void onCreate(Bundle savedInstanceState)
当Activity被第首次加载时执行。我们新启动一个程序的时候其主窗体的onCreate事件就会被执行。如果Activity被销毁后（onDestroy后），再重新加载进Task时，其onCreate事件也会被重新执行。注意这里的参数savedInstanceState（Bundle类型是一个键值对集合，大家可以看成是.Net中的Dictionary）是一个很有用的设计，由于前面已经说到的手机应用的特殊性，一个Activity很可能被强制交换到后台（交换到后台就是指该窗体不再对用户可见，但实际上又还是存在于某个Task中的，比如一个新的Activity压入了当前的Task从而“遮盖”住了当前的Activity，或者用户按了Home键回到桌面，又或者其他重要事件发生导致新的Activity出现在当前Activity之上，比如来电界面），而如果此后用户在一段时间内没有重新查看该窗体（Android通过长按Home键可以选择最近运行的6个程序，或者用户直接再次点击程序的运行图标，如果窗体所在的Task和进程没有被系统销毁，则不用重新加载Process, Task和Task中的Activity， 直接重新显示Task顶部的Activity， 这就称之为重新查看某个程序的窗体），该窗体连同其所在的Task和Process则可能已经被系统自动销毁了，此时如果再次查看该窗体，则要重新执行onCreate事件初始化窗体。而这个时候我们可能希望用户继续上次打开该窗体时的操作状态进行操作，而不是一切从头开始。例如用户在编辑短信时突然来电，接完电话后用户又去做了一些其他的事情，比如保存来电号码到联系人，而没有立即回到短信编辑界面，导致了短信编辑界面被销毁，当用户重新进入短信程序时他可能希望继续上次的编辑。这种情况我们就可以覆写Activity的void onSaveInstanceState(Bundle outState)事件，通过向outState中写入一些我们需要在窗体销毁前保存的状态或信息，这样在窗体重新执行onCreate的时候，则会通过savedInstanceState将之前保存的信息传递进来，此时我们就可以有选择的利用这些信息来初始化窗体，而不是一切从头开始。

2.	void onStart()
onCreate事件之后执行。或者当前窗体被交换到后台后，在用户重新查看窗体前已经过去了一段时间，窗体已经执行了onStop事件，但是窗体和其所在进程并没有被销毁，用户再次重新查看窗体时会执行onRestart事件，之后会跳过onCreate事件，直接执行窗体的onStart事件。

3.	void onResume()
onStart事件之后执行。或者当前窗体被交换到后台后，在用户重新查看窗体时，窗体还没有被销毁，也没有执行过onStop事件（窗体还继续存在于Task中），则会跳过窗体的onCreate和onStart事件，直接执行onResume事件。

4.	void onPause()
窗体被交换到后台时执行。

5.	void onStop()
onPause事件之后执行。如果一段时间内用户还没有重新查看该窗体，则该窗体的onStop事件将会被执行；或者用户直接按了Back键，将该窗体从当前Task中移除，也会执行该窗体的onStop事件。

6.	void onRestart()
onStop事件执行后，如果窗体和其所在的进程没有被系统销毁，此时用户又重新查看该窗体，则会执行窗体的onRestart事件，onRestart事件后会跳过窗体的onCreate事件直接执行onStart事件。

7.	void onDestroy()
Activity被销毁的时候执行。在窗体的onStop事件之后，如果没有再次查看该窗体，Activity则会被销毁。

最后用一个实际的例子来说明Activity的各个生命周期。假设有一个程序由2个Activity A和B组成，A是这个程序的启动界面。当用户启动程序时，Process和默认的Task分别被创建，接着A被压入到当前的Task中，依次执行了onCreate, onStart, onResume事件被呈现给了用户；此时用户选择A中的某个功能开启界面B，界面B被压入当前Task遮盖住了A，A的onPause事件执行，B的onCreate, onStart, onResume事件执行，呈现了界面B给用户；用户在界面B操作完成后，使用Back键回到界面A，界面B不再可见，界面B的onPause, onStop, onDestroy执行，A的onResume事件被执行，呈现界面A给用户。此时突然来电，界面A的onPause事件被执行，电话接听界面被呈现给用户，用户接听完电话后，又按了Home键回到桌面，打开另一个程序“联系人”，添加了联系人信息又做了一些其他的操作，此时界面A不再可见，其onStop事件被执行，但并没有被销毁。此后用户重新从菜单中点击了我们的程序，由于A和其所在的进程和Task并没有被销毁，A的onRestart和onStart事件被执行，接着A的onResume事件被执行，A又被呈现给了用户。用户这次使用完后，按Back键返回到桌面，A的onPause, onStop被执行，随后A的onDestroy被执行，由于当前Task中已经没有任何Activity，A所在的Process的重要程度被降到很低，很快A所在的Process被系统结束。

下篇预告：《[Android研究手记3] Component间的交互和进程间IPC通信》 </description>
		<link>http://hkbarton.sacredfir.com/?p=66</link>
			</item>
	<item>
		<title>[Android研究手记1]基本概念和模型</title>
		<description>前几天已经给大家做过广告了，从这篇开始，我准备每周更新一篇Android研究手记，分享我学习Android开发过程中的一些经验和知识，同时也是给自己进行备忘。由于我研究Android的过程也是我在Android上的第一个完整项目BlogMessage的开发过程，所以我尽量将这个实际项目的开发过程穿插在整个系列中，并试图以此将Google提供的各种文档中比较难理解的部分用尽量简单的方式表达出来。就不继续打广告了，下面进入正题：

学习在一个全新的平台上开发最重要的第一步是什么？我觉得当然不是语言的问题，也更不是工具的问题。学习Windows开发，我们得了解Win32窗口的运行原理，消息队列等机制，不了解这些背后的机制和基本的运行模型，只靠RAD工具我们还是只能停留在普通应用的阶段。学习Web开发，不了解HTML DOM，HTTP协议原理等内容，只靠掌握如ASP.Net，JSP等厂商技术，我们也做不到Web开发的“心想事成”，“胸有成竹”；同样如Anrs Blog中说到的正则表示式的应用，我们还得了解其背后的匹配原理。所以，我觉得面对一个全新的平台，我们得首先了解其工作和运行的基本模型和原理，才能做到以后在这个平台上的“得心应手”。

Android开发平台的架构模型，Google官方已经用一个很简单的结构图清晰的进行了说明，简单来说Android开发平台就是 Linux + Google在其上自己开发的Java虚拟机和运行时 + Android SDK 构成，这些内容供我们了解就可以了。就开发一个完整的Android应用来说，我将对我们十分重要而Google官方文档又说的有些复杂的，关于一个完整的Android程序的静态组成模型，和动态运行时模型，整理成了一张图形如下，我们就从这张图说起：

点击图片看大图

各位看官先不要被图形中的生词吓死，接下来我会详细解释每一个概念。

先来看图形中的灰色部分，这部分描述了一个完整的Android应用程序可以包含的各个组成部分，我们将组成一个Android程序的组件称为Android Component（图中中间部分的基类），由若干个Android Component就组成了一个完整的Android应用程序。先看图中左下方的Activity，这个组件我们可以认为它是Windows中的窗体概念，这是Android程序的基本组成部分，也就是程序的人机交互界面。比如一个简单的短信程序就应该包含三个Activity，一个短信列表界面，一个阅读短信详细内容的界面和一个编辑短信的界面。图中左上角的Service顾名思议就是服务，一个Android程序中哪些部分是服务呢？举例来说，短信程序并不只是在我们打开短信界面的时候才去收取短信，我们退出界面后，手机仍然会去收取短信，并在新的短信到达时通知我们，所以一定有某个任务在后台运行着，这就是Service了；再比如说音乐播放功能，当我们从播放界面返回手机待机界面的时候仍然可以继续听音乐，这也是一个Service的例子。其实Activity + Service是非常常见的手机软件应用，比如我要做的BlogMessage同样也是这样的结构。左边中间部分的“Broadcast Receiver”是用于接收各种系统定义事件或自定义事件的接收器，如果我们的程序想侦测一些系统事件的发生，我们就需要写一个Broadcast Receiver。例如我们的程序想在手机打开Wifi的时候立即去刷新最新的数据，或者我们想在手机来电时执行某个动作，这些都可以由Broadcast Receiver订阅特定的事件来完成。图中左边剩下的“Content Provider”，我们可以把它理解成一种特殊的Service，一种可以给其他程序提供数据的Service，例如手机中的联系人信息，我们任何程序都可以和其通信去获取联系人的信息，这就可实现为一个典型的Content Provider。

再来看图中蓝色的部分，这是一个静态的部署概念，就如同我们.Net开发的程序集的概念一样。Apk是我们Android程序发布和部署的基本单位，一个完整的Android程序就可以打包为一个或多个Apk进行发布，我们从Android Marketing上下载安装的程序也是一个个的Apk包，我们在Eclipse 中的一个Project的最终Build结果也就是一个Apk文件。一个Apk中包含了上面介绍的4种Android Component。

最后，图中黄色的部分就是系统运行时的概念了。由于Android平台是基于Linux的，所以Process（进程）和Thread（线程）的概念和Linux中的一致，在代码中我们可以编写一个普通的Java Thread来实现多线程。需要注意的是，Android中的Process是受系统自动管理的，并不是说我们在一个程序界面中按了手机上的Back键或者Home键程序就结束了，大家也很难在Android的各种程序中找到类似Symbian程序中的“退出”功能。Android系统会给每一个进程都计算出一个“重要程度”等级，在系统运行的某个时候例如资源不足的时候，系统会根据各个进程的“重要程度”来决定先释放哪个进程。（进程“重要程度”的判断在Google的官方文档还是说的比较清楚的，实际上各个Android Component都有很完整的运行时生命周期，由于我们不太清楚进程结束的时机，了解各个Android Component的运行时生命周期以及相关事件就对我们的开发来说非常重要，我会陆续在后续的手记中详细阐述这些内容）。一个Apk中包含的Android Component在运行时可以运行在同一个进程中，也可以运行在不同的进程中，这取决于我们在Apk的AndroidManifest.xml上进行的配置（大家可以将这个AndroidManifest.xml看成是Apk的全局配制信息，其中会描述这个Apk中包含了哪些Android Component以及各个Component的运行和启动方式等，我会在后续的Post中讲解这些内容）。最后，图中下面中间部分的“Task”是Android中一个很特殊的运行时概念，也是很复杂的一个概念，Google的官方文档用了很大的篇幅来说明这个概念。它有别于进程和线程，并且只和Activity的运行时有关系。我们可以将其理解成“窗口栈”，这是由手机上的特殊操作方式所引出的概念。由于手机上的程序，用户一般只能在同一时间看到一个界面，例如在编辑短信的时候一般就不能看到短信列表的界面。而一个完整的程序一般会由多个Activity组成，所以这些Activity会在运行时随着打开的先后顺序会被放到同一个窗口栈（Task）中，当前活动窗口栈中最上面的Activity就是用户当前看到的界面，按手机上的“Back”则是销毁当前栈顶的Activity，回到上一个界面。然而Task这个概念之所以复杂，是因为不同Process中的Activity可以被放到同一个Task中，例如在我们的程序中可能会打开Google Map的地图界面。具体Activity在运行时该被放到哪个Task中，这会由Activity的taskAffinity属性决定，一般情况下一个Apk中的所有Activity在运行时会被放到同一个Task中，但是运行时Activity的taskAffinity是可以修改的。例如上面说的Google Map的例子，地图显示界面默认是存在于Google Map这个程序的默认Task中的，但是我们却可以在运行时将这个界面带到我们自己程序的当前Task中来。窗口在Task中的“入栈”和“出栈”操作和Activity的运行时生命周期息息相关，后面我也会用更详细的篇幅来介绍Task和Activity运行时生命周期的关系。

第一篇手记就写到这里了，下篇预告：《[Android研究手记2] Activity和Service的运行时生命周期模型》。 </description>
		<link>http://hkbarton.sacredfir.com/?p=40</link>
			</item>
	<item>
		<title>G1入手</title>
		<description>中午接到快递公司的电话，我的G1终于到了。之前一直都玩Android SDK中的模拟器，拿到真机还是很不适应，逃腾了一下午，算是基本熟悉了。

这部G1已经刷成G2的Android1.5系统，并且做了简体中文的汉化，还安装了GOOGLE拼音输入法，基本上是拿来就可用了。系统是安卓网的自制版本，现在安卓网上的啊兴大牛已经发布了最新的自制ROM包，不过对我来说暂时还没有刷的必要。

大概说说G1给我的第一感觉，优点：

1.  Android系统和各种内置软件的用户体验！由于没有用过iphone，所以没有办法和同样在用户体验方面很强的iphone比较，但就我用过的手机来说，这绝对是我用过的最好用户体验的手机系统。比如，短信/彩信/GTalk等文字交流软件的体验是一致的，Gmail的联系人和手机中的联系人也可以互相同步，所有的操作给你的感觉都是简单明了，很少的几个步骤或者按钮就可以满足你的需要，做到了“有用的一个不少，没用的一个不多”。

2. 网络功能和服务非常强大，特别是结合google自身的服务，GTalk/Reader/Gmail全部在手机上还原了电脑上一样好的体验。机器自带的GPS结合Google Map，即好玩又好用。硬件上G网CMNET和Wifi的支持都很好，并且切换和开关都非常方便。还有一点很赞，所有的网络功能都不会保持长连接，有数据的时候连接，没有数据的时候断开，但是连接和断开的过程并不破坏你的用户体验。

3. 真机调试和开发非常方便，装好Android SDK中的Usb Debug Driver后，连上电脑，Eclipse ADT扩展会自动侦测选择不使用模拟器，而使用真机调试，通过Eclipse中的debug或者run就可以直接在真机中运行调试，相当方便。即使不连接电脑，手机中自带的Development Tool也可以帮助你查看程序运行的各种异常信息和调用堆栈信息。

再来说说缺点：

1. 这个缺点和google没啥关系，是硬件上的缺点，就是G1的屏幕侧滑露出键盘的设计，不知道是设计上的缺陷还是我这台机器的个体问题，导致屏幕和键盘之间缝隙过大，还有松动的感觉，让人很不放心，也给人一种质量不佳的感觉。不知道用久了滑盖轴承会不会断掉啊。

2. 电池续航时间过短，逃腾了一下午，感觉这么个玩法电池最多用一天。当然G1的硬件和网络配置确实都是电池杀手。

3. 发热... 如果一直拿在手中操作，特别是上网的话，手机背面的温度明显升高，影向拿在手上的感觉。

貌似说的这些缺点都是硬件上的，看来Android系统本身确实很让我满意啊～～～

大家期待我的BlogMessage吧，哈哈～～～ </description>
		<link>http://hkbarton.sacredfir.com/?p=35</link>
			</item>
	<item>
		<title>5oiR5pON55S15L+h5ZKM5YWx5Lqn5YWa5a6D5aiY</title>
		<description>5LiKIGh0dHA6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20g6K+V6aqMTuasoeacquaenCwg6ZeuZ29vZ

2xl5b6X55+l6KKr5Lyf5aSn55qER0ZX5bCB5o6JLi4uLi4u

 

5rKz6J+556S+5LyaLCDmiJHlsLHmg7Por7Qz5Liq5a2XOiDojYnms6Xpqawh

 

5Li65LqG55So6KGA5rGX6ZKx5Lmw5p2l55qESVDlkoznqbrpl7TkuI3ooqtHRlfmsrPon7ksIOWPquiDv

eeUqEJhc2U2NOWWt+S4gOS4i+S6hg==

 

火大中...... </description>
		<link>http://hkbarton.sacredfir.com/?p=22</link>
			</item>
	<item>
		<title>一个理由</title>
		<description>就4句话；一个合适的时间；一个合适的理由；我说完了。 </description>
		<link>http://hkbarton.sacredfir.com/?p=20</link>
			</item>
	<item>
		<title>.Net技术大会 Day 2</title>
		<description>第2天的.Net技术大会感觉明显不如第一天，整个第2天的主题比较偏向于实际应用的技术，内容涵盖WPF, Silverlight, WF, SQL Server, SharePoint, BizTalk, ASP.Net MVC等，但是很多相关的演讲都停留在比较初级的入门层面，大概就是介绍一下这些技术，然后做一些很简单的Demo，比较缺乏深入的内容。第2天也有一些关于项目管理和过程的演讲，如《敏捷项目管理》，《微软软件研发方法与过程》，这2场听的人都非常多，相比之下同时间段的Silverlight，SharePoint，WF，SQL Server BI这些场次就显得比较冷清了。这也可以说明一个现象，看来国内的程序员大部分都希望转型向管理方面发展，对管理的内容很感兴趣，想静下来做技术做到老的程序员很少，当然这也和国内的软件大环境有关。记得第1天技术大会最后的论坛活动上有人就问了Jeffrey这样一个问题，说大多数程序员都认为30岁是一个坎，过了30岁还在做技术就很痛苦了，问Jeffrey怎么看这个问题。Jeffrey当时听到这个问题觉得非常的惊讶，不能理解为什么国内的程序员有这个想法。这也从另一个方面说明了中国软件行业和欧美发达国家软件行业相比，重于管理远远大于重于技术。另外这天还有一场是《SQL Server性能优化关键路径》，这场也是人满为患，让同时间段的另外两场显得很冷清，这里还是可以看出一些共性，目前的企业开发中，数据存储方案是对性能影响最大的因素，也是开发人员关注最多的问题，很多开发人员都提问问到自己的数据量非常非常大，上TB上千万记录的数据量如何进行存储优化的问题，可见数据和对数据的处理确实是现在企业应用系统中很关键的一个环节。
第2天的有些场次我没有全程听完，而是根据内容，在不同的场次之间进行了一些调整。我总共参与的场次有Matt Gibbs的《Building Web Applications with .Net Now and Future》，彭爱华的《Windows平台安全框架与设计经验谈》，胡百师的《敏捷项目管理》，段凌的《SQL Server性能优化关键路径》，郜建和李丛昱的《深入浅出WF4.0》，高焕堂的《创意，接口与架构设计》，刘浩的《BizTalk企业应用集成方案深度演绎》。

下面还是简要记录一下各场的大致内容，回成都后再仔细整理：

《Building Web Applications with .Net Now and Future》：这一场没有太多深入的东西，Matt Gibbs给我们大致描述了一下ASP.Net下一代的一些新特性，包括VS2010中对HTML, JS, JQuery代码编写的更好支持，新的输出缓存架构，下一代的ASP.Net Web Form（包括支持static mode的ClientID，URL Routing，对SEO的支持，对ViewState的改进等），ASP.Net MVC，ASP.Net Data和Dynamic Data，ASP.Net AJAX的升级等。这些内容其实就是一个新特性的展示，在网上可以找到好多更详细的描述，所以选听这个场次让我比较后悔，应该多花点时间去听听同场的《Windows平台安全框架与设计经验谈》。

《Windows平台安全框架与设计经验谈》：这一场的内容应该是比较深入的，但是我只听到尾巴上一点，彭爱华先生首先讲解了基本的安全概念，随后深入讲解了Windows中的安全机制；包括域，活动目录，本地安全授权机构，Window内部验证原理（登录会话，令牌，网络验证，Windows窗口站，Winlogon）等，下来我找到这场的录像后会再仔细看一次。

《敏捷项目管理》：我也没有免俗，来听了这场项目管理方面的演讲，因为同时间段的其他内容我都不是太感兴趣。这场其实也没有太多新东西，大多数的概念和敏捷思想早已是大家耳熟能详了，胡百师先生结合自己的实际经验讲解了如何在项目管理中运用敏捷思想。总之我觉得项目管理往往都是说起来是这样，做起来又是另一回事，敏捷项目管理最核心的因素是人，所以你的团队是否敏捷，完全取决于你的团队中有怎样的一群Member。

《SQL Server性能优化关键路径》：说实话，这场听的我很晕，而且刚好又是吃完午饭后的第一场正是昏昏欲睡的时候。原本我以为本场的内容是和开发相关的，比如如何优化SQL之类的话题，但是听了一会就发现原来这场的内容是完全给DBA讲的。段凌小姐按影响程度从高到底描述了SQL Server性能瓶颈的一些影响因素，从锁和Page Latches产生的性能瓶颈到磁盘IO，CPU，内存，网络对SQL Server的性能影响等问题以及这些问题的识别和解决方法，比如如何在32位系统上开启SQL Server AWE，让SQL Server的data cache能够使用超过1.7G的扩展内存从而解决内存瓶颈等问题，当然这些都应该是DBA需要了解的内容。

《深入浅出WF4.0》：这场内容同样也很浅显，我觉得只能算浅出了，完全没有深入。本场演示了一些WF4.0的新特性，一些新的特性确实还是很不错的，比如支持复杂规则的定义（这样我们公司就可以在以后使用WF4.0代替现在使用的ILog了，毕竟ILog实在是很昂贵），又比如通过简单的编码可以将原本只能在设计时期才能看到的流程设计视图直接暴露给用户使用，在WF3.0中实现类似的功能需要大量的编码，还有就是对事物流的支持等。看来有空我得花点时间研究下WF了，看看除了工作流外，把它作为一个轻量的BPM是不是也是可行的。

《创意，接口与架构设计》：高焕堂先生算是台湾的牛人了（拿anrs的话来说是OO太空人），不过说实话本场的内容让我挺失望的，翻来覆去就讲了一些基础的OOD和OOA知识，，导致我中途就逃跑去听另一场《BizTalk企业应用集成方案深度演绎》去了。不过高Sir对中国文化的了解确实很深，能把易经八卦和修长城这两件事联系到架构设计上来真是前无古人后无来者了啊。

《BizTalk企业应用集成方案深度演绎》：这场又只听了个后面的尾巴，前面SOA和BPM的内容没有听到。刘浩先生主要讲了BizTalk 2006 R2版本里面的一些基本概念，比如端口，消息映射和事物补偿等，然后讲解了一些他们应用BizTalk 2006 ...</description>
		<link>http://hkbarton.sacredfir.com/?p=12</link>
			</item>
	<item>
		<title>.Net技术大会 Day One</title>
		<description>由于飞机误点，20号凌晨1点才到上海，到了酒店已经2点过了，睡了5个小时就昏昏沉沉的赶往会场开始了第一天的.Net技术大会。第一天的会议我总共选听了 Jeffrey Richter的Keynote《The Performance of Every Day Things》，张银奎的《使用WinDBG+SOS深入理解托管世界》，温昱的《Effective Architectural Design: 架构设计的10条经验》，郭晓颖的《使用Silverlight构建企业级RIA应用-现在与未来》，Jeffrey Richter的《Building Responsive and Scalable Applications》。
虽然没有休息好，但是听Jeffrey Richter的Keynote时还是打起了精神，一天5场演讲下来让我感觉收获最多的是Jeffrey的2场和张银奎的WinDBG那场。这里说一些细节：1. Jeffrey的语速极快，好在发音比较清楚，配合打印的讲义我勉勉强强跟上；2. 中午休息的时候Jeffrey签名兜售他的两本著作《CLR via C# second Edition》和《Windows via C/C++》，我买了一本《CLR via C# second Edition》；3. 张银奎的关于WinDBG演讲很有意思，不过关于C#析构函数和GC的一个细节有一点小错误。4. 根据我的观察，参会的牛人还是挺多的。

一天参加5场培训，内容很多，煞费体力，要都记下来很难，下面简要记录一下我参与的5个场次演讲的大体内容，待我全部整理好回到成都后再和同事们详细分享：

Keynote《The Performance of Every Day Things》：Jeffrey用一个精心设计好的Demo向我们展示了很多.Net代码中的性能问题并解释了各种性能测试结果的深层原因，虽然都是一些非常细节的东西，但是这些细节比较有用，而且一些细节也是我在平时写程序中没有用到或是没有关注过的一些知识点，比如check和uncheck的性能差别；普通参数和可变参数的性能差别；迭代和普通loop的性能差别；普通调用，通过委托调用，通过反射调用静态方法，实例方法，虚方法的不同性能；.Net中提供的不同种类的Monitor，Mutex的性能差别等。另外从Jeffrey的Demo中我们也可以学习到一些测试和调试性能问题的好方法。

《使用WinDBG+SOS深入理解托管世界》：以前竟然没有听过WinDBG真是很惭愧，原来这东西一直伴随着MS内部开发x86 OS内核，可以说NT这样的x86系统内核就是MS的牛人们用着WinDBG给调出来的。SOS是在.Net时代用WinDBG调试.Net托管进程的一个插件。这场演讲偏向系统底层，对于我这种已经远离底层十万八千里的企业应用开发程序员来说还是比较有难度的，但是张银奎先生的讲义和示例都做的很不错，还是很容易听懂的。张银奎先生在这场演讲中向我们从头到尾展示了一个托管进程的加载运行过程。从系统内核态的进程创建和内核模块加载以及初始线程执行，.Net mscoree引导_CoreExeMain，到加载CLR， 创建Domain，启动辅助调试线程，创建GCHeap和GC工作线程，再到从PE文件解析CallHeader，加载JIT模块，JIT开始进行，执行即时编译后的托管Main函数这一系列过程，向我们完整的演示了.Net托管进程的创建和执行过程。最后我们发现实际上托管进程和普通进程并没有什么区别，所有的过程和细节以及用到的技术手段和普通的Win32进程几乎完全一样，只有最后JIT的机制有别于普通的Win32进程，所以我们可以说托管进程就是具有JIT机制的Windows进程。演讲的最后一点时间，张银奎先生还为我们演示了如何用WinDBG来观察.Net GC的执行等话题。

《Effective Architectural Design: 架构设计的10条经验》：这场演讲收获并不是太大，讲的都是一些老生常谈，我自己平时也都有思考过的一些问题。温昱先生结合自己的经验提出了一些观点和经验总结。

《使用Silverlight构建企业级RIA应用-现在与未来》：这场演讲也几乎没有什么收获，就是MS的广告时间和Toy Show而已。纯当为下一场的Jeffrey演讲之前的休息和换脑时间。

《Building Responsive and Scalable Applications》：非常不错的一场演讲，不过Jeffrey讲的比较激动，语速更快，而且停顿极少，让我差点没跟上 本场Jeffrey同样用很有趣的例子向我们展示了何为Responsive和Scalable的程序，让我们知道了想一味的靠创建线程来增强程序的性能和响应是极其愚蠢的事情。相反在一些场景中我们应该避免多线程，因为创建和释放线程的开销是巨大的，而且无论我们创建多少个线程，单核CPU在同一时刻只能执行一个线程的代码，双核CPU也仅仅能同时执行两个线程的代码而已。多线程仅仅是CPU会为每一个线程分配一个时间片，然后在这些时间片中不停的switch到不同的context执行而已，这只是会让每一个线程的工作都有时间执行一点点，不至于长久等待，从而表面上是增加了可响应性，但实际上并不会带来性能的真正提升，另外CPU进行switch的开销也并不小。Jeffrey向我们展示了一些伪异步程序的示例，例如现在很多进程中开启了很多线程，然而大多数线程都处于block状态，什么都没有做而只是在那里浪费资源的实事，甚至我们平时不经意写出的代码也有这样的问题，这样的程序的确是不可伸缩的，他们的吞吐能力和性能并不会随着我们增加在硬件上的投资而成线性的增长。如何利用Thread Pool来使用多线程，如何避免线程的Block，如何进行真正的异步编程，从而建立真正可伸缩的应用？这些问题在Jeffrey的这场演讲中都给出了很好的答案。

OK，就到这里，关于.Net技术大会Day ...</description>
		<link>http://hkbarton.sacredfir.com/?p=11</link>
			</item>
</channel>
</rss>
