蓝色主题DynaBlue完全使用手册

This item was filled under [ 一步一步学习 ]

主题地址:http://themes.wopus.org/wpthemes/two-column/1242.html

1、这款主题有很多广告位可以使用,在主题LOGO右侧,可以放置一个468×60的banner广告。
添加办法:
在 header.php中找到如下代码:
view source
print?
1.
< ?php theme_banner_468_ads_show(); ?>

找到广告代码,替换
view source
print?
1.< ?php theme_banner_468_ads_show(); ?>

2、顶部幻灯片轮换这里,展示4篇文章,这里可以只是文字,也可以是图文的,图片大小是:161×107,这里需要使用到这个插件:featureme.zip,启用插件之后,在发布日志页面,最下方有一行文字:This is a really cool entry, Feature it!,勾选之后,这篇日志就会出现在幻灯片轮换这里了。
如果需要在幻灯片轮换中加入图片,需要使用到自定义字段功能,创建一个名为:thumbnail的自定义字段,然后自定义字段的值是图片的完整路径。

3、Feed的地址可以通过在header.php里添加。Twitter的地址可以在后台添加。ID就是在twitter上的登录用户名。

4、这款主题有九宫格,但是我在主题后台找了很久都没有找到实现的方法,不知道是不是在widgets的text里添加代码来完成的。

主题的使用基本就到这里了。主题还是很不错的,大家可以配合这篇教程来使用这款主题。

Bookmark and Share
Tagged with: [ ]

借助免费的Android Apps来赚钱

This item was filled under [ 一步一步学习 ]

相信很多做Andoird开发的人都有着靠其赚钱的目的,这里看到一篇文章,说了如何使用免费的Android Apps来赚钱,分别是:


  • 1.在免费的应用程序中嵌入广告。
  • 2. 肉包子效应。
  • 3.寻求直接赞助商。
  • 4.Micro Transactions – 建立一种小额捐赠从而获得程序更多功能的盈利模式

希望这篇文章可以给大家编写免费app的时候提供一些赚钱的思路。

来源:http://androiddevstudio.com/business/4-ways-to-monetize-free-android-application
中文有人翻译了:http://www.androidres.com/?p=408

————-转载正文——————–

相信不少人有过啃着方便面埋头写代码的经历,特别针对当今这个经济不景气的大背景下,存在许许多多依然执着追求梦想的人。梦想指引了前进的方向,而现实中的前进步伐过于缓慢,前方那个若隐若现的目标渐渐变得模糊不清。停!今天先不讨论如何“料理后事”,身处洪水中的我们如何才能选择一块带来希望的浮木。开篇的废话是一些糟料,目的是感受极端恶劣的环境后,才更容易得到满足感,这样接下来所说的内容才可能有意义。

希特勒把天赋用错的了地方,他给我们带来了第二次世界大战!乔布斯把天赋用对了地方,他给我们带来了App Store(我的确是Apple的信徒,但这与我喜欢Android不矛盾,从盈利模式上来看App Store 和Android Market存在 很多相通之处)。
很多人曾经借助App Store实现了各自的梦想(有了房子 – 讨到了老婆 – 买一辆四个轱辘的交通工具等等)。然而如果你刚刚了解到这个“新生”事物(特别针对刚刚了解这个产业的同仁)所带来的价值,并希望通过复制前辈的模式取得同样的成功,就目前的形式而言越来越困难了,为什么呢?
原因有三:

App Store应用程序数量(包括免费和收费)已突破25000,并且依然保持着快速增长趋势。

  • 大量优秀的免费程序可以满足很多人的一般性需要。
  • 设计一款别出心裁的产品越来越难。

也许你有更多的补充,但总的来说现实条件不允许我们可以偶然获得成功,尤其是不能单单只靠消费者下载收费程序来获得丰厚的回报。想起这样一句话“只要思想不滑坡,办法总比困难多”,面对目前这样的形式,我们应该考虑如何用不同于前辈的方式取得成功?下边将介绍四种靠发布免费Apps来赚钱的方法:

1,在免费的应用程序中嵌入广告。
这绝对不是一个崭新的Idea,很多人早就已经考虑过这种赚钱的模式。这里把它放在第一位来介绍的目的是可以让这种方式充分的产生价值,有两个很客观的问题需要面对,第一,要尽可能多的展现广告内容,针对不同的用户提供更精准的偏好广告。第二,为了让广告有展现的机会,不能让用户有不舒服的感觉,因为手机资源的局限性,才更需要考虑消费者的操作习惯。
针对以上的理由,可以放置广告的区域非常有限,下边提供两个可以放置广告的参考:

  • 程序主界面:可以放置一些简单的文字性广告,但需要特别考虑用户体验。毕竟用户下载使用你的程序为了它自身的功能性,而不是要被强制浏览你的广告。对于游戏程序而言,可以考虑在关卡跳转的时候利用加载界面方式一些醒目的广告。
  • 利用某些辅助性的界面:程序会包含一些辅助性的Activity,比如:关于我们、程序功能介绍和政策条款等。基于这些页面放置一些广告不会破坏或者影响用户对程序的使用体验,相对其广告效果也要打折扣。但相比主界面,则可以放置一些更加醒目和丰富的广告内容。

