<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Power by Result Search &#187; study on android</title>
	<atom:link href="http://www.result-search.com/sty/category/technology/android/%e4%b8%80%e6%ad%a5%e4%b8%80%e6%ad%a5%e5%ad%a6%e4%b9%a0/study-on-android/feed" rel="self" type="application/rss+xml" />
	<link>http://www.result-search.com/sty</link>
	<description>Just another weblog</description>
	<lastBuildDate>Wed, 23 Jun 2010 03:12:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Study on Android【六】&#8211;消息机制，异步和多线程</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%85%ad%e3%80%91-%e6%b6%88%e6%81%af%e6%9c%ba%e5%88%b6%ef%bc%8c%e5%bc%82%e6%ad%a5%e5%92%8c%e5%a4%9a%e7%ba%bf%e7%a8%8b.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%85%ad%e3%80%91-%e6%b6%88%e6%81%af%e6%9c%ba%e5%88%b6%ef%bc%8c%e5%bc%82%e6%ad%a5%e5%92%8c%e5%a4%9a%e7%ba%bf%e7%a8%8b.html#comments</comments>
		<pubDate>Mon, 11 May 2009 15:19:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e5%85%ad%e3%80%91-%e6%b6%88%e6%81%af%e6%9c%ba%e5%88%b6%ef%bc%8c%e5%bc%82%e6%ad%a5%e5%92%8c%e5%a4%9a%e7%ba%bf%e7%a8%8b.html</guid>
		<description><![CDATA[from： http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html
 
有了framework后，我们不用面对赤裸裸的OS API，做一些重复而繁杂的事情。但天下没有免费的午餐，我们还是需要学会高效正确的使用不同的framework，很多处理某一特定问题的手法在不同的framework中，用起来都会有所不同的。
在Android中，下层是Linux的核，但上层的java做的framework把这一切封装的密不透风。以消息处理为例，在MFC中，我们可以用PreTranslateMessage等东东自由处理消息，在C#中，Anders Hejlsberg老大说了，他为我们通向底层开了一扇“救生窗”，但很遗憾，在Android中，这扇窗户也被关闭了（至少我现在没发现&#8230;）。
在Android中，你想处理一些消息（比如：Keydown之类的&#8230;），你必须寻找Activity为你提供的一些重载函数（比如 onKeyDown之类的&#8230;）或者是各式各样的listener（比如OnKeyDownListner之类的&#8230;）。这样做的好处是显而易见的， 越多的自由就会有越多的危险和越多的晦涩，条条框框画好了，用起来省心看起来省脑，这是一个设计良好的framework应该提供的享受。对于我目前的工 程而言，我没有什么BT的需求在当前API下做不到的，google的设计ms还是很nice的。
但世界是残酷的，有的时候我们还是必须有机制提供消息的分发和处理的，因为有的工作是不能通过直接调用来同步处理的，同时也不能通过Activity中内 嵌的消息分发和接口设定来做到，比如说事件的定时触法，异步的循环事件的处理，高耗时的工作等等。在Android中，它提供了一些蛮有意思的方式来做这 件事情（不好意思，我见不多识不广，我没见过类似玩法，有见过的提个醒 &#38;&#38; 嘴下超生^_^），它有一个android.os.Handler的类，这个类接受一个Looper参数，顾名思义，这是一个封装过的，表征消息循环的 类。默认情况下，Handler接受的是当前线程下的消息循环实例，也就是说一个消息循环可以被当前线程中的多个对象来分发， 来处理（在UI线程中，系统已经有一个Activity来处理了，你可以再起若干个Handler来处理&#8230;）。在实例化一个 handlerInstance之后，你可以通过sendMessage等消息发送机制来发送消息，通过重载handleMessage等函数来分发消 息。但是！该handlerInstance能够接受到的消息，只有通过handlerInstance.obtainMessage构造出来的消息（这 种说法是不确切的，你也可以手动new一个Message，然后配置成该handlerInstance可以处理的，我没有跟进去分析其识别机制，有兴趣 的自己玩吧^_^）。也就是说A, B, C, D都可以来处理同一线程内的消息分发，但各自都只能处理属于自己的那一份消息， 这抹杀了B想偷偷进入A领地，越俎代庖做一些非份之事的可能（从理论上看，B还是有可能把消息伪装的和A他们家的一样，我没有尝试挑战一下google的 智商，有BT需求的自行研究^_^）。这样做，不但兼顾了灵活性，也确保了安全性，用起来也会简单，我的地盘我做主，不用当心伤及无辜，左拥右抱是一件很 开心的事情。。。
很显然，消息发送者不局限于自己线程，否者只能做一些定时，延时之类的事情，岂不十分无趣。在实例化Handler的时候，Looper可以是任意线程 的，只要有Handler的指针，任何线程也都可以sendMessage（这种构造方式也很有意思，你可以在A线程里面传B线程的Looper来构造 Handler，也可以在B线程里构造，这给内存管理的方法带来很大的变数&#8230;）。但有条规则肯定是不能破坏的，就是非UI线程，是不能触碰UI类的。 在不同平台上有很多解决方式（如果你有多的不能再多的兴趣，可以看一下很久很久以前我写的一个，不SB不要钱）。我特意好好跟了一下android中的AsyncQueryHandler类，来了解google官方的解决方案。
AsyncQueryHandler是Handler的子类，文档上说，如果处理ContentProvider相关的内容，不用需要自行定义一套东西， 而可以简单的使用async方式。我想指代的就应该是AsyncQueryHandler类。该类是一个典型的模板类，为ContentProvider 的增删改查提供了很好的接口，提供了一个解决架构，final了一些方法，置空了一些方法。通过派生，实例化一些方法（不是每个对 ContentProvider的处理多需要全部做增删改查，我想这也是该类默认置空一些方法而不是抽象一些方法的原因），来达到这个目的。在内部，该类 隐藏了多线程处理的细节，当你使用时，你会感觉异常便利。以query为例，你可以这么来用：
// 定义一个handler，采用的是匿名类的方式，只处理query，因此只重写了onQueryComplete函数：
queryHandler = new AsyncQueryHandler(this.getContentResolver()){ // 传入的是一个ContentResolver实例，所以必须在OnCreate后实例化该Handler类
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
        // 在这里你可以获得一个cursor和你传入的附加的token和cookie。
        // 该方法在当前线程下（如果传入的是默认的Looper话），可以自由设定UI信息
    }
};
// 调用时只需要调用startQuery(int token, Object cookie, ContentURI uri, [...]]]></description>
			<content:encoded><![CDATA[<p>from： <a href="http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html">http://www.cnblogs.com/duguguiyu/archive/2008/01/24/1050813.html</a></p>
<p> </p>
<p>有了framework后，我们不用面对赤裸裸的OS API，做一些重复而繁杂的事情。但天下没有免费的午餐，我们还是需要学会高效正确的使用不同的framework，很多处理某一特定问题的手法在不同的framework中，用起来都会有所不同的。<br />
在Android中，下层是Linux的核，但上层的java做的framework把这一切封装的密不透风。以消息处理为例，在MFC中，我们可以用PreTranslateMessage等东东自由处理消息，在C#中，<a id="jnfi" title="Anders Hejlsberg" href="http://en.wikipedia.org/wiki/Anders_Hejlsberg">Anders Hejlsberg</a>老大说了，他为我们通向底层开了一扇“救生窗”，但很遗憾，在Android中，这扇窗户也被关闭了（至少我现在没发现&#8230;）。<br />
在Android中，你想处理一些消息（比如：Keydown之类的&#8230;），你必须寻找Activity为你提供的一些重载函数（比如 onKeyDown之类的&#8230;）或者是各式各样的listener（比如OnKeyDownListner之类的&#8230;）。这样做的好处是显而易见的， 越多的自由就会有越多的危险和越多的晦涩，条条框框画好了，用起来省心看起来省脑，这是一个设计良好的framework应该提供的享受。对于我目前的工 程而言，我没有什么BT的需求在当前API下做不到的，google的设计ms还是很nice的。<br />
但世界是残酷的，有的时候我们还是必须有机制提供消息的分发和处理的，因为有的工作是不能通过直接调用来同步处理的，同时也不能通过Activity中内 嵌的消息分发和接口设定来做到，比如说事件的定时触法，异步的循环事件的处理，高耗时的工作等等。在Android中，它提供了一些蛮有意思的方式来做这 件事情（不好意思，我见不多识不广，我没见过类似玩法，有见过的提个醒 &amp;&amp; 嘴下超生^_^），它有一个android.os.Handler的类，这个类接受一个Looper参数，顾名思义，这是一个封装过的，表征消息循环的 类。默认情况下，Handler接受的是当前线程下的消息循环实例，也就是说一个<span style="color: #ff9966;"><span>消息循环可以被当前线程中的多个对象来分发</span></span>， 来处理（在UI线程中，系统已经有一个Activity来处理了，你可以再起若干个Handler来处理&#8230;）。在实例化一个 handlerInstance之后，你可以通过sendMessage等消息发送机制来发送消息，通过重载handleMessage等函数来分发消 息。但是！该handlerInstance能够接受到的消息，只有通过handlerInstance.obtainMessage构造出来的消息（这 种说法是不确切的，你也可以手动new一个Message，然后配置成该handlerInstance可以处理的，我没有跟进去分析其识别机制，有兴趣 的自己玩吧^_^）。也就是说A, B, C, D都可以来处理同一线程内的消息分发，但<span style="color: #ff9966;"><span>各自都只能处理属于自己的那一份消息</span></span>， 这抹杀了B想偷偷进入A领地，越俎代庖做一些非份之事的可能（从理论上看，B还是有可能把消息伪装的和A他们家的一样，我没有尝试挑战一下google的 智商，有BT需求的自行研究^_^）。这样做，不但兼顾了灵活性，也确保了安全性，用起来也会简单，我的地盘我做主，不用当心伤及无辜，左拥右抱是一件很 开心的事情。。。<br />
很显然，消息发送者不局限于自己线程，否者只能做一些定时，延时之类的事情，岂不十分无趣。在实例化Handler的时候，Looper可以是任意线程 的，只要有Handler的指针，任何线程也都可以sendMessage（这种构造方式也很有意思，你可以在A线程里面传B线程的Looper来构造 Handler，也可以在B线程里构造，这给内存管理的方法带来很大的变数&#8230;）。但有条规则肯定是不能破坏的，就是非UI线程，是不能触碰UI类的。 在不同平台上有很多解决方式（如果你有多的不能再多的兴趣，可以看一下很久很久以前<a id="jp83" title="我写的一个" href="http://www.cnblogs.com/duguguiyu/archive/2008/01/archive/2006/07/28/462365.html">我写的一个</a>，不SB不要钱）。我特意好好跟了一下android中的<span style="color: #ff9966;"><span>AsyncQueryHandler</span></span>类，来了解google官方的解决方案。<br />
AsyncQueryHandler是Handler的子类，文档上说，如果处理ContentProvider相关的内容，不用需要自行定义一套东西， 而可以简单的使用async方式。我想指代的就应该是AsyncQueryHandler类。该类是一个典型的模板类，为ContentProvider 的增删改查提供了很好的接口，提供了一个解决架构，final了一些方法，置空了一些方法。通过派生，实例化一些方法（不是每个对 ContentProvider的处理多需要全部做增删改查，我想这也是该类默认置空一些方法而不是抽象一些方法的原因），来达到这个目的。在内部，该类 隐藏了多线程处理的细节，当你使用时，你会感觉异常便利。以query为例，你可以这么来用：</p>
<blockquote><p>// 定义一个handler，采用的是匿名类的方式，只处理query，因此只重写了onQueryComplete函数：<br />
queryHandler = new AsyncQueryHandler(this.getContentResolver()){ // 传入的是一个ContentResolver实例，所以必须在OnCreate后实例化该Handler类<br />
@Override<br />
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {<br />
        // 在这里你可以获得一个cursor和你传入的附加的token和cookie。<br />
        // 该方法在当前线程下（如果传入的是默认的Looper话），可以自由设定UI信息<br />
    }<br />
};</p>
<p>// 调用时只需要调用startQuery(int token, Object cookie, ContentURI uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)函数即可：<br />
queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, sortBy);</p></blockquote>
<p>可见，该类的使用是多么简单（其实现可不会很容易，因为我尝试做了一次造车轮的工作*_*），比直接用Handler简单无数倍。但让我倍感孤独的是，不 知道是没人做异步的ContentProvider访问，还是这个类使用太过于弱智（这个使用方法可是我摸索了半天的啊，难道我真的如此的弱@_@），抑 或是大家都各有高招，从SDK到网上，没有任何关于该类的有点用的说明。而我又恰巧悲伤的发现，这个类其实有很多的问题，比如他吃掉异常，有错误时只是简 单的返回null指针（这个其实不能怪他，你可以看看<a id="rp8v" title="这里" href="http://www.cnblogs.com/duguguiyu/archive/2008/01/archive/2007/12/31/1021386.html">这里</a>&#8230;）；当你传一个null的ContentResolver进去的时候，没有任何异常，只是莫名其妙的丢弃所有消息，使你陷入苦苦的等待而不知其因；更愤慨的是，他的<span style="color: #ff9966;"><span>token传递竟然有Bug</span></span>（难 道还是我使用不对&amp;_&amp;），从startXX传入的token，到了onXXComplete里面一律变成1，而文档上明明写着两个是一 个东西（我的解决方法是用cookie做token，这个不会丢*_*）。不过我暂时还没有遗弃它的打算，虽然没人理睬，虽然有一堆问题，虽然我按图索骥 造了个新轮子，但为了节省剩下的一些无聊的工作，我决定苟且偷生了。。。<br />
还是习惯性跑题了，其实，我是想通过我对这个类的无数次Debugger跟进，说说它的多线程异步处理的解决策略的。他的基本策略如下：</p>
<blockquote><p>1. 当你实例化一个AsyncQueryHandler类时（包括其子类&#8230;），它会单件构造一个线程（后面会详述&#8230;），这个线程里面会构建一个消息循环。<br />
2. 获得该消息循环的指针，用它做参数实例化另一个Handler类，该类为内部类。至此，就有了两个线程，各自有一个Handler来处理消息。<br />
3. 当调用onXXX的时候，在XXX函数内部会将请求封装成一个内部的参数类，将其作为消息的参数，将此消息发送至另一个线程。<br />
4. 在该线程的Handler中，接受该消息，并分析传入的参数，用初始化时传入的ContentResolver进行XXX操作，并返回Cursor或其他返回值。<br />
5. 构造一个消息，将上述返回值以及其他相关内容绑定在该消息上，发送回主线程。<br />
6. 主线程默认的AsyncQueryHandler类的handleMessage方法（可自定义，但由于都是内部类，基本没有意义&#8230;）会分析该消息，并转发给对应的onXXXComplete方法。<br />
7. 用户重写的onXXXComplete方法开始工作。</p></blockquote>
<p>这就是它偷偷摸摸做过的事情，基本还是很好理解的。我唯一好奇的是它的线程管理方式，我猜测他是用的<span style="color: #ff9966;"><span>单件模式</span></span>。 第一个AsyncQueryHandler的实例化会导致创建一个线程，从此该线程成为不死老处男，所有的ContentResolver相关的工作，都 由该线程统一完成。个人觉得这种解决方式很赞。本来这个线程的生命周期就很难估量，并且，当你有一个ContentProvider的请求的时候，判断你 会做更多的类似操作并不过分。就算错了，花费的也只是一个不死的线程（与进程同生死共存亡&#8230;），换来的却是简单的生命周期管理和无数次线程生死开销的 节约。同时另外一个很重要的问题，他并会涉及到单件中数据同步的问题，每个类都有各自的Handler类，彼此互不干扰，分发可以分别进行。当多个数据请 求的时候，在同一个ContentResolver上进行的可能微乎其微，这就避免了堵塞。总而言之，这套解决办法和Android的整体设计算是天作之 合了。<br />
所以建议，如果你有什么非ContentProvider操作，却需要异步多线程执行的话，模拟一套，是个不错的策略，当然，具体情况具体分析，生搬硬套是学不好马列主义的。。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%85%ad%e3%80%91-%e6%b6%88%e6%81%af%e6%9c%ba%e5%88%b6%ef%bc%8c%e5%bc%82%e6%ad%a5%e5%92%8c%e5%a4%9a%e7%ba%bf%e7%a8%8b.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Study on Android【五】&#8211;自定义ContentProvider的语义</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%94%e3%80%91-%e8%87%aa%e5%ae%9a%e4%b9%89contentprovider%e7%9a%84%e8%af%ad%e4%b9%89.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%94%e3%80%91-%e8%87%aa%e5%ae%9a%e4%b9%89contentprovider%e7%9a%84%e8%af%ad%e4%b9%89.html#comments</comments>
		<pubDate>Mon, 11 May 2009 15:15:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e4%ba%94%e3%80%91-%e8%87%aa%e5%ae%9a%e4%b9%89contentprovider%e7%9a%84%e8%af%ad%e4%b9%89.html</guid>
		<description><![CDATA[from：http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html
Android做到现在。开始感觉到Android确实还是太年轻。系统本身好不够成熟，相关文档更是少的可怜。在Android的旅途中到处是暗坑陷阱，掉进去摔得半死，还只能靠自己琢磨着爬出来。
想 在大部分工作集中在了定义一套ContentProvider以及上层的显示控件上。一个ContentProvider向外提供的接口十分有限，但就是 这几个东西你要表征出正确（标准就是和系统ContentProvider一致的行为）的语义，还是很费功夫的。至少我就摔了好几个跟头。为了降低后续部 队的伤亡，我努力搬走几个绊脚石、填掉几个坑，希望能有一些作用。
ContentProvider中，最重要的就是query操作。query根 据输入返回一个符合条件的Cursor。这就可能出现以下几种情况：1. 查询成功，包含几个正确的结果；2. 查询失败，没有符合的结果；3. 输入错误， 触发了某个异常；4. 没能查询到结果，但无法确定是输入错误还是查询失败。第一种情况是我们最需要的，当然是需要正确维系的，而最后一种情况在大部分应用中应该不会出现（但在 我的应用中会的*_#），而第二种第三种是比较常见的。
经过我的测试，系统的ContentProvider维持这样的语义：如果是情况2，返回 正常的Cursor，并且，其count为0，相当于empty cursor；如果是情况3，不抛出任何异常，返回null的Cursor。这样的话明明白白写出来是很好理解的，但由于没有官方的文档说明，在自定义的 时候经常会误用。比如在某些情况下，用null表征查询失败，用抛出异常来描述错误的输入。
返回empty cursor，如果是通过databasecursor自然会有db帮你维护，但是如果返回ArrayListCursor，MergeCursor或其 他自定义的Cursor，就需要自己维系了。ArrayListCursor可以通过new ArrayListCursor(Columns, new ArrayList(){})来提供。其中Columns一定不为null。MergeCursor不能以new MergeCursor(new Cursor[]{})来创建，而需要通过new MergeCursor(new Cursor[]{aEmptyCursor, &#8230;}来维系（其实很好理解，我呆了&#8230;）。自定义的Cursor也一定要提供生成empty cursor的方式。
如果将ContentProvider作为一个单独的module来理解，不通过异常而是通过null来返回MS是有好处 的。在module的出口吃掉所有异常，虽然不能提供足够的信息（异常信息全部写入日志），但可能会使上层使用更简单。但在Android中，我并没有感 觉到这一点。作为ContentProvider的上层函数，ListActivity.managedQuery、 ListView.setListAdapter等，根本不能处理一个null的Cursor，在ListView中这会触发一个异常。更无语的是，当你 把一个null Cursor设置为manage的后。它不会立即抛异常，而是在OnFreeze等生命周期函数的时候，因无法处理null Cursor而抛出一个异常。这使得你根本无法在当地catch该异常，换句话，ListActivity的manageCursor根本是个无法使用的函数。你必须用getContext().query()获得Cursor，然后判定该Cursor是否null，在进行startManagingCursor进行绑定。这远不如直接用异常进行错误路径的处理来的统一和方便。
当然，有些东西我们是不能改变的，只能去适应。对于自定义的cursor, ContentProvider，最重要的，是在无人造错误输入的情况下返回empty cursor，而不是null。至于使用null响应还是异常响应上，我个人觉得还是和系统同步为好，虽然别扭，但至少统一不容易有歧义。
此外，ContentProvider还有很多细致的语义。比如返回的Cursor需要绑定一个URI，以便自动响应更新。自定义的更新需要支持deleteRow等操作语义等等。总之，我们需要更好的文档或更多经验文档，以便我们更好的爬上巨人的肩膀。
PS：而上层的ListView，更是陷阱重重。首先绑定到ListView的Cursor必须有_id项，否则会有异常抛出。如果做过.net的开发， 这一点是可以想到的，但是，这种问题应该在文档中写明。另外，在ListView中，如果你不绑定一个数据源，你一定不能在layout中添加涉及内容的 属性。比如android:height=&#8221;wrap_content&#8221;，这会在onMeasure的时候抛出异常。
]]></description>
			<content:encoded><![CDATA[<p>from：<a href="http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html">http://www.cnblogs.com/duguguiyu/archive/2007/12/31/1021386.html</a></p>
<p>Android做到现在。开始感觉到Android确实还是太年轻。系统本身好不够成熟，相关文档更是少的可怜。在Android的旅途中到处是暗坑陷阱，掉进去摔得半死，还只能靠自己琢磨着爬出来。<br />
想 在大部分工作集中在了定义一套ContentProvider以及上层的显示控件上。一个ContentProvider向外提供的接口十分有限，但就是 这几个东西你要表征出正确（标准就是和系统ContentProvider一致的行为）的语义，还是很费功夫的。至少我就摔了好几个跟头。为了降低后续部 队的伤亡，我努力搬走几个绊脚石、填掉几个坑，希望能有一些作用。<br />
ContentProvider中，最重要的就是query操作。query根 据输入返回一个符合条件的Cursor。这就可能出现以下几种情况：1. 查询成功，包含几个正确的结果；2. 查询失败，没有符合的结果；3. 输入错误， 触发了某个异常；4. 没能查询到结果，但无法确定是输入错误还是查询失败。第一种情况是我们最需要的，当然是需要正确维系的，而最后一种情况在大部分应用中应该不会出现（但在 我的应用中会的*_#），而第二种第三种是比较常见的。<br />
经过我的测试，系统的ContentProvider维持这样的语义：如果是情况2，返回 正常的Cursor，并且，其count为0，相当于empty cursor；如果是情况3，不抛出任何异常，返回null的Cursor。这样的话明明白白写出来是很好理解的，但由于没有官方的文档说明，在自定义的 时候经常会误用。比如在某些情况下，用null表征查询失败，用抛出异常来描述错误的输入。<br />
返回empty cursor，如果是通过databasecursor自然会有db帮你维护，但是如果返回ArrayListCursor，MergeCursor或其 他自定义的Cursor，就需要自己维系了。ArrayListCursor可以通过new ArrayListCursor(Columns, new ArrayList(){})来提供。其中Columns一定不为null。MergeCursor不能以new MergeCursor(new Cursor[]{})来创建，而需要通过new MergeCursor(new Cursor[]{aEmptyCursor, &#8230;}来维系（其实很好理解，我呆了&#8230;）。自定义的Cursor也一定要提供生成empty cursor的方式。<br />
如果将ContentProvider作为一个单独的module来理解，不通过异常而是通过null来返回MS是有好处 的。在module的出口吃掉所有异常，虽然不能提供足够的信息（异常信息全部写入日志），但可能会使上层使用更简单。但在Android中，我并没有感 觉到这一点。作为ContentProvider的上层函数，ListActivity.managedQuery、 ListView.setListAdapter等，根本不能处理一个null的Cursor，在ListView中这会触发一个异常。更无语的是，当你 把一个null Cursor设置为manage的后。它不会立即抛异常，而是在OnFreeze等生命周期函数的时候，因无法处理null Cursor而抛出一个异常。这使得你根本无法在当地catch该异常，换句话，<span style="color: #ff0000;">ListActivity的manageCursor根本是个无法使用的函数</span>。你必须用getContext().query()获得Cursor，然后判定该Cursor是否null，在进行startManagingCursor进行绑定。这远不如直接用异常进行错误路径的处理来的统一和方便。<br />
当然，有些东西我们是不能改变的，只能去适应。对于自定义的cursor, ContentProvider，最重要的，是在无人造错误输入的情况下返回empty cursor，而不是null。至于使用null响应还是异常响应上，我个人觉得还是和系统同步为好，虽然别扭，但至少统一不容易有歧义。<br />
此外，ContentProvider还有很多细致的语义。比如返回的Cursor需要绑定一个URI，以便自动响应更新。自定义的更新需要支持deleteRow等操作语义等等。总之，我们需要更好的文档或更多经验文档，以便我们更好的爬上巨人的肩膀。</p>
<p>PS：而上层的ListView，更是陷阱重重。首先绑定到ListView的Cursor必须有_id项，否则会有异常抛出。如果做过.net的开发， 这一点是可以想到的，但是，这种问题应该在文档中写明。另外，在ListView中，如果你不绑定一个数据源，你一定不能在layout中添加涉及内容的 属性。比如android:height=&#8221;wrap_content&#8221;，这会在onMeasure的时候抛出异常。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%94%e3%80%91-%e8%87%aa%e5%ae%9a%e4%b9%89contentprovider%e7%9a%84%e8%af%ad%e4%b9%89.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Study on Android【四】&#8211;显示控件使用</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%9b%9b%e3%80%91-%e6%98%be%e7%a4%ba%e6%8e%a7%e4%bb%b6%e4%bd%bf%e7%94%a8.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%9b%9b%e3%80%91-%e6%98%be%e7%a4%ba%e6%8e%a7%e4%bb%b6%e4%bd%bf%e7%94%a8.html#comments</comments>
		<pubDate>Mon, 11 May 2009 15:11:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e5%9b%9b%e3%80%91-%e6%98%be%e7%a4%ba%e6%8e%a7%e4%bb%b6%e4%bd%bf%e7%94%a8.html</guid>
		<description><![CDATA[from： http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html
Android的界面显示同样也是基于控件的。通常是用View（包括ViewGroup）控件配上XML的样式来做的。具体细节不想说了，可以参考 Samples里的ApiDemos/View，和View的Doc，以及Implementing a UI这篇Doc。其他还有很多，感觉算是SDK讲述的最多的内容。
从控件的使用上，和网页的设计类似，尽量用parent_width之类的抽象长度，用Theme来做风格，抽取所有的字串等信息做本地化设计。相关内容参看Implementing a UI就好。
一 类比较重要的是数据绑定控件。如果做过ASP.Net会从中看到很多类似的地方。一个支持数据绑定的控件，比如ListView。可以通过一个 ListAdapter绑定到一个数据源上。ListAdapter是一个抽象类，主要的实现类包括SimpleAdapter和 SimpleCursorAdapter。前者是绑定一个静态的Array，后者是绑定一个动态的Cursor。Cursor前面说过，是一个指向数据源 的随机迭代器，将View绑定到Cursor通常要设置这样几个参数。一个是每一行的样式，称作Row Layout，其实就是一个普通的Layout的XML文件。还有就是一个列和现实控件的对应关系。那个控件显示哪个列的值，这是需要配置的。为了定制一 个良好的数据显示控件，最简单你可以定制很PP的Row Layout，复杂一点就是可以重载绑定控件View，或者是适配器ListAdapter。如果是一个数据显示密集的应用，且你对UI有些追求，这个工 作估计是必不可少的。
一个主要用于显示数据内容的Activity，可以选择派生自ListActivity。它提供了一个具有ListView 的Layout，还有simple_list_item_1, simple_list_item_2, two_line_list_item等默认的Row Layout，还有一些比较不错的API，和可供响应选择Item的事件。可以满足你比较基础的需求。如果你觉得只有一个ListView的界面太突兀， 你可以为这个ListActivity指定一个Layout，需要注意的是，你需要提供一个id为@android:id/list的ListView控 件，避免Activity在内部偷偷寻找该控件的时候失败。
除了这些要求，做好UI还有注意易用性和效率。快捷键是一个比较不错的选择，在 Activity中调用setDefaultkeyMode(SHORTCUT_DEFAULT_KEYS)，可以开启快捷键模式，然后你可以将菜单绑定 到指定快捷键上就OK了。个人觉得Tip也是一个比较重要的东西，但目前观察看来，这个东西只能够自己提供了。界面的动态性有时候是不可避免的，比如说菜 单就是一个需要经常根据光标位置提供不同的选项。这个东西Android很人道的考虑到了，你可以参看NodeList这个Sample。它采取的应该是 一个静态模拟动态的方式，这样有助于提高速度。你也可以利用ViewInflate，动态从一个XML创建一个控件。成本据Doc说很大，不到万不得已不 要使用。
]]></description>
			<content:encoded><![CDATA[<p>from： <a href="http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html">http://www.cnblogs.com/duguguiyu/archive/2007/12/03/981680.html</a></p>
<p>Android的界面显示同样也是基于控件的。通常是用View（包括ViewGroup）控件配上XML的样式来做的。具体细节不想说了，可以参考 Samples里的ApiDemos/View，和View的Doc，以及Implementing a UI这篇Doc。其他还有很多，感觉算是SDK讲述的最多的内容。<br />
从控件的使用上，和网页的设计类似，尽量用parent_width之类的抽象长度，用Theme来做风格，抽取所有的字串等信息做本地化设计。相关内容参看Implementing a UI就好。<br />
一 类比较重要的是数据绑定控件。如果做过ASP.Net会从中看到很多类似的地方。一个支持数据绑定的控件，比如ListView。可以通过一个 ListAdapter绑定到一个数据源上。ListAdapter是一个抽象类，主要的实现类包括SimpleAdapter和 SimpleCursorAdapter。前者是绑定一个静态的Array，后者是绑定一个动态的Cursor。Cursor前面说过，是一个指向数据源 的随机迭代器，将View绑定到Cursor通常要设置这样几个参数。一个是每一行的样式，称作Row Layout，其实就是一个普通的Layout的XML文件。还有就是一个列和现实控件的对应关系。那个控件显示哪个列的值，这是需要配置的。为了定制一 个良好的数据显示控件，最简单你可以定制很PP的Row Layout，复杂一点就是可以重载绑定控件View，或者是适配器ListAdapter。如果是一个数据显示密集的应用，且你对UI有些追求，这个工 作估计是必不可少的。<br />
一个主要用于显示数据内容的Activity，可以选择派生自ListActivity。它提供了一个具有ListView 的Layout，还有simple_list_item_1, simple_list_item_2, two_line_list_item等默认的Row Layout，还有一些比较不错的API，和可供响应选择Item的事件。可以满足你比较基础的需求。如果你觉得只有一个ListView的界面太突兀， 你可以为这个ListActivity指定一个Layout，需要注意的是，你需要提供一个id为@android:id/list的ListView控 件，避免Activity在内部偷偷寻找该控件的时候失败。<br />
除了这些要求，做好UI还有注意易用性和效率。快捷键是一个比较不错的选择，在 Activity中调用setDefaultkeyMode(SHORTCUT_DEFAULT_KEYS)，可以开启快捷键模式，然后你可以将菜单绑定 到指定快捷键上就OK了。个人觉得Tip也是一个比较重要的东西，但目前观察看来，这个东西只能够自己提供了。界面的动态性有时候是不可避免的，比如说菜 单就是一个需要经常根据光标位置提供不同的选项。这个东西Android很人道的考虑到了，你可以参看NodeList这个Sample。它采取的应该是 一个静态模拟动态的方式，这样有助于提高速度。你也可以利用ViewInflate，动态从一个XML创建一个控件。成本据Doc说很大，不到万不得已不 要使用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e5%9b%9b%e3%80%91-%e6%98%be%e7%a4%ba%e6%8e%a7%e4%bb%b6%e4%bd%bf%e7%94%a8.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Study on Android【三】&#8211;Intent消息传递</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%89%e3%80%91-intent%e6%b6%88%e6%81%af%e4%bc%a0%e9%80%92.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%89%e3%80%91-intent%e6%b6%88%e6%81%af%e4%bc%a0%e9%80%92.html#comments</comments>
		<pubDate>Mon, 11 May 2009 15:08:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e4%b8%89%e3%80%91-intent%e6%b6%88%e6%81%af%e4%bc%a0%e9%80%92.html</guid>
		<description><![CDATA[from: http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html
在前面写Android的ContentProvider时候，可以看到那是基于观察者模式的一个消息传递方法。每一个Cursor、ContentResolver做为一个小的注册中心，相关观察者可以在这个中心注册，更新消息由注册中心分发给各个观察者。而在MFC或Winform中，都会形成一个消息网，让消息在网中流动，被各节点使用、吃掉或者在出口死掉。
相比之下，我个人觉得基于Intent的Android核心消息传递机制是有所不同的。它应该会有一个全局性的注册中心，这个注册中心是隐性的，整个Android系统中就那么一个。所有的消息接收者，都被隐形的注册到这个中心。包括Activity，Service和IntentReceiver。其实说隐形注册是不确切的，所有注册都还是我们手动告诉注册中心的，只是与传统的方式不一样，我们通常不是通过代码，而是通过配置文件来做。在应用的Manifest中，我们会为一些Activity或Service添加上Intent-filter，或在配置文件中添加&#60;receiver&#62;&#60;/receiver&#62;项。这其实就相当于向系统的注册中心，注册了相关的Intent-filter和receiver（这个事情完全可以通过代码来做，只是这样就失去了修改的灵活性）。
当程序有一个消息希望发出去的时候，它需要将消息封装成一个Intent，并发送。这时候，应该是有一个统一的中心（恩，有可能Android底层实现的时候不是，但简单这样看是没问题的&#8230;）接受到这个消息，并对它进行解析、判定消息类型（这个步骤降低了耦合&#8230;），然后检查注册了相匹配的filter或receiver，并创建或唤醒接收者，将消息分发给它。这样做有很多好处。虽然这种传递有的时候不如点对点的传递快（这有些需要速度的地方，我们看到Android会通过直接通信来做），但有时候又因为它只经过一跳（姑且这么叫吧&#8230;），比复杂的流动又要更快。更重要的是，它耦合性低，在手机平台这种程序组件多变的条件下使用十分适合。并且它可以很容易实现消息的精确或模糊匹配，弹性很大。（我个人曾想在开发一个C++二次平台的时候引入这样的机制，但在C++中，建立一套完整的数据marshal机制不容易，相比之下，用java来做会简单很多&#8230;）
恩，废话说了很多，具体讲讲Android中Intent的使用。当你有一个消息需要传递，如果你明确知道你需要哪个Activity或者其他Class来响应的话，你可以指定这个类来接受该消息，这被称为显性发送。你需要将Intent的class属性设置成目标。这种情况很常见，比如startActivity的时候，会清楚当前Activity完了应该是哪个Activity，那就明确的发送这个消息。
但是，有的时候你并不确定你的消息是需要具体哪个类来执行，而只是知道接收者该符合哪些条件。比如你只需要有一个接收者能显示用户所选的数据，而不想制定某个具体的方法，这时候你就需要用到隐形发送（传统上，我们可能会考虑用多态，但显然这种方式更为灵活&#8230;）。在Android中，你可以为Intent指定一个action，表示你这个指令需要处理的事情。系统为我们定义了很多Action类型，这些类型使系统与我们通信的语言（比如在Activity里面加一个Main的filter，该activity就会做成该应用的入口点），当然你也可以用于你自己的应用之间的通信（同样当然，也可以自定义&#8230;）。强烈建议，在自己程序接收或发出一个系统action的时候，要名副其实。比如你响应一个view动作，做的确实edit的勾当，你发送一个pick消息，其实你想让别人做edit的事，这样都会造成混乱。当然只有Action有时候是不够的，在Android中我们还可以指定catalog信息和type/data信息，比如所有的显示数据的Activity，可能都会响应View action。但很多与我们需要显示的数据类型不一样，可以加一个type信息，明确的指出我们需要显示的数据类型，甚至还可以加上一个catalog信息，指明只有你只有按的是“中键”并发出这样的消息才响应。
从上面可以看出，Android的Intent可以添加上class, action, data/type, catalog等消息，注册中心会根据这些信息帮你找到符合的接收者。其中class是点对点的指示，一旦指明，其他信息都被忽略。Intent中还可以添加key/value的数据，发送方和接收方需要保持统一的key信息和value类型信息，这种数据的marshal在java里做，是不费什么力气的。
Android的Intent发送，可以分成单播和广播两种。广播的接收者是所有注册了的符合条件的IntentReceiver。在单播的情况下，即使有很多符合条件的接收者，也只要有一个出来处理这个消息就好（恩，个人看法，没找到确切条款或抉择的算法，本来想实验一下，没来得及&#8230;），这样的情况很容易理解，当你需要修改某个数据的时候，你肯定不会希望有十个编辑器轮流让你来处理。当广播不是这样，一个receiver没有办法阻止其他receiver进行对广播事件的处理。这种情况也很容易理解，比如时钟改变了，闹钟、备忘录等很多程序都需要分别进行处理。在自己的程序的使用中，应该分清楚区别，合理的使用。
]]></description>
			<content:encoded><![CDATA[<p>from: <a href="http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html">http://www.cnblogs.com/duguguiyu/archive/2007/11/30/977665.html</a></p>
<p><span>在前面写Android的ContentProvider时候，可以看到那是基于观察者模式的一个消息传递方法。每一个Cursor、ContentResolver做为一个小的注册中心，相关观察者可以在这个中心注册，更新消息由注册中心分发给各个观察者。而在MFC或Winform中，都会形成一个消息网，让消息在网中流动，被各节点使用、吃掉或者在出口死掉。<br />
相比之下，我个人觉得基于Intent的Android核心消息传递机制是有所不同的。它应该会有一个全局性的注册中心，这个注册中心是隐性的，整个Android系统中就那么一个。所有的消息接收者，都被隐形的注册到这个中心。包括Activity，Service和IntentReceiver。其实说隐形注册是不确切的，所有注册都还是我们手动告诉注册中心的，只是与传统的方式不一样，我们通常不是通过代码，而是通过配置文件来做。在应用的Manifest中，我们会为一些Activity或Service添加上Intent-filter，或在配置文件中添加&lt;receiver&gt;&lt;/receiver&gt;项。这其实就相当于向系统的注册中心，注册了相关的Intent-filter和receiver（这个事情完全可以通过代码来做，只是这样就失去了修改的灵活性）。<br />
当程序有一个消息希望发出去的时候，它需要将消息封装成一个Intent，并发送。这时候，应该是有一个统一的中心（恩，有可能Android底层实现的时候不是，但简单这样看是没问题的&#8230;）接受到这个消息，并对它进行解析、判定消息类型（这个步骤降低了耦合&#8230;），然后检查注册了相匹配的filter或receiver，并创建或唤醒接收者，将消息分发给它。这样做有很多好处。虽然这种传递有的时候不如点对点的传递快（这有些需要速度的地方，我们看到Android会通过直接通信来做），但有时候又因为它只经过一跳（姑且这么叫吧&#8230;），比复杂的流动又要更快。更重要的是，它耦合性低，在手机平台这种程序组件多变的条件下使用十分适合。并且它可以很容易实现消息的精确或模糊匹配，弹性很大。（我个人曾想在开发一个C++二次平台的时候引入这样的机制，但在C++中，建立一套完整的数据marshal机制不容易，相比之下，用java来做会简单很多&#8230;）<br />
恩，废话说了很多，具体讲讲Android中Intent的使用。当你有一个消息需要传递，如果你明确知道你需要哪个Activity或者其他Class来响应的话，你可以指定这个类来接受该消息，这被称为显性发送。你需要将Intent的class属性设置成目标。这种情况很常见，比如startActivity的时候，会清楚当前Activity完了应该是哪个Activity，那就明确的发送这个消息。</span></p>
<p><span>但是，有的时候你并不确定你的消息是需要具体哪个类来执行，而只是知道接收者该符合哪些条件。比如你只需要有一个接收者能显示用户所选的数据，而不想制定某个具体的方法，这时候你就需要用到隐形发送（传统上，我们可能会考虑用多态，但显然这种方式更为灵活&#8230;）。在Android中，你可以为Intent指定一个action，表示你这个指令需要处理的事情。系统为我们定义了很多Action类型，这些类型使系统与我们通信的语言（比如在Activity里面加一个Main的filter，该activity就会做成该应用的入口点），当然你也可以用于你自己的应用之间的通信（同样当然，也可以自定义&#8230;）。强烈建议，在自己程序接收或发出一个系统action的时候，要名副其实。比如你响应一个view动作，做的确实edit的勾当，你发送一个pick消息，其实你想让别人做edit的事，这样都会造成混乱。当然只有Action有时候是不够的，在Android中我们还可以指定catalog信息和type/data信息，比如所有的显示数据的Activity，可能都会响应View action。但很多与我们需要显示的数据类型不一样，可以加一个type信息，明确的指出我们需要显示的数据类型，甚至还可以加上一个catalog信息，指明只有你只有按的是“中键”并发出这样的消息才响应。<br />
从上面可以看出，Android的Intent可以添加上class, action, data/type, catalog等消息，注册中心会根据这些信息帮你找到符合的接收者。其中class是点对点的指示，一旦指明，其他信息都被忽略。Intent中还可以添加key/value的数据，发送方和接收方需要保持统一的key信息和value类型信息，这种数据的marshal在java里做，是不费什么力气的。<br />
Android的Intent发送，可以分成单播和广播两种。广播的接收者是所有注册了的符合条件的IntentReceiver。在单播的情况下，即使有很多符合条件的接收者，也只要有一个出来处理这个消息就好（恩，个人看法，没找到确切条款或抉择的算法，本来想实验一下，没来得及&#8230;），这样的情况很容易理解，当你需要修改某个数据的时候，你肯定不会希望有十个编辑器轮流让你来处理。当广播不是这样，一个receiver没有办法阻止其他receiver进行对广播事件的处理。这种情况也很容易理解，比如时钟改变了，闹钟、备忘录等很多程序都需要分别进行处理。在自己的程序的使用中，应该分清楚区别，合理的使用。</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%89%e3%80%91-intent%e6%b6%88%e6%81%af%e4%bc%a0%e9%80%92.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Study on Android【二】&#8211;ContentProvider数据模型概述</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%8c%e3%80%91-contentprovider%e6%95%b0%e6%8d%ae%e6%a8%a1%e5%9e%8b%e6%a6%82%e8%bf%b0.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%8c%e3%80%91-contentprovider%e6%95%b0%e6%8d%ae%e6%a8%a1%e5%9e%8b%e6%a6%82%e8%bf%b0.html#comments</comments>
		<pubDate>Mon, 11 May 2009 15:04:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e4%ba%8c%e3%80%91-contentprovider%e6%95%b0%e6%8d%ae%e6%a8%a1%e5%9e%8b%e6%a6%82%e8%bf%b0.html</guid>
		<description><![CDATA[from： http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html
Android的数据（包括files, database等&#8230;）都是属于应用程序自身，其他程序无法直接进行操作。因此，为了使其他程序能够操作数据，在Android中，可以通过做成 ContentProvider提供数据操作的接口。其实对本应用而言，也可以将底层数据封装成ContentProvider，这样可以有效的屏蔽底层 操作的细节，并且是程序保持良好的扩展性和开放性。
ContentProvider，顾名思义，就是数据内容的供应者。在Android中它是一 个数据源，屏蔽了具体底层数据源的细节，在ContentProvider内部你可以用Android支持的任何手段进行数据的存储和操作，可能比较常用 的方式是基于Android的SQLite数据库（恩，文档中和示例代码都是以此为例）。无论如何，ContentProvider是一个重要的数据源， 可以预见无论是使用和定制ContentProvider都会很多。于是花了点时间仔细看了看。
数据库操作
从 我目前掌握的知识来看，SQLite比较轻量（没有存储过程之类的繁杂手段），用起来也比较简单。实例化一个SQLiteDatabase类对象，通过它 的APIs可以搞定大部分的操作。从sample中看，Android中对db的使用有一种比较简单的模式，即派生一个 ContentProviderDatabaseHelper类来进行SQLiteDatabase对象实例的获取工作。基本上， ContentProviderDatabaseHelper类扮演了一个singleton的角色，提供单一的实例化入口点，并屏蔽了数据库创建、打开 升级等细节。在ContentProvider中只需要调用ContentProviderDatabaseHelper的openDatabase方法 获取SQLiteDatabase的实例就好，而不需要进行数据库状态的判断。
URI
像 进行数据库操作需要用SQL一样，对ContentProivder进行增删改查等操作都是通过一种特定模式的URI来进行的（ig：content: //provider/item/id），URI的能力与URL类似，具体细节可以查看SDK。建立自己的ContentProvider，只需要派生 ContentProivder类并实现insert, delete, update等抽象函数即可。在这些接口中比较特殊的是getType(uri)。根据传入的uri，该方法按照MIME格式返回一个字符串（==!没听 过的诡异格式&#8230;）唯一标识该uri的类型。所谓uri的类型，就是描述这个uri所进行的操作的种类，比如content://xx/a与 content://xx/a/1不是一个类型（前者是多值操作，后者是单值），但content://xx/a/1和content://xx/a/2 就会是一个类型（只是id号不同而已）。
在ContentProvider通常都会实例化一个ContentURIPraser来辅助解析和操作 传入的URI。你需要事先（在static域内）为该ContentURIPraser建立一个uri的语法树，之后就可以简单调用 ContentURIPraser类的相关方法进行uri类型判断（match方法），获取加载在uri中的参数等操作。但我看来，这只是在使用上简化了 相关操作（不然就需要自己做人肉解析了&#8230;），但并没有改变类型判定的模式。你依然需要用switch&#8230;case&#8230;对uri的类型进行判断，并 进行相关后续的操作。从模式来看，这样无疑是具有强烈的坏味道，类似的switch&#8230;case&#8230;代码要出现N此，每次一个 ContentProvider做uri类型的增减都会需要遍历修改每一个switch&#8230;case&#8230;，当然，如果你使用模式（策略模式&#8230;）进 行改造对手机程序来说无疑是崩溃似的（类型膨胀，效率降低&#8230;），所以，只能是忍一忍了（恩，还好不会扩散到别的类中，维护性上不会有杀人性的麻 烦&#8230;）。
增删改查
ContentProvider 和所有数据源一样，向外提供增删改查操作接口，这些都是基于uri的指令。进行insert操作的时候，你需要传入一个uri和 ContentValues。uri的作用基本就限于指明增减条目的类型（从数据库层面来看就是table名），ContentValues是一个 key/value表的封装，提供方便的API进行插入数据类型和数据值的设置和获取。在数据库层面上来看，这应该是column name与value的对应。但为了屏蔽ContentProvider用户涉及到具体数据库的细节，在Android的示例中，用了一个小小的模式。它 为每一个表建一个基于BaseColumn类的派生类（其实完全可以不派生自BaseColumn，特别当你的表不基于默认的自动id做主键的时候），这 个类通常包括一个描述该表的ContentURI对象和形如 public static final TITLE = &#8220;title&#8221;这样的column到类数据的对应。从改变上角度来看，你可以修改column的名字而不需要更改用户上层代码，增加了灵活性。 insert方法如果成功会返回一个uri，该uri会在原有的uri基础上增加有一个row id。对于为什么使用row id而不是key id我想破了脑袋。到最后，我发现我傻了，因为ContentProvider不一定需要使用数据库，使用数据库对应的表也可以没有主键，只有row id，才能在任何底层介质下做索引标识。
但，基于row id在删除和修改操作是会造成一定的混乱。删除和修改操作类似。删除操作需要传入一个uri，一个where字串，一组where的参数（做条件判 定&#8230;），而修改操作会多一个ContentValues做更新值。着两个操作的uri都支持在末尾添加一个row id。于是混乱就出现了。当在where参数中指明了key id，而在uri中提供了row id，并且row id和key id所指函数不一致的时候，你听谁的？示例代码中的做法是完全无视row id（无语&#8230;），如此野蛮的方式我估计也只能在示例中出现，在实际中该如何用，恩，我也不知道。幸运的是，我看了下上层对 ContentProvider的删除操作，其实都不会直接进行，而是通过调用Cursor的delete方法进行，在这前提下，我想Cursor会处理 好这些东西吧。
最后一个操作是查询操作，可以想见，查询的参数是最多的，包括uri和一组条件参数。条件参数类型和标准的sql类似，包括 [...]]]></description>
			<content:encoded><![CDATA[<p>from： <a href="http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html">http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html</a></p>
<p>Android的数据（包括files, database等&#8230;）都是属于应用程序自身，其他程序无法直接进行操作。因此，为了使其他程序能够操作数据，在Android中，可以通过做成 ContentProvider提供数据操作的接口。其实对本应用而言，也可以将底层数据封装成ContentProvider，这样可以有效的屏蔽底层 操作的细节，并且是程序保持良好的扩展性和开放性。<br />
ContentProvider，顾名思义，就是数据内容的供应者。在Android中它是一 个数据源，屏蔽了具体底层数据源的细节，在ContentProvider内部你可以用Android支持的任何手段进行数据的存储和操作，可能比较常用 的方式是基于Android的SQLite数据库（恩，文档中和示例代码都是以此为例）。无论如何，ContentProvider是一个重要的数据源， 可以预见无论是使用和定制ContentProvider都会很多。于是花了点时间仔细看了看。</p>
<p><span style="font-size: medium;"><span>数据库操作</span></span><br />
从 我目前掌握的知识来看，SQLite比较轻量（没有存储过程之类的繁杂手段），用起来也比较简单。实例化一个SQLiteDatabase类对象，通过它 的APIs可以搞定大部分的操作。从sample中看，Android中对db的使用有一种比较简单的模式，即派生一个 ContentProviderDatabaseHelper类来进行SQLiteDatabase对象实例的获取工作。基本上， ContentProviderDatabaseHelper类扮演了一个singleton的角色，提供单一的实例化入口点，并屏蔽了数据库创建、打开 升级等细节。在ContentProvider中只需要调用ContentProviderDatabaseHelper的openDatabase方法 获取SQLiteDatabase的实例就好，而不需要进行数据库状态的判断。</p>
<p><span style="font-size: medium;"><span>URI</span></span><br />
像 进行数据库操作需要用SQL一样，对ContentProivder进行增删改查等操作都是通过一种特定模式的URI来进行的（ig：content: //provider/item/id），URI的能力与URL类似，具体细节可以查看SDK。建立自己的ContentProvider，只需要派生 ContentProivder类并实现insert, delete, update等抽象函数即可。在这些接口中比较特殊的是getType(uri)。根据传入的uri，该方法按照MIME格式返回一个字符串（==!没听 过的诡异格式&#8230;）唯一标识该uri的类型。所谓uri的类型，就是描述这个uri所进行的操作的种类，比如content://xx/a与 content://xx/a/1不是一个类型（前者是多值操作，后者是单值），但content://xx/a/1和content://xx/a/2 就会是一个类型（只是id号不同而已）。<br />
在ContentProvider通常都会实例化一个ContentURIPraser来辅助解析和操作 传入的URI。你需要事先（在static域内）为该ContentURIPraser建立一个uri的语法树，之后就可以简单调用 ContentURIPraser类的相关方法进行uri类型判断（match方法），获取加载在uri中的参数等操作。但我看来，这只是在使用上简化了 相关操作（不然就需要自己做人肉解析了&#8230;），但并没有改变类型判定的模式。你依然需要用switch&#8230;case&#8230;对uri的类型进行判断，并 进行相关后续的操作。从模式来看，这样无疑是具有强烈的坏味道，类似的switch&#8230;case&#8230;代码要出现N此，每次一个 ContentProvider做uri类型的增减都会需要遍历修改每一个switch&#8230;case&#8230;，当然，如果你使用模式（策略模式&#8230;）进 行改造对手机程序来说无疑是崩溃似的（类型膨胀，效率降低&#8230;），所以，只能是忍一忍了（恩，还好不会扩散到别的类中，维护性上不会有杀人性的麻 烦&#8230;）。</p>
<p><span style="font-size: medium;"><span>增删改查</span></span><br />
ContentProvider 和所有数据源一样，向外提供增删改查操作接口，这些都是基于uri的指令。进行insert操作的时候，你需要传入一个uri和 ContentValues。uri的作用基本就限于指明增减条目的类型（从数据库层面来看就是table名），ContentValues是一个 key/value表的封装，提供方便的API进行插入数据类型和数据值的设置和获取。在数据库层面上来看，这应该是column name与value的对应。但为了屏蔽ContentProvider用户涉及到具体数据库的细节，在Android的示例中，用了一个小小的模式。它 为每一个表建一个基于BaseColumn类的派生类（其实完全可以不派生自BaseColumn，特别当你的表不基于默认的自动id做主键的时候），这 个类通常包括一个描述该表的ContentURI对象和形如 public static final TITLE = &#8220;title&#8221;这样的column到类数据的对应。从改变上角度来看，你可以修改column的名字而不需要更改用户上层代码，增加了灵活性。 insert方法如果成功会返回一个uri，该uri会在原有的uri基础上增加有一个row id。对于为什么使用row id而不是key id我想破了脑袋。到最后，我发现我傻了，因为ContentProvider不一定需要使用数据库，使用数据库对应的表也可以没有主键，只有row id，才能在任何底层介质下做索引标识。<br />
但，基于row id在删除和修改操作是会造成一定的混乱。删除和修改操作类似。删除操作需要传入一个uri，一个where字串，一组where的参数（做条件判 定&#8230;），而修改操作会多一个ContentValues做更新值。着两个操作的uri都支持在末尾添加一个row id。于是混乱就出现了。当在where参数中指明了key id，而在uri中提供了row id，并且row id和key id所指函数不一致的时候，你听谁的？示例代码中的做法是完全无视row id（无语&#8230;），如此野蛮的方式我估计也只能在示例中出现，在实际中该如何用，恩，我也不知道。幸运的是，我看了下上层对 ContentProvider的删除操作，其实都不会直接进行，而是通过调用Cursor的delete方法进行，在这前提下，我想Cursor会处理 好这些东西吧。<br />
最后一个操作是查询操作，可以想见，查询的参数是最多的，包括uri和一组条件参数。条件参数类型和标准的sql类似，包括 sort, projection 之类的。从这些参数到sql语句的生成，可以寻求QueryBuilder类的帮助，它提供了一组操作接口，简化了参数到sql的生成工作，哪怕你不懂 sql都完全没有问题（这话说的我自己都觉得有点悬&#8230;）。查询返回一个Cursor。Cursor是一个支持随机读写的指针，不仅如此，它还提供了方 便的删除和修改的API，是上层对ContentProvider进行操作一个重要对象，需要仔细掌握（Cursor还可以绑定到view上，直接送显， 并与用户进行交互，真是程序越往上，封装越好，工作越机械没有复杂性了&#8230;）。</p>
<p><span style="font-size: medium;"><span>数据模型</span></span><br />
在 与界面打交道的Cursor、ContentResolver等数据操作层中，大量采用观察者模式建立数据层与显示层的联系。一个显示层的视图，可以做成 某一种观察者注册到Cursor或ContentResolver等数据中间层中，在实现底层ContentProvider中，我们需要特别注意在对数 据进行修改操作（包括增删改&#8230;）后，调用相应类型的notify函数，帮助表层对象进行刷新（还有一种刷新方式是从一个view发起的）。可以看到 Android的整体数据显示框架有点像MVC的方式（贫瘠了&#8230;叫不出名）。Cursor、ContentResolver相当于控制层，数据层和显 示层的交互通过控制层来掌管，而且控制层很稳定不需要特别定制，通常工作只在定制数据层和显示层空间，还是比较方便和清晰的。</p>
<p><span style="font-size: medium;"><span>一个设计问题</span></span><br />
现 在有个设计问题，比如我要扩充一个已有的ContentProvider（第三方提供），我是建立一个ContentProvider，只保留第三方 ContentProvider的key信息，并为其添加更多的信息，在表层维护这两个ContentProvider的联系好；还是建议一个 ContentProvider，以第三方的ContentProvider做一部分底层数据源，像表层提供一个ContentProvider好。<br />
前者无疑在实现上简单一些，如果第三方改变，灵活性也更好，只是需要仔细维护表层的相关代码。后者实现上需要付出大量的苦力劳动，当表层使用会简单多了。我举棋不定，期待你的意见。。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%ba%8c%e3%80%91-contentprovider%e6%95%b0%e6%8d%ae%e6%a8%a1%e5%9e%8b%e6%a6%82%e8%bf%b0.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Study on Android【一】&#8211;概述</title>
		<link>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%80%e3%80%91-%e6%a6%82%e8%bf%b0.html</link>
		<comments>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%80%e3%80%91-%e6%a6%82%e8%bf%b0.html#comments</comments>
		<pubDate>Mon, 11 May 2009 14:45:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[study on android]]></category>

		<guid isPermaLink="false">http://www.yaaahaaa.com/2009/05/11/study-on-android%e3%80%90%e4%b8%80%e3%80%91-%e6%a6%82%e8%bf%b0.html</guid>
		<description><![CDATA[from：http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html
 
如果你还不知道google的重磅炸弹Android（中文意思是机器人&#8230;感觉google取名字的天赋全部花在google这个词上了&#8230;）是什么，你可以看一下这里。如果你觉得挺没有意思，再看一下这里。如果还觉得不好玩，那下面的东西就不需要看了。。。
对我来说，Android还是很有吸引力的，不然一个MS技术的忠实走狗也不至于一下就投入java的怀抱。至于为什么？恩，等我有八卦精神的时候再使劲的侃。
在这里还是谈正事的要紧。这几天看了下Android SDK，编了几个练习，获得了一点点经验。简单的罗列一下，比较重要的内容都添上链接，也是方便我和所有需要的人查看。
 
按google的说法Android包括一个操作系统，一些中间件和核心应用程序。操作系统是基于Linux的，上面的东西用了些开源的、google也花了不少精力开发了其他一些东东。底层用的是C++，但所有供应用程序开发的API都是java的（伪托管操作系统？^_^）。具体内容可以看一下这里 。基本上不会与你闭着眼睛幻想的有太大区别。
Android的GUI框架，你可以从你本身的编程经验中看到很多的影子（对我而言主要是.net winform &#38;&#38; asp.net，但感觉上很多理念与WPF类似，只是我对WPF只是走马观花的了解了一些*_*，谈不上有任何经验&#8230;）。
首先，在Android中，每一个需要显示并运行的程序都需要有一个Activity 类的派生类，从某个程度上来说它有点类似于Page的概念。每一个Activity从直观上来看就是一屏幕的内容，当你切换了屏幕，基本上就意味着你切换了一个Activity。Activity负责管理界面上的各个显示控件，最重要的，是它提供了基本的生命周期管理的函数，包括OnCreate, OnResume, OnFreeze, OnPause等等。从名字上，就可以大致看出这些函数所负责的内容，但你一定要明白他们具体分工的区别，具体情况查看一下这里 。但与Page不同的是，当一个Activity被切换出去的时候（你随时可能在你未完成所需事情的时候离开一个Activity，因为你用的是手机，你要随时准备接电话，准备迎接GF，准备与悄悄从后面摸过来的老板据理力争），你会希望回来还看到一样的内容。因此，你对Activity的生命管理尤其的重要（特别是当你了解了Android的进程管理的时候&#8230;），你可能需要在各个周期点上负责保管状态、恢复状态、传送数据等工作。
当你从一个界面切换到另一个界面的时候，就涉及到了Activity的切换。当你做这个工作的时候，你需要用到Intent，它包含切换所需的动作、（动作）分类、传送数据等信息。这个类的工作虽然简单，但内容丰富，建议仔细看看SDK，因为开发中你会反复与它打交道，而且可能你需要在两个Activity切换时做很多事情，比如传数据、做一些限定，都需要你对Intent比较熟悉。在配置文档中，你可以使用IntentFilter 对Intent进行过滤和匹配。在一个进程中，系统会维护一个Activity历史记录栈，以更好的维护Activity之间的交互。
在切换过程中（和其它一些场合），你需要传送数据。在Android中，你需要使用到一个Bundle 的类来传输。Bundle是其实一个key/value的map，不过它提供了很多API，用起来会比较方便。用这种统一格式来传输数据，在所需数据一定时会使判定比较简单，不需要太在乎是谁什么时候进行的传输。
每一个Activity还需要负责加载这个Activity所需要的显示的内容。显示的每一个部分称作一个view（你可以对应到control上），每一个都会处理键盘等交互事件、完成相应功能，并进行绘制。view的组织基本可以看成是一个复合模式，每一个view还会有相应的style，具体可以看这里。通过派生不同的view类，你可以定制你所需要的特定view（自定义控件&#8230;），它可以是简单的多view的特定布局组合，也可以是完成某种特殊功能。一般你会需要重载onDraw和onMeasure，具体可以看这里，规则还是有点小繁琐的。
但view的构造、layout的设定、样式的设定等等工作，通常不会使用显性的java代码进行编制，而是通过XML进行配置（WPF！！）。所有的资源也都是通过这种方式进行提供（查看这里）。而XML配置文件与代码的联系，是通过R类来进行的。R类是动态构造，它里面有一对的内嵌类，内嵌类里有一堆的静态int ID值。它是有系统自动根据配置文档的增删进行维护（in Eclipse&#8230;），完成从名字到ID的转换工作。而所有接受这种ID值的API，都会负责根据XML进行资源的配置。
Android的进程管理和资源管理都很有意思。通常，每一个应用程序（入口会是一个Activity的onCreate），都会占据一个进程。但这个进程是托管的！！你无法确定它何时会被回收，当系统进程空间紧张的时候，会依照优先级自动进行进程的回收（查看这里 ）。由此可以看到，维护一个Activity的生命周期是多么的重要，因为它随时会被系统干掉*_*。同时，每一个应用程序的数据都是独享的。就是你存在数据库、文件的数据别的程序无法访问（其实根本是无法获知）。要在应用间共享数据，比较好的一个策略是把自己做成contentProvider，其他应用可以通过提交特定格式URL申请你的数据×—×（Why URL?&#8230;）。
除了Activity，还有就是server。顾名思义，这就是幕后英雄的角色。他们不在屏幕上占据任何位置，只是在后台默默工作。与他们交互的方法比较传统，主要是监听一些事件。当然很多时候这需要权限，因此你需要了解一些具体内容。
每一个应用都会有一个Manifest.xml，提供全局的配置。包括设置权限，设置各个Activity的属性等等。维护这个配置文件是一项基本任务（当你添加了新的Activity的时候），因为好像插件不会帮你完成这件比较琐碎的事情。
 
本来还看了其他更多的内容。写累了，不写了。其他等有了更多经验再慢慢写吧。如果想学个入门的话，还是建议好好看SDK。Doc基本上是把你看成一无所知（实际上，我就是这样*_*），而源码里也是包含海量的注释（只是时不时就有几个词打错&#8230;），连我如此弱的人都感觉看得不错，可想而知这SDK做的还是非常好的。。。
]]></description>
			<content:encoded><![CDATA[<p>from：<a href="http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html">http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html</a></p>
<p> </p>
<p><span>如果你还不知道google的重磅炸弹Android（中文意思是机器人&#8230;感觉google取名字的天赋全部花在google这个词上了&#8230;）是什么，你可以看一下</span><a id="q89_" title="这里" href="http://code.google.com/android/"><span>这里</span></a><span>。如果你觉得挺没有意思，再看一下</span><a id="b0no" title="这里" href="http://code.google.com/android/adc.html"><span>这里</span></a><span>。如果还觉得不好玩，那下面的东西就不需要看了。。。</span></p>
<p><span>对我来说，Android还是很有吸引力的，不然一个MS技术的忠实走狗也不至于一下就投入java的怀抱。至于为什么？恩，等我有八卦精神的时候再使劲的侃。</span></p>
<p><span>在这里还是谈正事的要紧。这几天看了下Android SDK，编了几个练习，获得了一点点经验。简单的罗列一下，比较重要的内容都添上链接，也是方便我和所有需要的人查看。</span></p>
<p><span> </span></p>
<p><span>按google的说法Android包括一个操作系统，一些中间件和核心应用程序。操作系统是基于Linux的，上面的东西用了些开源的、google也花了不少精力开发了其他一些东东。底层用的是C++，但所有供应用程序开发的API都是java的（伪托管操作系统？^_^）。具体内容可以看一下</span><a id="m6pg" title="这里" href="http://code.google.com/android/what-is-android.html"><span>这里</span></a><span> 。基本上不会与你闭着眼睛幻想的有太大区别。</span></p>
<p><span>Android的GUI框架，你可以从你本身的编程经验中看到很多的影子（对我而言主要是.net winform &amp;&amp; asp.net，但感觉上很多理念与WPF类似，只是我对WPF只是走马观花的了解了一些*_*，谈不上有任何经验&#8230;）。</span></p>
<p><span>首先，在Android中，每一个需要显示并运行的程序都需要有一个</span><a id="q1pb" title="Activity" href="http://code.google.com/android/reference/android/app/Activity.html"><span>Activity</span></a><span> 类的派生类，从某个程度上来说它有点类似于Page的概念。每一个Activity从直观上来看就是一屏幕的内容，当你切换了屏幕，基本上就意味着你切换了一个Activity。Activity负责管理界面上的各个显示控件，最重要的，是它提供了基本的生命周期管理的函数，包括OnCreate, OnResume, OnFreeze, OnPause等等。从名字上，就可以大致看出这些函数所负责的内容，但你一定要明白他们具体分工的区别，具体情况查看一下</span><a id="oa2v" title="这里" href="http://code.google.com/android/intro/tutorial-ex3.html"><span>这里</span></a><span> 。但与Page不同的是，当一个Activity被切换出去的时候（你随时可能在你未完成所需事情的时候离开一个Activity，因为你用的是手机，你要随时准备接电话，准备迎接GF，准备与悄悄从后面摸过来的老板据理力争），你会希望回来还看到一样的内容。因此，你对Activity的生命管理尤其的重要（特别是当你了解了Android的进程管理的时候&#8230;），你可能需要在各个周期点上负责保管状态、恢复状态、传送数据等工作。</span></p>
<p><span>当你从一个界面切换到另一个界面的时候，就涉及到了Activity的切换。当你做这个工作的时候，你需要用到</span><a id="l8m2" title="Intent" href="http://code.google.com/android/reference/android/content/Intent.html"><span>Intent</span></a><span>，它包含切换所需的动作、（动作）分类、传送数据等信息。这个类的工作虽然简单，但内容丰富，建议仔细看看SDK，因为开发中你会反复与它打交道，而且可能你需要在两个Activity切换时做很多事情，比如传数据、做一些限定，都需要你对Intent比较熟悉。在配置文档中，你可以使用</span><a id="pi7r" title="IntentFilter" href="http://code.google.com/android/reference/android/content/IntentFilter.html"><span>IntentFilter</span></a><span> 对Intent进行过滤和匹配。在一个进程中，系统会维护一个Activity历史记录栈，以更好的维护Activity之间的交互。</span></p>
<p><span>在切换过程中（和其它一些场合），你需要传送数据。在Android中，你需要使用到一个</span><a id="gbwi" title="Bundle" href="http://code.google.com/android/reference/android/os/Bundle.html"><span>Bundle</span></a><span> 的类来传输。Bundle是其实一个key/value的map，不过它提供了很多API，用起来会比较方便。用这种统一格式来传输数据，在所需数据一定时会使判定比较简单，不需要太在乎是谁什么时候进行的传输。</span></p>
<p><span>每一个Activity还需要负责加载这个Activity所需要的显示的内容。显示的每一个部分称作一个view（你可以对应到control上），每一个都会处理键盘等交互事件、完成相应功能，并进行绘制。view的组织基本可以看成是一个复合模式，每一个view还会有相应的style，具体可以看这里。通过派生不同的view类，你可以定制你所需要的特定view（自定义控件&#8230;），它可以是简单的多view的特定布局组合，也可以是完成某种特殊功能。一般你会需要重载onDraw和onMeasure，具体可以看</span><a id="zlb4" title="这里" href="http://code.google.com/android/toolbox/custom-components.html"><span>这里</span></a><span>，规则还是有点小繁琐的。</span></p>
<p><span>但view的构造、layout的设定、样式的设定等等工作，通常不会使用显性的java代码进行编制，而是通过XML进行配置（WPF！！）。所有的资源也都是通过这种方式进行提供（查看这里）。而XML配置文件与代码的联系，是通过R类来进行的。R类是动态构造，它里面有一对的内嵌类，内嵌类里有一堆的静态int ID值。它是有系统自动根据配置文档的增删进行维护（in Eclipse&#8230;），完成从名字到ID的转换工作。而所有接受这种ID值的API，都会负责根据XML进行资源的配置。</span></p>
<p><span>Android的进程管理和资源管理都很有意思。通常，每一个应用程序（入口会是一个Activity的onCreate），都会占据一个进程。但这个进程是托管的！！你无法确定它何时会被回收，当系统进程空间紧张的时候，会依照优先级自动进行进程的回收（查看</span><a id="dzvh" title="这里" href="http://code.google.com/android/intro/lifecycle.html"><span>这里</span></a><span> ）。由此可以看到，维护一个Activity的生命周期是多么的重要，因为它随时会被系统干掉*_*。同时，每一个应用程序的数据都是独享的。就是你存在数据库、文件的数据别的程序无法访问（其实根本是无法获知）。要在应用间共享数据，比较好的一个策略是把自己做成contentProvider，其他应用可以通过提交特定格式URL申请你的数据×—×（Why URL?&#8230;）。</span></p>
<p><span>除了Activity，还有就是server。顾名思义，这就是幕后英雄的角色。他们不在屏幕上占据任何位置，只是在后台默默工作。与他们交互的方法比较传统，主要是监听一些事件。当然很多时候这需要权限，因此你需要了解一些具体内容。</span></p>
<p><span>每一个应用都会有一个Manifest.xml，提供全局的配置。包括设置权限，设置各个Activity的属性等等。维护这个配置文件是一项基本任务（当你添加了新的Activity的时候），因为好像插件不会帮你完成这件比较琐碎的事情。</span></p>
<p><span> </span></p>
<p><span>本来还看了其他更多的内容。写累了，不写了。其他等有了更多经验再慢慢写吧。如果想学个入门的话，还是建议好好看SDK。Doc基本上是把你看成一无所知（实际上，我就是这样*_*），而源码里也是包含海量的注释（只是时不时就有几个词打错&#8230;），连我如此弱的人都感觉看得不错，可想而知这SDK做的还是非常好的。。。</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.result-search.com/sty/2009/05/11/study-on-android%e3%80%90%e4%b8%80%e3%80%91-%e6%a6%82%e8%bf%b0.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