下面是一些可以寻求广告合作的列表:

相比于放置广告的位置,还有另外一点需要受到关注。当用户在程序中点击某一广告后,可能需要启动Browser,这会让当前的程序失去“焦点”。为此尽管某些广告被用户关注,但却大大降低了用户体验的流畅性。有个非常直接的方法来解决这个问题,在程序中使用WebView来显示广告内容,而避免启动外部的Browser。这样可以保证当前程序仍然处于前台运行,当用户关掉广告内容后,可以非常容易的返回到查看广告之前的状态,从而保护了程序用户体验的流畅度。


2. 肉包子效应。
这种方式适合于已经在庞大用户群中被广泛应用的程序,利用其自身的价值邀请用户访问你的网站,从而达到宣传网站的目的。通过放置链接或者某些明显的提示来引导用户,而且一定要让用户清楚自己查看某些外部资源的目的(谨慎小心,避免给用户一些“Surprise”)。
建议同样借鉴与方法一中提到的利用Loading页面来展示信息内容,避免强制用户履行查看广告的行为。

3.寻求直接赞助商。
这相比于第二种方法显得难度更大一些,毕竟涉及到与第三方合作。需要将当前程序的固定用户群作为筹码来寻求善良的赞助商,这有点类似于经常在中国足球圈里听到的“冠名”,比如在程序中显示赞助商的Logo或者用一些简单的介绍文字“Sponsored By…”等等。

4.Micro Transactions – 建立一种小额捐赠从而获得程序更多功能的盈利模式。
正如小标题中对“Micro Transactions”的解释,采用小额的费用(通常由用户自己选择支付的额度)来支持某一款软件的后续研发,类似于Donation(捐助)。捐助者可以从其行为中获得一定的奖励,可以使用程序的更多功能(即便用户没有捐赠行为,也需要保证程序最低功能要求),或者效仿腾讯此前的做法,只需花费非常少的金钱取得会员身份之后,就可以避免系统弹出广告。
以上四种方法并不是标准的理论,仅仅是作为一种可行的方法与大家共同探讨,欢迎不一样的声音,或者提供更新鲜的赚钱方法给大家。

Bookmark and Share

深入淺出 Android — Google 手持設備應用程式設計

This item was filled under [ 一步一步学习 ]

授權

  

歡迎到 http://code.google.com/p/androidbmi/wiki/IntroAndroid 閱讀本書。 也歡迎使用留言功能提供建議。

本書採用創用CC:「姓名標示─非商業性─禁止改作」授權條款

本書的文字、圖片皆不歡迎轉載,也不可使用於商業用途。 但歡迎您將本書網址 http://code.google.com/p/androidbmi/wiki/IntroAndroid 分享到各網站。

作者

  • gasolin,項目發起人,也是本書的主筆。你可以寫信至 gasolin+android -at- gmail.com 聯絡作者。

作者的作品有 aTrackDog 軟體更新通知程式。在 Android Market 上架三天,下載數即破2萬。

近期寫的 Anobiit 程式,讓我也成為 zxing(Barcode scanner) 專案的 Contributor。

致謝

  • Crota,在項目初期提供建議等許多協助。

簡介

「深入淺出 Android 手持設備應用程式設計」將以開發實例,講解 Android 應用程式開發,協助讀者了解 Android 手持設備的應用程式設計。

回響

歡迎任何建設性的建議、批評、或者讚美。作者的電子郵件信箱是 gasolin+android -at- gmail.com。

想在簡單易學和提供完整詳盡的資訊之間取得平衡,一直是種永恆的掙扎。 期望讀者您能提供一些反饋,讓作者能更好地掌握主題深入的程度。

目錄

入門

  1. 初探 Android
  2. 安裝 Android 開發工具
  3. 開啟現有專案
  4. 操作 Android 模擬器(Emulator)
  5. 建立一個 Android 程式 (BMI0)

基礎

  1. 描述使用者介面
  2. 設計使用者介面 (BMI01)
  3. 存取識別符號
  4. 解讀程式流程 (BMI02)
  5. 完成 BMI 程式

中階

  1. 重構程式 (BMI03)
  2. 加入對話框(Dialog)
  3. 初見 Intent
  4. 加入選單(Menu) (BMI4)
  5. 定義 Android 清單
  6. 加入新 Activity (BMI5)
  7. 傳送資料到新 Activity(BMI6)
  8. 記錄與偵錯 (Log)
  9. 活動的生命週期
  10. 儲存資訊(Preference)(BMI7)
  11. 發佈到 Android 市集(Market)
  12. 開發不息

附錄

資源

  1. Android 相關資源 (相關資源)
  2. 後續章節
  3. 取得原始碼

範例

  1. gBMI:輸入身高體重(公制),計算出BMI值

Bookmark and Share

android内核编译方法

This item was filled under [ 一步一步学习 ]

google的android很多人都希望在gphone没有出来之前,把它移植到相关的硬件平台上去。网上看了不少文章,总的感觉是:在这一步走得最远的就是openmoko的一个大师级别的黑客 
Ben“Benno”Leslie,他曾经试图把目前google发布的android移植到openmoko的平台上去,并且做了10000多行代码的尝试。最终虽然由于open moko采用比较老的arm920t的内核,而android采用较新的arm926-ej-s内核,而且使用了新的内核的一些新特性,导致移植失败,但是anyway,他已经做了足够多的前期工作了,尔后的宣布成功移植android到real target板子上的人,大多是在他提供的patch的基础上继续走下去做出来的。 

下面是一些有用的参考,希望有助于对此感兴趣的开发人员: 
(1)Ben “Benno” Leslie的关于andorid移植到openmoko的个人博客地址: 
http://benno.id.au/blog/ 

(2)早期宣布成功移植android到zauraus-sl-c760的详细方法描述的链接: 
http://euedge.com/blog/2007/12/06/google-android-runs-on-sharp-zaurus-sl-c760/ 

(3)后续的根据上述先行者们的工作,成功移植android到zauraus-c3000的方法: 
http://androidzaurus.seesaa.net/article/74237419.html 

(4)本文是参考下面的wiki,接合个人的实践写出来的,对原文的作者表示一下感谢: 
http://wiki.droiddocs.net/Compilation_of_Android_kernel 

很羡慕这些人阿! 

不过很可惜,偶的开发板是s3c2410的,恰好是arm920t的核心的。。。估计移植上去戏不是很大,需要重写很多代码,毕竟偶跟benno相差得太远太远了,同样是开发人员,差距咋就那么大呢?! 
(毕竟google仅仅开放了kernel的源代码而已,他们需要开放的东西还很多。) 

在这里把关于android内核编译方法简单写一下,或许对希望移植内核的朋友能有些帮助: 
(看了Benno的移植过程以后,觉得即使你能够编译google开放出来的内核,意义也不是特别大,因为这个内核中加入了为了支持qemu的很多东西,而这些代码似乎对希望移植到真机上的朋友来说,没有任何意义,反而是一种阻碍)。 

1)从CodeSourcery上面载用于交叉编译的工具链: 
http://www.codesourcery.com/gnu_toolchains/arm/download.html 
我在这里选择的是->ARM GNU/Linux,以及IA32-GNU/Linux。有文章说应该选择ARM EABI,我不知道了,没有测试过,反正我选择的这个编译的内核也是可以跑起来的 

2)下载google的android linux的内核源代码: 
http://code.google.com/p/android/downloads/list 
主要是这个文件:linux-2.6.23-android-m3-rc20.tar.gz 
3)把下载到的内核和交叉编译工具解压缩,并最好把工具链的路径放到PATH里面去 
解压缩内核: 
$ mkdir -p android 
$ cd android 
$ tar xzvf ../linux-2.6.23-android-m3-rc20.tar.gz 
会解压出来一个叫做kernel的目录,google的android的linux内核就在里面了。 

解压缩交叉编译工具链: 
$ cd /usr/local/ 
$ sudo cp ~/arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 . 
$ sudo tar zxvf arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 
此时会解压出来一个叫做arm2007q3的一个目录,这里面就是工具链了。 

设置一下环境变量: 
$ export PATH=$PATH:/usr/local/arm2007q3/bin 
好了,到此,基本的内核编译环境就搞好了。 

4)现在是要得到android的内核编译参数的配置文件的时候了,该文件需要从已经安装好的android的模拟器 
中得到才行。所以安装android的sdk也是必须的,这一步不太明白的朋友可以参考我以前发的android 
命令行体验的文章。 
首先启动android模拟器,然后通过adb得到模拟器中提供的内核配置文件: 
$emulator & 
$adb pull /proc/config.gz . 
这时候adb工具会连接模拟器,并从它里面下载一个叫做config.gz的文件到你的当前目录下。 
把它拷贝到你的kernel目录: 
$cd ~/android/kernel 
$cp ~/config.gz . 
解压缩该文件,并重命名为.config,这一步做了就可以跳过make menuconfig之类的内核参数设置 
动作了。 
$gunzip config.gz 
$mv config .config 

5)修改kernel目录中的Makefile文件,用emacs或vi打开该Makefile 

修改CROSS_COMPILE变量为: 
CROSS_COMPILE=arm-none-linux-gnueabi- 
这个就是刚刚的下载和解压的工具链的前缀了,旨在告诉make,在编译的时候要使用我们的工具链。 

在Makefile中注释掉LDFLAGS_BUILD_ID这个变量: 
例如将如下定义: 
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ 
$(call ld-option, -Wl$(comma)–build-id,)) 
修改为: 
LDFLAGS_BUILD_ID= 
#LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ 
# $(call ld-option, -Wl$(comma)–build-id,)) 
把它注释掉的原因是目前android的内核还不支持这个选项。–build-id选项,主要是用于在生成的elf 
可执行文件中加入一个内置的id,这样在core dump,或者debuginfo的时候就可以很快定位这个模块是 
哪次build的时候弄出来的。这样就可以避免,每次都把整个文件做一遍效验,然后才能得到该文件的是由 
哪次build产生的。对于内核开发者来说,这是很不错的想法,可以节约定位模块版本和其影响的时间。 
目前,该功能还出于early stage的状态,未来的android或许会支持,但至少目前的版本是不支持的。 
所以,用#注释掉即可,或者害怕不保险的话,就加入LDFLAGS_BUILD_ID=空,这样即使编译的时候用了, 
也只是一个空格而已。 
对这个–build-id选项感兴趣的朋友,可以访问下面的网址,它的作者已经解释得非常明白了: 
http://fedoraproject.org/wiki/Releases/FeatureBuildId 

6)终于可以开始make了。 
$ make 
不出意外的话,应该整个过程都会非常顺利,最终会在~/android/kernel/arch/arm/boot目录下面 
生成一个zImage,这个就是我们要的内核映像了。 

7)激动人心的时刻终于到来了,我们可以测试一下刚刚编译出来的内核可以不可以用了。 
$emulator -kernel ~/android/kernel/arch/arm/boot/zImage 
当看到red eye在晃来晃去,最终显示出来android的界面的时候,一颗悬着的心总算放下了。 

android的proc里面的version如下: 
# cat version 
Linux version 2.6.23 (wayne@wayne) (gcc version 4.2.1 (CodeSourcery Sourcery G++ Lite 2007q3-51)) #1 Sat Jan 19 18:11:44 HKT 2008 
从这里就可以看出,这是自己编译的kernel,而不是人家sdk里面自带的kernel-qemu了。 

android自带的sdk里面的kernel映像的version应该是: 
# cat version 
Linux version 2.6.23-gcc3bc3b4 (arve@arvelnx.corp.google.com) (gcc version 4.2.1) #3 Tue Oct 30 16:28:18 PDT 2007 
hoho, 这里不会把这个开发者的email暴露出来了吧。。。 

android的cpuinfo如下: 
Processor : ARM926EJ-S rev 5 (v5l) 
BogoMIPS : 313.75 
Features : swp half thumb fastmult vfp edsp java 
CPU implementer : 0×41 
CPU architecture: 5TEJ 
CPU variant : 0×0 
CPU part : 0×926 
CPU revision : 5 
Cache type : write-through 
Cache clean : not required 
Cache lockdown : not supported 
Cache format : Harvard 
I size : 4096 
I assoc : 4 
I line length : 32 
I sets : 32 
D size : 65536 
D assoc : 4 
D line length : 32 
D sets : 512 

Hardware : Goldfish 
Revision : 0000 
Serial : 0000000000000000 
不过挺奇怪的,google sdk自带的内核映像的BogoMIPS是3.18的,偶编译出来的是3.13的。 
为了方便没有安装sdk的朋友也可以编译内核,我把config.gz贴上来: 

文件: config.gz
大小: 5KB
下载: 下载
Bookmark and Share

Study on Android【六】–消息机制,异步和多线程

This item was filled under [ study on android ]

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中,这扇窗户也被关闭了(至少我现在没发现…)。
在Android中,你想处理一些消息(比如:Keydown之类的…),你必须寻找Activity为你提供的一些重载函数(比如 onKeyDown之类的…)或者是各式各样的listener(比如OnKeyDownListner之类的…)。这样做的好处是显而易见的, 越多的自由就会有越多的危险和越多的晦涩,条条框框画好了,用起来省心看起来省脑,这是一个设计良好的framework应该提供的享受。对于我目前的工 程而言,我没有什么BT的需求在当前API下做不到的,google的设计ms还是很nice的。
但世界是残酷的,有的时候我们还是必须有机制提供消息的分发和处理的,因为有的工作是不能通过直接调用来同步处理的,同时也不能通过Activity中内 嵌的消息分发和接口设定来做到,比如说事件的定时触法,异步的循环事件的处理,高耗时的工作等等。在Android中,它提供了一些蛮有意思的方式来做这 件事情(不好意思,我见不多识不广,我没见过类似玩法,有见过的提个醒 && 嘴下超生^_^),它有一个android.os.Handler的类,这个类接受一个Looper参数,顾名思义,这是一个封装过的,表征消息循环的 类。默认情况下,Handler接受的是当前线程下的消息循环实例,也就是说一个消息循环可以被当前线程中的多个对象来分发, 来处理(在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理…)。在实例化一个 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线程里构造,这给内存管理的方法带来很大的变数…)。但有条规则肯定是不能破坏的,就是非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, String[] projection, String selection, String[] selectionArgs, String sortOrder)函数即可:
queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, sortBy);

可见,该类的使用是多么简单(其实现可不会很容易,因为我尝试做了一次造车轮的工作*_*),比直接用Handler简单无数倍。但让我倍感孤独的是,不 知道是没人做异步的ContentProvider访问,还是这个类使用太过于弱智(这个使用方法可是我摸索了半天的啊,难道我真的如此的弱@_@),抑 或是大家都各有高招,从SDK到网上,没有任何关于该类的有点用的说明。而我又恰巧悲伤的发现,这个类其实有很多的问题,比如他吃掉异常,有错误时只是简 单的返回null指针(这个其实不能怪他,你可以看看这里…);当你传一个null的ContentResolver进去的时候,没有任何异常,只是莫名其妙的丢弃所有消息,使你陷入苦苦的等待而不知其因;更愤慨的是,他的token传递竟然有Bug(难 道还是我使用不对&_&),从startXX传入的token,到了onXXComplete里面一律变成1,而文档上明明写着两个是一 个东西(我的解决方法是用cookie做token,这个不会丢*_*)。不过我暂时还没有遗弃它的打算,虽然没人理睬,虽然有一堆问题,虽然我按图索骥 造了个新轮子,但为了节省剩下的一些无聊的工作,我决定苟且偷生了。。。
还是习惯性跑题了,其实,我是想通过我对这个类的无数次Debugger跟进,说说它的多线程异步处理的解决策略的。他的基本策略如下:

1. 当你实例化一个AsyncQueryHandler类时(包括其子类…),它会单件构造一个线程(后面会详述…),这个线程里面会构建一个消息循环。
2. 获得该消息循环的指针,用它做参数实例化另一个Handler类,该类为内部类。至此,就有了两个线程,各自有一个Handler来处理消息。
3. 当调用onXXX的时候,在XXX函数内部会将请求封装成一个内部的参数类,将其作为消息的参数,将此消息发送至另一个线程。
4. 在该线程的Handler中,接受该消息,并分析传入的参数,用初始化时传入的ContentResolver进行XXX操作,并返回Cursor或其他返回值。
5. 构造一个消息,将上述返回值以及其他相关内容绑定在该消息上,发送回主线程。
6. 主线程默认的AsyncQueryHandler类的handleMessage方法(可自定义,但由于都是内部类,基本没有意义…)会分析该消息,并转发给对应的onXXXComplete方法。
7. 用户重写的onXXXComplete方法开始工作。

这就是它偷偷摸摸做过的事情,基本还是很好理解的。我唯一好奇的是它的线程管理方式,我猜测他是用的单件模式。 第一个AsyncQueryHandler的实例化会导致创建一个线程,从此该线程成为不死老处男,所有的ContentResolver相关的工作,都 由该线程统一完成。个人觉得这种解决方式很赞。本来这个线程的生命周期就很难估量,并且,当你有一个ContentProvider的请求的时候,判断你 会做更多的类似操作并不过分。就算错了,花费的也只是一个不死的线程(与进程同生死共存亡…),换来的却是简单的生命周期管理和无数次线程生死开销的 节约。同时另外一个很重要的问题,他并会涉及到单件中数据同步的问题,每个类都有各自的Handler类,彼此互不干扰,分发可以分别进行。当多个数据请 求的时候,在同一个ContentResolver上进行的可能微乎其微,这就避免了堵塞。总而言之,这套解决办法和Android的整体设计算是天作之 合了。
所以建议,如果你有什么非ContentProvider操作,却需要异步多线程执行的话,模拟一套,是个不错的策略,当然,具体情况具体分析,生搬硬套是学不好马列主义的。。。

Bookmark and Share

Study on Android【五】–自定义ContentProvider的语义

This item was filled under [ study on android ]

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, …}来维系(其实很好理解,我呆了…)。自定义的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=”wrap_content”,这会在onMeasure的时候抛出异常。

Bookmark and Share

Study on Android【四】–显示控件使用

This item was filled under [ study on android ]

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说很大,不到万不得已不 要使用。

Bookmark and Share

Study on Android【三】–Intent消息传递

This item was filled under [ study on android ]

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,或在配置文件中添加<receiver></receiver>项。这其实就相当于向系统的注册中心,注册了相关的Intent-filter和receiver(这个事情完全可以通过代码来做,只是这样就失去了修改的灵活性)。
当程序有一个消息希望发出去的时候,它需要将消息封装成一个Intent,并发送。这时候,应该是有一个统一的中心(恩,有可能Android底层实现的时候不是,但简单这样看是没问题的…)接受到这个消息,并对它进行解析、判定消息类型(这个步骤降低了耦合…),然后检查注册了相匹配的filter或receiver,并创建或唤醒接收者,将消息分发给它。这样做有很多好处。虽然这种传递有的时候不如点对点的传递快(这有些需要速度的地方,我们看到Android会通过直接通信来做),但有时候又因为它只经过一跳(姑且这么叫吧…),比复杂的流动又要更快。更重要的是,它耦合性低,在手机平台这种程序组件多变的条件下使用十分适合。并且它可以很容易实现消息的精确或模糊匹配,弹性很大。(我个人曾想在开发一个C++二次平台的时候引入这样的机制,但在C++中,建立一套完整的数据marshal机制不容易,相比之下,用java来做会简单很多…)
恩,废话说了很多,具体讲讲Android中Intent的使用。当你有一个消息需要传递,如果你明确知道你需要哪个Activity或者其他Class来响应的话,你可以指定这个类来接受该消息,这被称为显性发送。你需要将Intent的class属性设置成目标。这种情况很常见,比如startActivity的时候,会清楚当前Activity完了应该是哪个Activity,那就明确的发送这个消息。

但是,有的时候你并不确定你的消息是需要具体哪个类来执行,而只是知道接收者该符合哪些条件。比如你只需要有一个接收者能显示用户所选的数据,而不想制定某个具体的方法,这时候你就需要用到隐形发送(传统上,我们可能会考虑用多态,但显然这种方式更为灵活…)。在Android中,你可以为Intent指定一个action,表示你这个指令需要处理的事情。系统为我们定义了很多Action类型,这些类型使系统与我们通信的语言(比如在Activity里面加一个Main的filter,该activity就会做成该应用的入口点),当然你也可以用于你自己的应用之间的通信(同样当然,也可以自定义…)。强烈建议,在自己程序接收或发出一个系统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。在单播的情况下,即使有很多符合条件的接收者,也只要有一个出来处理这个消息就好(恩,个人看法,没找到确切条款或抉择的算法,本来想实验一下,没来得及…),这样的情况很容易理解,当你需要修改某个数据的时候,你肯定不会希望有十个编辑器轮流让你来处理。当广播不是这样,一个receiver没有办法阻止其他receiver进行对广播事件的处理。这种情况也很容易理解,比如时钟改变了,闹钟、备忘录等很多程序都需要分别进行处理。在自己的程序的使用中,应该分清楚区别,合理的使用。

Bookmark and Share

Study on Android【二】–ContentProvider数据模型概述

This item was filled under [ study on android ]

from: http://www.cnblogs.com/duguguiyu/archive/2007/11/25/972060.html

Android的数据(包括files, database等…)都是属于应用程序自身,其他程序无法直接进行操作。因此,为了使其他程序能够操作数据,在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格式返回一个字符串(==!没听 过的诡异格式…)唯一标识该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中的参数等操作。但我看来,这只是在使用上简化了 相关操作(不然就需要自己做人肉解析了…),但并没有改变类型判定的模式。你依然需要用switch…case…对uri的类型进行判断,并 进行相关后续的操作。从模式来看,这样无疑是具有强烈的坏味道,类似的switch…case…代码要出现N此,每次一个 ContentProvider做uri类型的增减都会需要遍历修改每一个switch…case…,当然,如果你使用模式(策略模式…)进 行改造对手机程序来说无疑是崩溃似的(类型膨胀,效率降低…),所以,只能是忍一忍了(恩,还好不会扩散到别的类中,维护性上不会有杀人性的麻 烦…)。

增删改查
ContentProvider 和所有数据源一样,向外提供增删改查操作接口,这些都是基于uri的指令。进行insert操作的时候,你需要传入一个uri和 ContentValues。uri的作用基本就限于指明增减条目的类型(从数据库层面来看就是table名),ContentValues是一个 key/value表的封装,提供方便的API进行插入数据类型和数据值的设置和获取。在数据库层面上来看,这应该是column name与value的对应。但为了屏蔽ContentProvider用户涉及到具体数据库的细节,在Android的示例中,用了一个小小的模式。它 为每一个表建一个基于BaseColumn类的派生类(其实完全可以不派生自BaseColumn,特别当你的表不基于默认的自动id做主键的时候),这 个类通常包括一个描述该表的ContentURI对象和形如 public static final TITLE = “title”这样的column到类数据的对应。从改变上角度来看,你可以修改column的名字而不需要更改用户上层代码,增加了灵活性。 insert方法如果成功会返回一个uri,该uri会在原有的uri基础上增加有一个row id。对于为什么使用row id而不是key id我想破了脑袋。到最后,我发现我傻了,因为ContentProvider不一定需要使用数据库,使用数据库对应的表也可以没有主键,只有row id,才能在任何底层介质下做索引标识。
但,基于row id在删除和修改操作是会造成一定的混乱。删除和修改操作类似。删除操作需要传入一个uri,一个where字串,一组where的参数(做条件判 定…),而修改操作会多一个ContentValues做更新值。着两个操作的uri都支持在末尾添加一个row id。于是混乱就出现了。当在where参数中指明了key id,而在uri中提供了row id,并且row id和key id所指函数不一致的时候,你听谁的?示例代码中的做法是完全无视row id(无语…),如此野蛮的方式我估计也只能在示例中出现,在实际中该如何用,恩,我也不知道。幸运的是,我看了下上层对 ContentProvider的删除操作,其实都不会直接进行,而是通过调用Cursor的delete方法进行,在这前提下,我想Cursor会处理 好这些东西吧。
最后一个操作是查询操作,可以想见,查询的参数是最多的,包括uri和一组条件参数。条件参数类型和标准的sql类似,包括 sort, projection 之类的。从这些参数到sql语句的生成,可以寻求QueryBuilder类的帮助,它提供了一组操作接口,简化了参数到sql的生成工作,哪怕你不懂 sql都完全没有问题(这话说的我自己都觉得有点悬…)。查询返回一个Cursor。Cursor是一个支持随机读写的指针,不仅如此,它还提供了方 便的删除和修改的API,是上层对ContentProvider进行操作一个重要对象,需要仔细掌握(Cursor还可以绑定到view上,直接送显, 并与用户进行交互,真是程序越往上,封装越好,工作越机械没有复杂性了…)。

数据模型
在 与界面打交道的Cursor、ContentResolver等数据操作层中,大量采用观察者模式建立数据层与显示层的联系。一个显示层的视图,可以做成 某一种观察者注册到Cursor或ContentResolver等数据中间层中,在实现底层ContentProvider中,我们需要特别注意在对数 据进行修改操作(包括增删改…)后,调用相应类型的notify函数,帮助表层对象进行刷新(还有一种刷新方式是从一个view发起的)。可以看到 Android的整体数据显示框架有点像MVC的方式(贫瘠了…叫不出名)。Cursor、ContentResolver相当于控制层,数据层和显 示层的交互通过控制层来掌管,而且控制层很稳定不需要特别定制,通常工作只在定制数据层和显示层空间,还是比较方便和清晰的。

一个设计问题
现 在有个设计问题,比如我要扩充一个已有的ContentProvider(第三方提供),我是建立一个ContentProvider,只保留第三方 ContentProvider的key信息,并为其添加更多的信息,在表层维护这两个ContentProvider的联系好;还是建议一个 ContentProvider,以第三方的ContentProvider做一部分底层数据源,像表层提供一个ContentProvider好。
前者无疑在实现上简单一些,如果第三方改变,灵活性也更好,只是需要仔细维护表层的相关代码。后者实现上需要付出大量的苦力劳动,当表层使用会简单多了。我举棋不定,期待你的意见。。。

Bookmark and Share

Study on Android【一】–概述

This item was filled under [ study on android ]

from:http://www.cnblogs.com/duguguiyu/archive/2007/11/17/962325.html

 

如果你还不知道google的重磅炸弹Android(中文意思是机器人…感觉google取名字的天赋全部花在google这个词上了…)是什么,你可以看一下这里。如果你觉得挺没有意思,再看一下这里。如果还觉得不好玩,那下面的东西就不需要看了。。。

对我来说,Android还是很有吸引力的,不然一个MS技术的忠实走狗也不至于一下就投入java的怀抱。至于为什么?恩,等我有八卦精神的时候再使劲的侃。

在这里还是谈正事的要紧。这几天看了下Android SDK,编了几个练习,获得了一点点经验。简单的罗列一下,比较重要的内容都添上链接,也是方便我和所有需要的人查看。

 

按google的说法Android包括一个操作系统,一些中间件和核心应用程序。操作系统是基于Linux的,上面的东西用了些开源的、google也花了不少精力开发了其他一些东东。底层用的是C++,但所有供应用程序开发的API都是java的(伪托管操作系统?^_^)。具体内容可以看一下这里 。基本上不会与你闭着眼睛幻想的有太大区别。

Android的GUI框架,你可以从你本身的编程经验中看到很多的影子(对我而言主要是.net winform && asp.net,但感觉上很多理念与WPF类似,只是我对WPF只是走马观花的了解了一些*_*,谈不上有任何经验…)。

首先,在Android中,每一个需要显示并运行的程序都需要有一个Activity 类的派生类,从某个程度上来说它有点类似于Page的概念。每一个Activity从直观上来看就是一屏幕的内容,当你切换了屏幕,基本上就意味着你切换了一个Activity。Activity负责管理界面上的各个显示控件,最重要的,是它提供了基本的生命周期管理的函数,包括OnCreate, OnResume, OnFreeze, OnPause等等。从名字上,就可以大致看出这些函数所负责的内容,但你一定要明白他们具体分工的区别,具体情况查看一下这里 。但与Page不同的是,当一个Activity被切换出去的时候(你随时可能在你未完成所需事情的时候离开一个Activity,因为你用的是手机,你要随时准备接电话,准备迎接GF,准备与悄悄从后面摸过来的老板据理力争),你会希望回来还看到一样的内容。因此,你对Activity的生命管理尤其的重要(特别是当你了解了Android的进程管理的时候…),你可能需要在各个周期点上负责保管状态、恢复状态、传送数据等工作。

当你从一个界面切换到另一个界面的时候,就涉及到了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(自定义控件…),它可以是简单的多view的特定布局组合,也可以是完成某种特殊功能。一般你会需要重载onDraw和onMeasure,具体可以看这里,规则还是有点小繁琐的。

但view的构造、layout的设定、样式的设定等等工作,通常不会使用显性的java代码进行编制,而是通过XML进行配置(WPF!!)。所有的资源也都是通过这种方式进行提供(查看这里)。而XML配置文件与代码的联系,是通过R类来进行的。R类是动态构造,它里面有一对的内嵌类,内嵌类里有一堆的静态int ID值。它是有系统自动根据配置文档的增删进行维护(in Eclipse…),完成从名字到ID的转换工作。而所有接受这种ID值的API,都会负责根据XML进行资源的配置。

Android的进程管理和资源管理都很有意思。通常,每一个应用程序(入口会是一个Activity的onCreate),都会占据一个进程。但这个进程是托管的!!你无法确定它何时会被回收,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收(查看这里 )。由此可以看到,维护一个Activity的生命周期是多么的重要,因为它随时会被系统干掉*_*。同时,每一个应用程序的数据都是独享的。就是你存在数据库、文件的数据别的程序无法访问(其实根本是无法获知)。要在应用间共享数据,比较好的一个策略是把自己做成contentProvider,其他应用可以通过提交特定格式URL申请你的数据×—×(Why URL?…)。

除了Activity,还有就是server。顾名思义,这就是幕后英雄的角色。他们不在屏幕上占据任何位置,只是在后台默默工作。与他们交互的方法比较传统,主要是监听一些事件。当然很多时候这需要权限,因此你需要了解一些具体内容。

每一个应用都会有一个Manifest.xml,提供全局的配置。包括设置权限,设置各个Activity的属性等等。维护这个配置文件是一项基本任务(当你添加了新的Activity的时候),因为好像插件不会帮你完成这件比较琐碎的事情。

 

本来还看了其他更多的内容。写累了,不写了。其他等有了更多经验再慢慢写吧。如果想学个入门的话,还是建议好好看SDK。Doc基本上是把你看成一无所知(实际上,我就是这样*_*),而源码里也是包含海量的注释(只是时不时就有几个词打错…),连我如此弱的人都感觉看得不错,可想而知这SDK做的还是非常好的。。。

Bookmark and Share
Page 1 of 212»