分类目录归档:程序生活

Program Life – Web

从新手到高手!一步到位!【Mac 操作指南 完全说明 】

在登陆系统之前需要了解Mac操作中的手势都有哪些

鼠标指针的变化:
①鼠标指针,日常移动;②I 型光标:进行文本的交互;③“风火轮”:表示当前‘忙’的状态;④不可行:不可完成当前的任务;⑤添加:直接拷贝/添加到指定处

依次表示“关闭窗口(不是退出)”   “最小化到Dock”   “最适合观看(不是最大化)”

    首先,先看到是桌面
底下的是Dock,一些快捷打开的程序或正在运行的程序会显示在上面
其中正在运行的程序下方会有小灯亮起(如果没有灯,可以在‘系统偏好设置’程序里的‘Dock’“显示已打开的应用程序指示灯”中勾选)
Mac不像Win那样,按住左上角关闭按钮就是退出程序,在Mac中‘关闭’的涵义只是关闭窗口,想要 退出程序 需要在菜单栏中或Dock右键“退出”程序
退出程序快捷键是⌘command+Q; 关闭窗口快捷键是⌘command+W; 最小化窗口快捷键是⌘command+M

点击此处 查看Apple官方 桌面 说明

Launchpad

如果某款程序不在 Dock 上,你也能在 Launchpad 中找到它,拇指或其它三指合拢可激活 Launchpad
在Launchpad中可以任意拖动程序,已达到自己想要的排列顺序,在App Store中安装的程序(APP)可在Launchpad中直接删除卸载
调整 Launchpad的背景可视化特效可按control+option+command+B

Mission Control

Mission Control 是可以让你了解所有打开的窗口,以便切换你需要的窗口
左上角是Dashboard ,里面有很多Widget小插件,比如天气、汇率、时钟等…
右上角是桌面缩略图,可以新建多个桌面或全屏打开的程序
可以四指或三指(根据自己设置)在各桌面或全屏程序中切换…
点击获取更多Widget小插件

想要关闭多余的桌面可按X关闭

  Dock
Dock,与win下的‘开始’的地位同等重要(但win8已经把它抛弃了~),可以自定顺序,把不常用的程序用鼠标单击不放拖到Dock以外的区域就可以让它在Dock中消失,当然 也可以把常用的程序拖到Dock里,以便捷打开。
Dock左端有不可移动的Finder和一些常用软件,中右段是正在运行的程序,右侧也有不可移动的废纸篓和‘堆栈’,那么什么是‘堆栈’呢?堆栈就是‘可以使用它快速访问常用的文件或文件夹’  补充:将项目拖到 Dock 上时,该项目的替身被放置到 Dock 中。原始项目没有被移动。

制作堆栈也十分简单,只需把文件夹拖到到Dock右端即可,比如 将‘应用程序’文件夹拖到dock上,就形成了堆栈,利用堆栈可以快捷访问里面的文件/程序(十分怀念雪豹里的自带堆栈)

更改堆栈里的视图大小也十分简单,按command+(加号)就是放大图标,按command-就是缩小图标

更改堆栈的显示效果可以‘右键’,可以按排列方式显示方式等查看

Finder

Finder 相当于windows下的‘我的电脑’ 资源管理器,文件和程序可以从Finder 中管理

‘系统’文件夹中就是系统文件(新手不要乱动哦);‘应用程序’就是本电脑的app程序所在文件夹;‘用户’文件夹顾名思义就是你个人的文件夹;‘资源库’是一些本机程序所需的运行文件和素材。拷贝(复制)的快捷键是command+c;粘贴 command+v;一些文字的剪贴是command+x
点击此处查看Apple官方Finder说明

选择多个项目时,除了用鼠标指针画一个选框 和全选的command+A之外,还有就是选择无序或散落的文件,在Mac中 选多个文件项目需要边按住command键鼠标指针边选择文件;而选择很多文件时只需选中第一个文件,按下shift键再点击顺序的最后一个文件,即 这个范围的文件项目全部选中

在Finder的标题栏里‘右键’选择‘自定工具栏…’,可以根据个人喜好或需要程度来自定 工具,当然 也可以把最常用的文件夹拖到工具栏里 达到快捷打开的目的…

‘前往文件夹…’功能可以仅凭地址 来打开文件夹,在前往复杂深邃的文件时相当有用,前往文件夹的快捷键 shift+command+G

在‘Finder’偏好设置中可以根据自己需求设定自己所需在边栏中显示的项目,推荐把‘外置磁盘’选项的对勾划上,因为 插硬盘的时候查看十分方便

当你要查看一个文件夹或app程序的‘属性’时,需要在‘文件’里选择‘显示简介’或者按下快捷键command+i便出来一个信息框,看要查看项目大小/修改日期/权限等
在这个信息框里 你可以更改这个项目的属性,比如更改图标  只需把icn图标文件直接拖到 信息框左上角的图标中,即可替换/更改图标,要还原按下delete即可还原原状
也可以更改使用权限,比如这个文件你只想读,不想写的话,在底部方框中 选择‘读或写’的要求,也可以设成不可访问的文件…

新建智能文件夹
新建智能文件夹,是可以根据用户自己所需量身打造‘文件夹’,这不是传统意义上的‘文件夹’里面没有实体的文件,只是把用户需要的变量和因素来查找符合条件的文件 在其中,当然 这里面可以实时删除文件的。里面有非常多的变量让用户选择,Mac会根据你的条件查找整机里符合的文件来分类,比如只有MP3格式的文件/今天创建的文件等…

当你运行的运行程序出现未响应的状况或卡死的状况时,按下‘退出’键也无法退出时,不妨试一下 option+command+esc 选择你要退出的程序,强制退出,十分管用~

在点击菜单栏之后,按不同的功能键会出现不同的效果,比如按shift键的时候,菜单中的‘强制退出…’就变成了‘强制退出当前的程序’;比如按option键的时候,菜单中的执行命令可立即执行,关机不再等待/确认,就可以立即关机,当然 还有很多奥秘

Dock中也是如此

废纸篓
废纸篓不用多说,和win下的回收站一样
想要清空废纸篓就可以右键废纸篓选择‘清倒废纸篓’,如果想‘倒’的干净点 在标题栏中的‘Finder’中选择‘安全清倒废纸篓…’,
陈冠希老师当年就没有选择安全清倒废纸篓~

关于废纸篓的小技巧:把移动硬盘或U盘或光盘等一些外部设备 拖到到废纸篓的时候,这时候废纸篓变成‘推出’的样子,这样就可以安全推出设备,是不是很方便?

预览
预览也是Mac中很强大但也很日常的软件,凭借预览,能轻松地阅读便携式文件格式文件(PDF)并打开常见图像文件……
查看和处理图像
适用于预览的手势
三指滑动:可以查看上一张图片或下一张
缩小放大:可以缩小放大查看图片
双指选择:可以以90°旋转图片,并可以保存

使用预览可以查看图像、编辑图像、将图像转换为另一种格式或以幻灯片显示照片。
点击查看Apple官方 预览 说明
如果想要缩小图片的尺寸,首先要选择你要打开的图片或文稿,多选或单选,双击文件 即可打开预览

在预览窗口里,可以调整图片

在左侧的图片的缩略图中按下⌘A,选择需要的调整大小的图片,在菜单栏中选择‘工具’—‘调整大小’

接着,会出来一个窗口,询问调整大小的数值,有具体尺寸,也有百分比调整,它会自动保存图片

     恢复文件
当我想要恢复原状怎么办??因为Mac中自带的一些软件在修改之后是自动保存的,没有询问是否保存的选项,那么即使修改错了也是可以恢复的
就以‘预览’为例子。不小心图片成这样了,怎么办?!!如果没有关闭预览 可以按command+z来撤销步骤

打开文件,默认是‘预览’程序,在菜单栏中选择‘文件’ —‘复原到’—“上次打开”或“浏览所有版本”

接着选择‘浏览所有版本’,神奇的一幕出现了,屏幕界面变成了在银河中穿梭,如同时光机里一样,可以查看这张图片之前的历史记录

找到你要回到目标文件的样子之后,点击‘恢复’  ,文件便回到初识状态,并自动保存上

这是“文本编辑”程序的‘时光机’,同样iWork套件也是有‘时光机’的

强大的搜索“善用搜索”
Mac中的Spotlight搜索也十分强悍,你几乎能用它搜到任何文件(系统文件除外),算术题它也会~
在Mac中搜索的快捷键是command+f,在不同的程序中 搜索会不同,比如在Safari中按下⌘f 会搜索当前网页的关键字…在Finder中就是搜索文件……

强悍的快速预览
在Mac中你可以不用打开文件即可快速查看文件,十分强大,只要合理文件都可以快速预览,只需选中项目 按下空格键即可 或者用三指单击项目文件也可以快速预览
快速预览支持的文件十分多,也支持第三方程序的扩展;用手势放大或点击右上方全屏功能即可全屏,甚至可以多选项目 按空格来 快速预览

万能的截图
在Mac中自带了 最‘完美’的截图功能:
全屏截图:按下Command+Shift+3 ,截取全屏图像将以PNG透明格式保存到桌面上。
区域截图:按下Command+Shift+4,鼠标变成十字准星,单击划出你想要的截图范围,自动保存到桌面上,想要取消截图按esc,想要移动选区按空格键即可
窗口截图:按下Command+Shift+4后,再按下空格键,这时鼠标变成’小相机’,点击想要的部件,就可以以PNG透明格式存在桌面上

懒得打字?动动嘴就行~
Mountain Lion中自带 听写功能,懒得打字?动动嘴就行!
只要在你需要键入/打字的地方,你都可以用说话的方式输入。听写功能可将你说的话 通过联网 转换成文本。
说出“逗号”或“感叹号”时,听写功能会为你加上标点‘,’‘!’。默认按键是按两下fn(在键盘左下角)即可唤出 听写功能。
设置在‘系统偏好设置’中的‘听写与语音’
  点击此处 查看Apple官方 听写 说明


音量/键盘灯/屏幕亮度 调整
关于调节屏幕亮度/键盘灯亮度/音量大小 我相信不用说
分享一个小技巧,就是微调,所谓微调就是以¼的量调整,按住Shift+Option+f1就是降暗,Shift+Option+f2就是缓亮,其它键盘灯和音量大小也可以组合Shift+Option来按
还有一个小技巧,就是在调节音量大小时候不发出“嘟嘟嘟”的声音,首先按shift不放,再按f11/f12,这样调节音量就是无声了,也可以组合上面的微调键

  快捷键

快捷键在Mac的操作中 有着举足轻重的地位,一些繁琐的操作 仅凭快捷键就可以完成
在菜单中,右侧的字符便是快捷键的方式

⌘  Command ‘花’键- 在部分 Apple 键盘上可能印有
⌃  Control
⌥  Option 键-“Alt”也可能会在此键上显示
⇧  Shift
⇪  Caps Lock 键- 切换大写字母锁定开或关
Fn  功能键;组合fx键
⏎ return -回车键/确定键
⌫ delete -删除;组合command+delete可删除文件

由于快捷键十分繁多,就不一一举例
详情 点击此处查看Apple快捷键 大全

系统编好设置
系统偏好设置与win下的控制面板功能相同,但Mac的控制面板逻辑性/归类方法要比win的控制面板简洁明了,新手上门也会很快。
首先打开‘系统偏好设置’,从中可以看到如何你想设置的一切,这个面板也可以扩展,后续会讲到…

首先先要根据个人情况设置触控板/鼠标

新上手的机子,肯定有不少人抱怨触控板默认下无法‘轻拍’,单击需要使劲按下“嘎嘣嘎嘣”十分不方便也十分心疼这样按
打开‘触控板’下面红框的就是‘轻拍来点按’把划上即可轻拍…

有些新手一直以为在Mac中没有右键的说法,其实右键是有的,但唤出方式与Win不同,Mac下的右键需要双指点按,当然  如果习惯了win   也可以设置成右键的方式
下拉选框,选择你习惯的方式即可……其他手势功能和鼠标手势 根据自己习惯自己设置,百变不离其踪,设置 十分方便

双击标题即可最小化
在win下 双击标题即可最小化,这是十分方便的一向功能,Mac中也可以设置~
首先打开‘系统偏好设置’,找到‘Dock’项目,‘连按窗口的标题栏以将窗口最小化’√划上

⬆另外,在这里用户可以调节Dock的大小、Dock的自动隐藏,最小化缩到图标里…或者缩放的动画效果,还有之前提到的“显示已打开的程序的指示灯”也是在这里设置

另外,再向大家推荐一个功能—触发角,触发角就是可以根据鼠标指针接触屏幕四角而达成一些快捷功能
比如,当鼠标指针滑到屏幕左上角时 活动窗口滑向四边,显示桌面;当鼠标指针滑到左下角的时候  唤醒Mission Control  以切换窗口,指针滑到右下角 屏幕熄灭但机器运行…
这一切都要在‘Mission Control ’中设置,左下角找到‘触发角…’

四角用户根据自己习惯自定,如果不习惯或感觉麻烦也可以空着不设置

如果在设置过程中按下⌘⌥⌃等 功能键,那么在触发四角的时候也要搭配 功能键使用,这样可以防止误触到四角


部分 有锋友抱怨 不知为什么在登陆界面莫名多了一个“客人账户”,那么改如何删除呢?
首先‘系统偏好设置’,找到‘用户与群组’,左侧候选栏里选中‘客人账户’,再单击左下角小锁 输入用户设定的密码解锁 权限 ,如果没有密码 直接空着不填点‘确定’
在“允许客人登陆到这台电脑”的选项中把取消即可关闭‘客人账号’,需要的时候可以再开启…

这个是‘登陆选项’用户可以设定 登陆时的选项,不如是直接登陆用户账户还是显示登陆界面后在登陆用户等,根据个人需要设定吧…

或者,有些程序莫名的随机启动,和win下‘启动’菜单一个道理,自己可以设定哪些程序可以自动随机启动(按下方+号),哪些不要随机启动(下方-号)
点击‘当前用户’选择‘登陆项’中 你可以看到哪些程序是随机开启启动的…自己设定

安全性与隐私’这是决定你mac安全性的一扇大门,在安全与隐私中的‘通用’里用户可以设定/修改 用户登陆密码
“我 从其他网站下的软件为什么不能安装呢?”从‘安全性与隐私’中可以设定,设定你允许的应用程序的来源,app应用程序一般可划分为‘随机自带程 序’‘App Store中下载的程序’‘从其他网上上下载的程序’。一般Mac默认的是‘App Store和被认可的开发者’ 这类软件通常为收费或必备软件。当然 我们要设定成‘任何来源’,这样从网站下的软件就可以成功安装上了。

安全性与隐私’的‘隐私’中,是可以设定你允许程序访问的内容,就如同iPhone设置中隐私,可以设定‘定位’‘访问通讯录’(用量与诊断是Mac向Apple不定期的发送你机子使用 情况与问题,如果你比较反感这个 可以把对勾取消,不发送)

另一个十分常用的功能就是—让Mac成为WIFI热点
如果用的是有线网络,不是无线网络,那么可以让你的Mac成为WIFI热点,把有线网络形成WIFI的形成发散出去,供 手机或一些设备利用电脑的网络上网
打开‘系统偏好设置’—找到“共享”,在左侧选择选择你要‘共享’的内容,之后在右侧选择你要‘共享’的方式,如下图所示,就可以让你的Mac成为WIFI热点

“共享”还有很多功能,WIFI热点只是一个典型例子,其他 共享 也很精彩~自己尝试一下。
关于系统偏好设置先讲到这里,其它功能大家可以自己体验体验

蓝牙文件交换
这个程序是非常好用的!当手头上没有数据线,要想给手机传图片/歌曲/文件 就可以用‘蓝牙文件交换’这个程序搞定!
(注意!有些手机是不支持的!主要以智能手机为主,不支持iPhone)
首先在“应用程序”—“实用工具”中找到“蓝牙文件交换”这个程序
传输文件的方式有两种
先说第一种,是类似发送信息的方式把文件发送出去(类似与手机与手机直接传歌);
①首先打开程序会出来文件选择窗口,选择你要传输的文件

②找到手机,点击后 会出现配对设置,在手机中输入电脑出现的配对码 即可配对,之后再传输就不用再配对了

③手机支持!这样就可以传输文件了,手机会以信息的提示 收到文件

另一种是直接访问手机的文件管理器  可以直接把文件放到手机需要的目录下即可
①点击选择‘文件’—‘浏览设备…’

②与上面的②相同,需要手机配对

③出来一个窗口,这样就可以访问手机里的储存空间,可以把需要的文件拖到想要的目录下

字典
‘字典’这个应用程序虽然不起眼,但内容十分强大
这个就是‘字典’程序,command+(逗号)即可唤出当前程序的偏好设置,选择你所需要的词库~(Mac自带的词库非常少,下面部分我会补充词库)


字典’这个程序在浏览网页时非常方便,当有不认识的单词或不明白的术语,都可以 “用三个手指轻按(在系统偏好设置中设置)” 可唤出字典功能


扩充自带的词库!
  首先,引用我之前教大家的“前往文件夹…”的功能
打开 Finder,在 Mac 屏幕顶部菜单栏选择 “前往” — “前往文件夹”。在弹出窗口里粘入下面这个路径 /Library/Dictionaries

然后就转到Mac系统资源库的‘字典文件夹’,把字典包拖进去就行了(如果弹出个警告框,点击 “鉴定”,然后输入密码就行)
扩展后再打开‘字典’程序,⌘,偏好设置中√你需要的字典即可

以下是几个常用的扩展词库

点击下载 115网盘 英-汉字典词库
点击下载 115网盘 汉-英字典词库
点击查看 扩展更多词库

   Safari
Safari是Mac中自带的网页浏览器,通过 iCloud 令你的 Mac、iPad、iPhone 协作得更有默契
Safari 是第一个支持 HTML5音频和视频标签的浏览器和第一个支持 CSS3 动画的浏览器。
首先,也是了解一下在Safari中常用的手势都有哪些
①双指轻扫,用于网页中的后退/前进 ②双指缩小,在多标签中转换标签 ③双指扩大,放大查看网页


点击查看Apple官方Safari说明

top sites功能是Mac Safari独有的一项功能,它能都打开网页开始,方便查看一些常用网页,还会提示有哪些网页已经更新

我打开Safari为什么没有发现top sites?
首先在使用Safari之前,需要设置一下你需要的功能,打开Safari的偏好设置⌘(逗号),会出来Safari的偏好设置,从中可以设置任何你需要的一切
‘Safari的打开方式’就是你启动Safari第一眼所看到的是什么,根据个人设置,可以是某个网页,可以使书签,也可以是top sites

偏好设置中的功能
通用:设置基本用户操作方式,包括主页,历史记录,下载目标文件等…
书签:书签功能 能设置在顶部书签栏中要显示的项目,以及联系人的个人主页等
标签页:标签页用于 当你点击某个连接时 标签页显示的状态
自动填充:自动填充Web表单,比如在填表的时候,只需之前设置你的个人信息,它会记住 自动当你填充
密码:这个功能很强大但也很脆弱!它能记住你邮箱/微博/论坛等的用户名和密码,帮助你下次不用重复繁琐的输入密码。但是!它能查看你的密码,所以在把电脑借给朋友的时候 一定要设置一下用户密码,不然 你邮箱/微博等用户名和密码 一览无余 全部都知道
安全性:网页安全,总之打开为好
隐私:里面存储的cookie和一些网站的数据,与win下的道理相似
通知:用于网站消息的通知,比如微博/邮件受到新消息 它会提醒你,但目前我一条还没有受到= =,比较鸡肋
扩展:功能强大!能够扩展Safari的功能,比如下载器的联动插件,Google翻译等,还有一个很强大的屏蔽视频网站广告的插件 下面讲到
高级:所谓的高级 其实就是其它的补充内容,在中可以可以设置字体,编码等

有一个技巧,就是不用Flash插件 用HTML5观看视频,如同iPhone和iPad那样,发热量小
在‘高级’中的‘在显示栏里显示‘开发’菜单’

这样,再打开视频网址的时候选择‘用.户.代.理.’就可以显示的是移动版的网页 和iOS上观看的一样,用完之后关闭 或 选回‘默认(自动选取)’

默认搜索引擎  就根据各位的习惯和所在地域设置吧,需要搜索的时候 直接在地址栏里打入关键字即可搜索

收藏网址
只需把地址栏中的地址 拖拽到下面的收藏栏里即可,或者也可以按照紫色箭头拖到top sites中显示。

下载太慢?
不如把下载地址拷贝了,到下载器中去下载,找到项目右键’拷贝地址’再到下载程序中新建项目即可

其它Safari神奇的扩展功能
点击 查看 谷歌翻译/视频下载 扩展部件下 载
点击 查看 OpenGG 视频网址屏蔽广告 说明
点击 Adobe官方 Flash播放器 下载

下载 app应用程序
下载来说目前就有两个渠道,一个是从 App Store里下载,里面的软件都是需要购买的(俗称 正版),当然比如QQ、PPS、迅雷等常用软件都是免费的,
需要Apple ID来购买,和iTunes里的Store是一样的,账户可以共用,如果经济条件允许的话 我们还是推荐在App Store里安装程序
在Store里,按下‘安装’,程序就会自动的安装到Mac上,不用安装包,一切都是自动的,它也会更新已安装的软件,卸载程序也非常简单,直接把程序图标拖到废纸篓里就是删除程序⌘⌫

我着重讲另一种渠道,因为这种渠道是最常用的,不为别的,就为它基本是免费的。
在威锋上就可以下载Mac软件,都是免费的,大部分也是破解版的,就体验上来说与‘正版’一样,只不过初期安装 要费脑筋(是因为在Store里安软件太白痴了,用多了人会变傻~)
1.Wefiler网盘上下载软件,但是需要邀请码,邀请码在235点我 直达235楼
2.Mac综合区或软件游戏分享区里会有帖子分享 程序
3.从其他网站上下载,比如MacX、MacApp等网站,度娘一下,你就知道

我从网站上下完了程序,该怎么安装呢?
下载完后,在‘下载’文件夹中可以看到你下载的安装包,安装包大致分为两类,一个是dmg格式,一个是pkg格式,没有win的exe文件
dmg是压缩镜像文件,相当于在Win上常见的iso文件;pkg格式属于系统级软件的安装程序,目前以dmg格式居多


dmg
首先是dmg安装文件,双击打开文件会出现一个窗口,程序就在里面,安装方法也比较简单,就是直接把程序图标拖到‘应用程序’文件夹里就行了(尽量都放在应用程序文件夹里)
相当于拷贝/解压的过程,拷贝完之后  就安装完毕了~是不是很简单

另外,在安装完毕后,记得推出 dmg安装包,之后这个安装包就没什么作用了,可以删除了⌘⌫(也可以留着 供下次或给朋友安装…)

新手可能疑问了,就这样复制到文件夹里就是安装程序?
是的,因为Mac使用的是linux的文件分区格式和存储方式,运行文件都包含在‘程序’包里,没有win所谓的程序文件和快捷方式启动,mac一般不存在文件碎片和磁盘整理的问题

如果要查看app程序 里的程序文件夹,选择程序 右键‘显示包内容’,里面就是这个程序所需的运行文件,全部包含在里面,是一个整体!因此要删除程序的话只需拖到废纸篓
  

pkg
接下来是pkg安装包,与dmg不同,pkg需要’安装器‘这个程序安装,一般pkg程序比较大型。安装方式和win差不多,按照一步一步的顺序就能安装完毕了

pkg安装后的程序想要卸载,需要卸载器或卸载程序 来卸载,因为在’资源库‘里也会有文件,故 直接拖到废纸篓里是删除不干净的

iTunes
自它诞生之日起 就背负着‘复兴苹果’的伟大 重任,如今经过10代的洗礼
用iTunes的用户不用多说,再熟悉不过了,这里我不着重讲解怎么操作,喜欢iTunes的人 恨不得抱着电脑,恨iTunes的人恨不得砸电脑
点击查看具体Apple官方iTunes说明
这是iTunes11,与之前的iTunes有了很大的改观,风格变得清淡,与iPhone5传达的感觉 一样,但取消了cover flow模式 很多人不爽(包括我)
如果不习惯iTunes11没有左侧边栏 是可以打开的,在菜单栏里找到“显示”—‘显示边栏’即可,快捷键是command+option+s,剩下的一切与之前 无异

这里 告诉一下我使用iTunes后的心得,打开‘偏好设置’⌘(逗号),在iTunes中也分成各个项目来设置,但有些在天.朝是无法使用的……
在通用设置里,是可以勾选你需要显示的项目。视图 就是显示窗口的效果,‘插入CD时…’这个后面会讲到


有些用户在使用过一段iTunes之后 发现电脑的容量急剧缩小,可能有人知道为何如此,就是因为iTunes的一个‘贴心’设计
我和大多数用户都喜欢和习惯把‘音乐‘放在一个文件夹里,建一个音乐库,这个’文件夹‘都是音乐文件,而在iTunes的世界中有一个叫做‘iTunes Media’的文件夹
‘iTunes Media’文件夹的主要任务就是把用户拖入的媒体文件(音乐/视频)拷贝一份到iTunes里,理论上 是直接可以把拖完的音乐文件删除的
但我们大家的习惯都是自己‘手动’的建一个‘音乐库’(文件夹)。所以,这就造成了同一个歌曲在电脑里有两份,iTunes Media文件夹一份,我们自己建的音乐库一份
这就造成了电脑的容量 减少/下降,当然,是可以关闭 拷贝iTunes Media文件夹 这个功能的。
在偏好设置中找到‘高级’下的“将添加到资料库时将文件拷贝到itunes media文件夹”这一项的√去掉。

iTunes‘导入设置’ 是可以把CD里的歌曲转换格式拷贝到Mac上,‘导入设置’就是设置CD转换成的格式;需要翻刻的时候只需选中你要翻刻的项目,右键 “创建XXX版本…”即可
CD中的数字音乐比特率约为1410kbps (简单来说数字越大 音质越好) ,一个3分钟的音乐 大约30MB
AAC编码格式16~320kbps :AAC相对于mp3,AAC格式的音质更佳,文件更小 ,在iTunes音乐商店下载的歌曲一般为 256Kbps AAC ,一个3分钟的音乐 大约6MB
AIFF编码格式:与CD的编码率相同,主要适用于电子音响设备,大小有CD音源决定
Apple Lossless:与CD的编码率相同,苹果研发的无损音频压缩编码格式,在苹果设备中听高音质音乐 Apple Lossless最为合适
Mp3编码格式64~320kbps:大众最熟悉不过的格式,就是因为使用的人多,才让它保持生命,一个3分钟的音乐 大约8MB
WAV编码格式:目前公认最好的音频格式  最接近CD的音质,虽然苹果设备是支持WAV格式的,但不支持歌词/插图,所以在苹果上编辑不如Apple Lossless完整

在Dock中显示iTunes播放专辑封面
这是一个小插件,可以让Dock中的iTunes图标显示成正在播放专辑的封面
点击此处查看/下载 插件

Remote
Remote是可以使iOS设备当做Mac的‘遥控器’来使用,首先是在iPhone或iPad中安装
点击此处查看Apple官方Remote说明
点击下载iOS设备Remote的app

在iOS设备上安装Remote完毕后 ,在iTunes中输入 iOS屏幕显示的适配码即可配对(同一个局域网内)

操作方式如同iOS自带音乐播放器一样,只是声音是从Mac上播放的…躺在床上也可以换歌~

Quick Time
Quick Time是Mac中的视频播放器,但由于它内置编码很少,一些电影不支持播放  我们用第三方的播放软件,所以Quick Time的亮点不在于‘播放电影’而是录制/剪辑
使用Quick Time录制‘影片(电脑摄像头录制)’ ‘录音’‘屏幕录制’

影片录制,首先,点击上方菜单栏中的‘文件’-‘新建影片录制’,出来一个窗口,随之摄像头便开启


录制完后,它会储存在Mac上,如果喜欢也可以分享到优酷/土豆/邮件/信息上

音频录制,也是点击上方菜单栏中的‘文件’-‘新建音频录制’,出来一个窗口,电脑内置的麦克风会开启,也可以选择外置麦克风

屏幕录制,点击上方菜单栏中的‘文件’-‘新建屏幕录制’,屏幕录制就是 可以录制整个屏幕的操作,一些视频电脑教程就是这样录制的

修剪视频,如果喜欢一个电影片段而不像保留整个,那么可以使用剪辑,把需要的部分保留下来,点击菜单栏‘编辑’—‘修剪’,快捷键是⌘T

接着,拖动两端的黄色选框边缘,选框内即是需要保留的片段,按下‘修剪’,黄框之外的片段便被剪掉

修剪音频,有一首歌,想制作成铃声,但时间太长怎么办?也可以使用Qiuck Time中的修剪功能
先把要修剪的歌曲拖到Qiuck Time中播放,点击菜单栏‘编辑’—‘修剪’,快捷键是⌘T
拖动两端的黄色选框边缘,选框内即是需要保留的音频,按下‘修剪’,黄框之外的音频便被剪掉

iCloud
iCloud 不仅可存储你的内容,还可让你在所有设备上访问你的照片、日历、通讯录、文档以及更多内容。十分方便,在Mac下编辑好的通讯录、备忘录、日历等信息会通 过iCloud自动同步到iOS设备上,同时 在iOS设备上 照的照片以及修改的文稿也会通过iCloud回传到Mac上…

点击查看Apple官方iCloud说明     点击访问iCloud
首先需要开启iCloud账号,iCloud账户有两种,一种是有iCloud邮箱账户,这个需要重新注册以@me@iCloud结尾的账户;另一种就是普通邮箱也可以注册的iCloud账号,但是‘邮件’这个功能是无法使用的,需要单独在“邮件”程序中单独设置

在”系统偏好设置”中点击 iCloud,输入你的 Apple ID,然后选择要启用的服务
邮件:此功能需要iCloud邮箱开启
通讯录:可以与iOS上的通讯录同步,或在iCloud上备份
日历与提醒事项:在日历中添加的任务可自动同步到iOS设备上,提醒事项也是如此
Safari:同步Safari中的标签页 以及在iOS上浏览过的网页
照片流:简单来说就是在iPhone上照张照片,立即会在Mac的iPhoto中出现~~借给朋友时 应该把此项功能关闭
文稿与数据:iWork办公套件,在iPhone上修改文稿的时候 会自动同步到Mac上,还有游戏存档~~
回到我的Mac:简单意思就是远程访问,复杂的来说 我也没有用过……
查找我的Mac:与查找我的iPhone一样,丢了 被偷了可以找回来(除非那贼太笨或压根就是个苹果白痴…个人建议在‘关闭’这个功能的时候也要输入账户密码)


日历
日历就不用多说了,但我想说的是教大家 添加农历日历(还有很多比如天气/节日等)
首先,打开‘日历’在‘文件’中选择‘新建日历订阅…⌥⌘S’,订阅日历就是 引用一些大家在网上分享的日历任务,

之后,输入订阅地址(订阅地址下面提到)

订阅之后,日历会添加农历,注意:在‘显示简介’要‘移除’‘提醒’和‘附件’,不然每天都会提醒你一遍,即使Mac上不烦在iPhone上也会烦的

之后就完成了!点击可查看每天的‘任务’

想要删除也十分简单,在左侧边栏中找到想移除的‘日历’,右键‘删除’即可…

订阅日历
2013年农历:

  1. https://www.google.com/calendar/ical/jhkliqpl%40126.com/public/basic.ics


2012、2013农历+星期+节日:

  1. http://www.google.com/calendar/ical/mnmnscg3edii9e97dvbphoreh0%40group.calendar.google.com/private-2125576945eac72a7efa790e43a83a71/basic.ics


2013节日星期农历黄历:

  1. https://www.google.com/calendar/ical/anjg3tsnm6aanh4tj8db3f42j4%40group.calendar.google.com/public/basic.ics

Time Machine
Time Machine是可以与 Mac 和外置硬盘或 Time Capsule 配合使用来备份 整个Mac的文件,包括系统文件、应用软件、帐户、偏好设置、电子邮件、音乐、照片、影片和文稿
而 Time Machine 与其他备份应用软件的区别在于它不仅能备份所有文件,还能够记住系统在任意一天的显示状态,因此可以重新访问 Mac 在过去某个时段的显示状态(像时光机器一样)。Time Machine 会保留过去 24 小时的每小时备份、过去一个月的每日备份及每周备份,直到备份硬盘撑死为止。

点击查看Apple官方Time Machine说明
备份硬盘大致有三种选择
   外置硬盘:品牌无所谓,后期需要把硬盘格式转成“mac os x扩展日志式 ”
Time Capsule:苹果自家的无线硬盘/路由器,目前有2TB和3TB版本,价格略高
硬盘分区:这个方法有种脱裤子放屁的味道~给喜欢折腾的用户吧

首先,在拿到新电脑的时候,右上角会有个类似时间的图标,这个就是Time Machine 标志,点击‘打开Time Machine 偏好设置…’即可开始设置Time Machine
从中可是设置 备份周期,需要备份的文件等,初次备份的时候因为要备份整台电脑的文件,大概需要一个通宵的时间来备份,之后每天/每周/每月的备份所需时间就少了

把要用于Time Machine 备份的移动硬盘插入电脑(最后专门准备个 用于Time Machine 备份的硬盘),用于手头没有Time Capsule,就拿移动硬盘了~~

如果不想在右上角的菜单栏里显示这个图标,在偏好设置中下部的“在菜单栏中显示Time Machine ”的选项√划掉即可

具体操作说明 看Apple官方出的视频教程,我就不在这里班门弄斧了
具体 点击查看 Apple官方录制的Time Machine教程 (讲的比较清晰)

分享功能
分享是Mountain Lion 中新添加的功能,在Mac上总是能找到”分享“按钮的
你可以通过 Mail、信息及 AirDrop 分享照片、视频及其他文件,甚至还可以从 Safari 上发送链接。只需点击几下,即可直接将内容发布到新浪微博、优酷、土豆上。

首先,这一切都是需要设置的,打开‘系统偏好设置’中的“邮件、通讯录、日历”面板,从中你可以设置 土豆/优酷/新浪微博/和一些上不去的网站

例如,在‘预览’程序中 要分享图片至新浪微博上,可以点击 分享 按钮,并分享至‘新浪微博’即可

输入上你要说的话,即可‘发送’~也可以添加‘定位’信息

也可以通过‘信息’的方式发到好友的手机上(苹果设备),一切都是免费的

设置‘信息’ iMessage,需要打开‘信息’程序,找到偏好设置,这个账户要和你iPhone上的账户一致

使用 iMessage 发信息,可以向任何运行 iOS 5/6的 iPhone、iPad 或 iPod touch 用户发送信息。信息会在你的 Mac 及你使用的任何设备上显示,就可以在 Mac 上开始对话,然后无论走到哪里都能在 iPhone 或 iPad 上继续进行。你还可以发送照片、视频、文档和通讯录,甚至发送群组消息。

分享视频到优酷/土豆
首先,在你要分享的视频(一般为mp4格式)右键,找到‘共享’,优酷或者土豆,即可分享到视频网站上


通知中心
新消息总会在 Mac 的某处即时弹出,如电子邮件、信息、软件更新或日历提醒等,通知中心会让你轻松掌握所有情况
通知横幅总会在你桌面上的同一位置出现,然后迅速消失,只要从右向左轻扫触控板,所有通知便会在通知中心里

唤出通知中心十分简单,只需双指从触摸板外向左滑即可,或 在菜单栏右上角 “

如果要设置一些项目程序的通知方式,可以在‘系统偏好设置’中的‘通知’设置
从中可以设置一切的提醒方式
:即不提醒通知
横幅:提醒用户,变回向右滑动消失
提示:可以从中操作通知选项

用户甚至可以在通知中心发布‘新浪微博’,只需把相应的‘在通知中心显示分享按钮’即可发布

系统信息
当我们买了一台新的Mac后,通过‘系统信息’可以来查看当前电脑的信息,以及硬件配置
在系统信息中可以查看Mac中所有的信息,系统、内存、显示器、储存、内存、显卡、电池等等…
新买Mac,首先,在菜单栏中点击“”,‘关于本机’,这里显示的是大致信息,以防您买错型号,点击‘更多信息’可以查看 硬件/显示器/存储/内存/保修状况…

弹出一个窗口,选择你要查看的内容,有处理器,内存,显卡,序列号等基本信息。单击‘系统报告…’可启动‘系统信息’程序

选择‘内存’可查看基本内存信息以及插槽数量,用户可自己拆机升级内存(Macbook Pro),更换内存是不影响保修的,这大家不用担心
点击“内存升级说明”可查看Apple官方制作的拆机说明,内容详细。主要选中内存的时候尽量选择同一型号/品牌/大小的,最好成双成对的选择

服务’是可以查询Apple对用户的服务范围,包括保修期限,保修状态。不用 死记硬背几下 序列号 再输入查询,直接点击 即可转到Apple官网 查询

再让我们看看‘系统信息’这个程序,这个程序比‘关于本机’要强大和详细,这个相当于win下的 设备管理器
左边是项目栏,可以选择需要查看的目录,右边则是详细信息,界面和查看方式要比win简洁明了

如何确保我的Mac是全新的呢?除了包装和激活系统
查看‘电源’也是个很好的方法,此方法适用MacBook,这里能查看Mac电池的使用状况,包括容量、实际容量、电池循环(在下面讲解电池)
电池循环通俗讲就是电池使用次数,也间接的表明了这台电脑的使用情况,一般刚拆封的MacBook 循环计数为0或1

    关于电池—锂聚合物电池

目前,可充电锂聚合物电池为你的Mac笔记本电脑、iPod 或 iPhone提供动力
锂离子聚合物电池的功率密度更高。一块电池即可提供很长的使用时间。可以随时为锂离子聚合物电池充电,而无需进行完全的充放电。也就是说新买的Mac没必要用到完全没电的时候再充电(这样反而损坏锂电池),或一次性充电十几个小时,总之 充满就好
正确的用法就是能充就充,尽量插着电源使用, 因为Mac在电量剩余95%以上的时候 是不向电池充电的,也就是说插着电源用实际上是在使用的电源电,不是电池里的电。所以就会看到 即使插着电源,菜单栏里的电池项目会显示>95%的数字,当低于95% 电池才会充电,充到100%,第二天打开电脑看剩余电量为99%而不充电,这是正常的!但 至少每月为电池充电、放电一次

充电周期与电池循环
大多数锂离子聚合物电池均采用一种快速充电方式,可迅速为你的设备充满 80% 的电量,然后再转换为连续补充式充电方式继续充电。
在Mac上,电锂电池的充电/放电次数是有限制的,可以实现多达1000次完全充电和放电循环,在‘系统信息’程序 中可查看当前循环次数
关 于电池循环的解释:一次充电循环意味着用完电池的全部电量,但不一定意味着进行一次充电。例如,某天您可能使用笔记本电脑一个小时或更长时间,用完一半电 量后即重新充满。如果第二天仍是如此,则可计为一次(而不是两次)充电循环,因此,一次充电循环是将之前用过的电量做加法合 计算的。

注意:请避免在夏天将Mac 锁在高温的车内或汽车后备箱中
10° 到 35° C 是运行电脑和锂电池的适宜温度
-25° 到 45° C 是存放笔记本电脑的适宜温度

电池是个损耗商品,无论怎样呵护与保养,它都是有寿命的,提醒各位要理性对待,不要让电池健康度与循环次数影响了用户使用电脑的体验,‘电池’这都是可以更换的!

光盘刻录
在Mac中无论是音乐光盘还是数据光盘 甚至是镜像光盘,这些全部都能搞定!
我分别讲解这几种光盘是怎么刻录的,不需要第三方软件,在Mac自带的程序中即可!
首先是先让大家了解一下常见的光盘分为哪几种,刻录的基本小常识

CD-R          容量700M 或80分钟音频/视频    不可重复擦写     容量小,刻录速度快,耗时短
CD-RW       容量700M 或80分钟音频/视频  可重复擦写
DVD±R       容量4.7G  或120分钟音频/视频  不可重复擦写    容量是CD的6倍,多用于数据备份
DVD±RW    容量4.7G  或120分钟音频/视频   可重复擦写
DVD-RAM   容量4.7G  或120分钟音频/视频  可重复擦写    比DVD±RW使用更方便
DVD±R DL  容量8.5G  或240分钟音频/视频  不可重复擦写    单面双层DVD,是普通DVD的2倍容量
BD蓝光       容量25G   或130分钟音频/视频  不可重复擦写    超大容量但Mac不可刻录

再来看看刻录的类型有哪些
数据光盘:顾名思义就是可以刻录文件,与U盘的方式差不多,受光盘容量限制,使用Finder刻录
音乐光盘:就是CD,可以在播放机中播放的光盘,受刻录时间限制,使用iTunes刻录
视频光盘:就是DVD,可在播放机中播放,受刻录时间限制,使用iDVD刻录
镜像光盘:系统光盘/安装光盘,ISO镜像文件,受光盘容量限制,使用‘磁盘工具’刻录

    数据光盘
当我们插入光盘的时候,会出现一个窗口,这个窗口问你要用什么程序打开,这无形中的意思就是问你要刻录什么类型的光盘

接着打开Finder,在左边栏里 出现了‘光盘’这个文件夹,如同U盘一样,这样就可以把需要刻录的文件拖进去就行了
大小限制是根据你用的是什么光盘,VCD就700MB,DVD达到4.7GB
拖进去的文件会以‘替身’的方式显现,当选择好文件之后,按下‘小辐射’图标或右上角的‘刻录’即可刻录光盘!

    音乐光盘
刻录音乐光盘 可以在汽车内的CD中播放
在插入光盘后显示的窗口中 选择在iTunes中打开光盘

打开iTunes,从歌曲曲目库中找到你想刻录的歌曲。点击上方菜单栏的‘文件’-‘新项目’-‘播放列表’快捷键是command+n
再把你之前选中的歌曲,拖到这个新建的播放列表里,可以给这个新播放列表重命名,然后选中这个播放列表‘右键’选择‘将播放列表刻录到光盘’

在选择完之后,会弹出一个窗口,这个窗口是设置刻录光盘的基本信息
选择‘音乐光盘’就是刻录CD,注意:音乐光盘的限制是VCD光盘80分钟,DVD光盘120分钟,也就是说 播放列表中的歌曲时间累加在一起 要在这个时间之内
如果选择‘数据CD或DVD光盘’,这个效果和在Finder里刻录的数据光盘是一样的,数据光盘的限制是VCD光盘700MB,DVD光盘4.7GB,也就是播放列表中歌曲大小累加一起要在这个容量之内,不过一些 播放机和汽车音响是识别数据光盘播放的

     视频光盘
打开iDVD这个程序(我觉得没什么用 给删了= =)
刻录DVD大致的方法就是,首先确定你要刻录的视频,或者从iMovie中制作的电子相册
新建一个项目,里面有一些模版,就是DVD播放的开始界面和选集目录,挑选一个你喜欢的
把项目视频直接拖进模版里,然后就可以刻录DVD了

     镜像光盘
接下来 着重讲一讲刻录镜像光盘,镜像光盘在日常生活中十分常用,比如系统安装光盘,软件光盘等,都是iso镜像光盘
在目前的Mac中已经取消了系统光盘,但可以DIY刻录一张,以备不时之需,刻录系统需要DVD光盘
这是一个从OS X10.8中提取的镜像文件

在‘实用工具’中打开‘磁盘工具’,点击刻录 出来一个窗口,选择你准备好的镜像文件,点击‘刻录’

接着就是刻录设置了,基本上不用更改,点击刻录……

N分钟后 热乎乎的系统光盘便出炉了,是不是很简单?

磁盘工具
磁盘工具是Mac中最为重要的系统工具之一,一切硬盘上的问题可以由它解决
当电脑不好用的时候,一些程序文件出现错误的时候,可以尝试尝试“磁盘修复权限”
在Mac中,文件是有权限的,为了保证用户不会篡改重要的文件而影响系统,所以‘修复磁盘权限’就是修文件的权限
打开‘实用工具’中的‘磁盘工具’,左侧是项目栏,能够选取需要的 磁盘,包括镜像文件、光盘、移动硬盘、U盘等……总之,一切需要装载/推出的文件
点击‘修复磁盘权限’可以修复文件的权限,以保证文件的安全和文件的有效;而‘修复磁盘’是可以检验和修复磁盘的问题,比如数据丢失 硬盘坏道等,如果损坏比较严重这是需要修硬件了

另一个比较常用的功能—格式化硬盘
在日常生活中 我们离不开U盘或移动硬盘,在Mac中 格式化硬盘也是在磁盘工具中完成的
一般全新的硬盘格式为NTFS,为Mac专用的硬盘一般为Mac OS 扩展 日志式
介绍几种常见格式
Mac OS 扩展(日志式):Mac最常用的格式,也是系统硬盘的格式,如果U盘和移动硬盘只在苹果电脑间使用那么用这个格式就好
Mac OS 扩展(日志式区分大小写):区分大小写是区分于 Mac OS扩展日志式 最大的区别,比如在这个格式下 同一名称文件 大写和小写会共同存在,尽量不要选这个会出现兼容性问题
FAT:在Mac和Win下都可以使用的硬盘格式,但对于文件大小有限制 一般文件不能超过4GB
ExFAT:在Mac和Win下可以使用,一般多为U盘格式,WinXP需要装驱动,ExFAT在Mac下读取速度一般
NTFS(compressed):(Win7)如果U盘和硬盘在Win和Mac之间使用的话,NTFS绝对是首选,Mac+Win最好选此
NTFS:这个版本比较老,U盘和硬盘在Win和Mac之间使用

插入U盘或硬盘,打开‘磁盘工具’选择你需要格式化的硬盘,在‘抹掉’中选择你需要的格式,由于我这个是4G的U盘,所以FAT是最好的选择,Win与Mac公用

NTFS
由于NTFS是微软的专利,所以在原生Mac下是只能读取,不能写入的,所以在Mac下需要第三方插件来支持读取NTFS,安装也是很方便的
Mac中NTFS插件有很多,比如Tuxera NTFS、Paragon NTFS、PropEdit、NTFS-3G等

点击查看 NTFS插件 帖子
点击下载 威锋盘 NTFS插件

  硬盘分区
从 Win过渡到Mac的用户 再使用后有疑虑 ‘为什么Mac没有 C/E/F等磁盘呢?’,这是因为Mac电脑没有硬盘分区的概念,也就是说Mac使用的是一整块硬盘空间来使用,而不像Windows 把硬盘划分很多空间区域。使用Boot Camp安装双系统(windows)时 需要硬盘分区
也就是说在Mac上 分区 完全靠用户自愿的。例如 你可以创建一个分区来用作Time Machine 备份,但硬盘出了问题 分区也是无药可救的。所以分区带来的益处在Mac上是微乎其微
Mac电脑上其实自带有两个分区,另一个分区属于隐藏分区 起到恢复盘的作用,所以在新电脑盒子里找不到传统的”系统恢复光盘”,在开机时按下option可以看见它,它叫“Recovery HD

硬盘分区也是需要由“磁盘工具”完成的,在‘实用工具’中找到它,打开
在左侧边栏找到你需要的分区的硬盘,这里我以移动硬盘为例(在分区之前请先备份一下),之后选择你需要分区的数量1~16,2个分区的涵义就是把这块硬盘划分为2为空间

在选择2个分区后,会出现2块区域,拖动之间的滑棍 可以调节这2块分区的容量空间分配
格式,格式可以参考上面的信息,根据自己需要找到合适的格式。大小,也可以手动输入容量空间的数值

之后,点击应用,热腾腾的硬盘出锅!

  磁盘镜像
磁盘镜像是可以将镜像文件(系统安装文件)投入到U盘之中,使之达到安装光盘一样的效果,适用于没有光驱的电脑安装或恢复系统
首先 打开磁盘工具程序,同时插入你需要被制成镜像的U盘(如果是OS X系统 需要8GB的U盘)根据刻录大小而定

在左边栏找到你的U盘或移动硬盘,在项目分栏中点击“恢复”,“恢复”具体涵义是指 将现成已有的镜像文件(dmg Iso)恢复到硬盘/U盘之中

之后,把你需要被刻录的镜像文件 拖入“源磁盘”之中,也可以点击“映像…”选取文件

“目的磁盘”是需要被刻录的U盘或硬盘,拖入其中就可

在检查一遍所选取的内容是否有错,最后 点击“恢复”即可

钥匙串访问
钥匙串访问是顾名思义就是Mac中的钥匙,它在‘危机’时刻十分管用!!(要利用它的好处)
比如 QQ号忘了密码 可以在这里面查看 找到你当初的QQ号密码,邮箱密码忘了 也可以在这个程序中找到密码,是不是有点毛骨悚然的感觉,你的一切密码都在这里
首先我就不拿QQ密码举例了…我拿WIFI密码来举例, 比如你拿Mac去好友家上网,但好友很抠门,捂着键盘输入密码,但利用‘钥匙串访问’就能一览无余~~
在‘应用程序’文件夹中找到‘实用工具’文件夹 找到“钥匙串访问”,打开程序,这个程序窗口很单一,操作也很简单,具体自己点两下就了解了!
找到WIFI的项目,首先是要找到WIFI的名称了(这个容易鉴别),双击之后弹出一个窗口,这个就是着串‘钥匙’的具体信息了~在查看密码前需要鉴定用户密码(登录密码)
在输入你自己的密码后 ,把‘显示密码’√划上,就能查看别人WIFI的‘密码’了~  这只是一个例子,更多的是在找不到密码的危急时刻使用

这是是抛砖引玉,强大的钥匙串访问 不止看看密码这么简单,具体深奥的用法  本人不才,各位探索~

  Boot Camp双系统
需要Windows?可以!在Mac中Boot Camp助理可以让你使用Windows,一台电脑,两个系统!
什么是Boot Camp?Boot Camp 是可以让您安装Windows 安装光盘和在 Mac 电脑上运行 Windows的助理。Windows 将被安装在Mac的另一个分区上,所以安装双系统 需要分区
切换Mac/Win系统也是十分的方便,重新启动或启动电脑时按下option键 即可选择当前需要的操作系统,相互切换系统需要重启,也就是说一台电脑有两种状态,一种是Mac状态,一种是Win状态,它们相互生存 互不打扰。
前 期准备:Windows安装光盘,没有光盘或插不了光盘可以制作一个U盘镜像  与光盘效果一样。iMac台式机用户需要注意了:在未安装 驱动之前 蓝牙的Magic Mouse鼠标和 Wireless Keyboard键盘是无法使用的,无法操作电脑的!因此需要一个无线(不是蓝牙)或有线的键盘鼠标。

看看具体步骤吧 我以普遍的安装方式安装,首先在“实用工具”中找到“Boot Camp助理”。点击‘继续’

有些人可能没有“创建更高版本的安装盘” 所以不用勾上。第 二个重要啦,“从Apple下载Win支持的软件”这里指的是驱动以及蓝牙鼠标键盘和摄像头等的驱动,以便在Windows中使用,但 苹果服务器的网速我想大家都知道,很慢,而且这个驱动也将近1GB左右,网速快的和iMac没有有线鼠标键盘的同学可以选择勾上,不过在安装完Win后可 以手动下载,所以只是早晚下载的事儿。第三个“安装Win7或更高版本”勾上,除非安XP(XP比较费工夫)
Apple官方更新BootCamp
手动下载BootCamp驱动连接

接下来会看到一个分区调整的界面,插入安装光盘或安装U盘,拖动中间滑棍来调整Mac与Win的硬盘容量划分,根据自己使用情况而定

电脑会自动分区,如果提示分区失败,可以打开‘磁盘工具’程序 修复一下磁盘权限即可,分区完毕,电脑会黑屏 重启

之后,熟悉的Windows安装界面出现了,这里的安装也是十分重要,关系着Windows安装的正确与否
选择“自定义(高级)”,从中可以自定义安装 路径或磁盘

接着,十分重要的界面出现了!这不仅关系着Windows的性命,同时也关乎着你的Mac系统的性命!小心!仔细!
一定一定要选择 之前划分的BootCamp分区,选择分区后 点击“驱动器选项(高级)”

点击“格式化”,格式化BootCamp这个分区,已达到Windows需要的分区格式

之后的步骤就是等待安装了,安装步骤一切顺利后 Windows启动,一切都是你熟悉的Windows,之前没有安装驱动可以下载安装驱动

启动或重新启动电脑时按住option键 可以选择当前需要启动哪一个系统

虚拟机
双系统太繁琐?寻求最简单使用Windows?虚拟机是首选!
虚拟机是另一种可以在Mac上使用Win的工具,它要比BootCamp双系统要简单,同时也很方便,相互切换也不必重启电脑,只是像打开一个软件一样简单,更不用硬盘分区
虚拟机可以看作是Mac的一个软件,利用这个软件来模拟使用windows,也就是说一台电脑以Mac系统为基础 可以同时运行两个系统和同时运行Mac和Win的应用程序
就像这样,是不是很酷呢,可以运行Windows、Linux 甚至 Google Chrome OS等操作系统

目 前普遍使用的虚拟机有两个 Parallels Desktop(简称PD)和VMware Fusion(简称VM) ,这俩孰优孰劣目前不能定夺,各有优缺,PD用的人多  界面华丽,VM操作简单 稳定性强。很多基本的功能两者都是相似的(目前最新版本都是支持Windows8)

Parallels Desktop目前在Apple Store上正版售价为¥298,使用PD 需要激活码,目前网上售卖的激活码也在¥188左右
点击 ParallelsDesktop威锋盘下载

VMware Fusion目前在Apple Store上正版售价为¥319,VM相比PD 要容易破解
点击VMware Fusion威锋盘下载

接着 我以 VMware Fusion为示范安装windows7
需要Windows7安装光盘(要求是‘纯洁版’的)或者制作好的U盘安装镜像 ,或者直接在电脑上下载windows的ISO镜像安装包
打开虚拟机选择安装方式
‘新建’就是新建一个虚拟机的操作系统,一般选这个。‘新建Boot Camp’就是把目前有的BootCamp双系统导入虚拟机中

插入光盘,确定是需要安装的系统后点击‘继续’

接 着,选择Windows的安装类型(集成),有“更加无缝”和“更加独立”两种方式,更加无缝就是Mac中的文件会在Win中同步显示,在Win删除一个 文件则Mac中这个文件也会消失。更加独立则是这个Windows就是全新的,Win与Mac互不打扰,但之间可以共享和传输拷贝文件/文字。个人和多数 人都选择的是“更加独立”,视自己习惯而定

下一步,‘完成’,其中有分配给虚拟机的性能,后期可以再设置调整,点击完成,会弹出窗口,选择你想要存储的位置,保存Windows系统的虚拟机文件,这个文件比较大(20GB左右)

这个文件就是Windows系统所需的文件,在Finder中就能找到它

剩 下的步骤就属于Windows安装步骤了,基本上是比较顺利的步骤。虚拟机会重新启动,熟悉的Windows便会启动(注意:虚拟机会耗大量的内存,请把 Mac上不需要的程序退出,预留内存给虚拟机使用),之后在Win上会按照各种驱动和插件,虚拟机上Win的网络会桥接Mac的网络使用,系统之间的拷贝 文件/文字就像在一个系统中操作那样方便。
不需要Windows时,和正常一样,在菜单中选择‘关机’,Windows会关机,直到黑屏后 再关闭 退出虚拟机,不然下次打开虚拟机会恢复未关机的Windows 耽误时间。

双系统与虚拟机
通过以上安装与使用方式  可以辨别BootCamp双系统和虚拟机的利与弊,优与缺

这是张以按照 电脑的100%性能为标准,比如内存、CUP等,蓝色代表Mac的性能量,红色代表Win的性能量,与此比较便可大致 明确虚拟机与双系统之间的性能差距

这是为什么呢?与双系统和虚拟机的特性相关联。
BootCamp双系统的Win与Mac切换时需要重启电脑,之间的两个系统只许运行一个,一台电脑的硬件专心奉献与一台系统
VM/PD虚拟机,它们只是一个Mac的应用程序,在Mac的基础上运行Win,切换系统时只需切换桌面样便捷,但一台电脑的硬件要供足两部系统来使用,由于虚拟机要耗费大量内存,最好再扩大一下电脑内存

那双系统好还是虚拟机好呢?根据它们的特性与自己需求来选取
虚拟机:安装简单,启动方便 快捷,两部系统可同时使用,相互切换便捷,但由于性能 只可在Win上运行小量程序,比如上上网 用用网银 看看电影 小游戏…虚拟机是首选
双系统:纯正安装Windows,性能比虚拟机强大,根据需求选用启动,日常可以 运行大游戏  专业性软件  适合大量运算…

Android Fragments 详细使用

Fragments 诞生初衷

自从Android 3.0中引入fragments 的概念,根据词海的翻译可以译为:碎片、片段。其上的是为了解决不同屏幕分辩率的动态和灵活UI设计。大屏幕如平板小屏幕如手机,平板电脑的设计使得其有 更多的空间来放更多的UI组件,而多出来的空间存放UI使其会产生更多的交互,从而诞生了fragments 。fragments 的设计不需要你来亲自管理view hierarchy 的复杂变化,通过将Activity 的布局分散到frament 中,可以在运行时修改activity 的外观,并且由activity 管理的back stack 中保存些变化。

 

      Fragments 设计理念

在设计应用时特别是Android 应用 ,有众多的分辨率要去适应,而fragments 可以让你在屏幕不同的屏幕上动态管理UI。例如:通讯应用程序(QQ),用户列表可以在左边,消息窗口在右边的设计。而在手机屏幕用户列表填充屏幕当点击 某一用户时,则弹出对话窗口的设计,如下图:

Fragments的生命周期

每一个fragments 都有自己的一套生命周期回调方法和处理自己的用户输入事件。 对应生命周期可参考下图:

其中大多数程序必须使用Fragments 必须实现的三个回调方法分别为:

onCreate

系统创建Fragments 时调用,可做执行初始化工作或者当程序被暂停或停止时用来恢复状态,跟Activity 中的onCreate相当。

onCreateView

用于首次绘制用户界面的回调方法,必须返回要创建的Fragments 视图UI。假如你不希望提供Fragments 用户界面则可以返回NULL。

onPause

当用户离开这个Fragments 的时候调用,这时你要提交任何应该持久的变化,因为用户可能不会回来。更多的事件可以参考上图的生命周期关系图。

Fragments 的类别

系统内置了三种Fragments ,这三种Fragments 分别有不同的应用场景分别为:

DialogFragment

对话框式的Fragments,可以将一个fragments 对话框并到activity 管理的fragments back stack 中,允许用户回到一个前曾摒弃fragments.

ListFragments

类似于ListActivity 的效果,并且还提供了ListActivity 类似的onListItemCLick和setListAdapter等功能。

PreferenceFragments

类似于PreferenceActivity .可以创建类似IPAD的设置界面。

 

Fragments 的详细使用

首先先来看一张DEMO 效果图:

左边点击时,右边的字符会与左边选中的项的字符相同。与IPAD上的设置界面很相似,这一点是否借鉴了ipad 上的UI呢?

相就的XML文件:

复制代码

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”horizontal” >

<fragment class=”com.xuzhi.fragment.FragmentDemoActivity$TitlesFragment” android:id=”@+id/titles” android:layout_weight=”1″
android:layout_width=”0px” android:layout_height=”match_parent”
/>

<FrameLayout android:id=”@+id/details” android:layout_weight=”1″ android:layout_width=”0px” android:layout_height=”match_parent”
android:background=”?android:attr/detailsElementBackground”
></FrameLayout>
</LinearLayout>

复制代码

 

 

主界面代码(己做注释):

 

复制代码

package com.xuzhi.fragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;

public class FragmentDemoActivity extends Activity {

public static String[] array = { “text1,”, “text2”, “text3”, “text4”,
“text5,”, “text6”, “text7”, “text8” };

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

public static class TitlesFragment extends ListFragment {

boolean mDualPane;
int mCurCheckPosition = 0;

@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
System.out.println(“Fragment–>onCreate”);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
System.out.println(“Fragment–>onCreateView”);
return super.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println(“Fragment–>onPause”);
}

@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();

System.out.println(“Fragment–>onStop”);
}

@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
System.out.println(“Fragment–>onAttach”);
}

@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
System.out.println(“Fragment–>onStart”);
}

@Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println(“Fragment–>onResume”);
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println(“Fragment–>onDestroy”);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
System.out.println(“Fragment–>onActivityCreted”);
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, array));

View detailsFrame = getActivity().findViewById(R.id.details);

mDualPane = detailsFrame != null
&& detailsFrame.getVisibility() == View.VISIBLE;

if (savedInstanceState != null) {
mCurCheckPosition = savedInstanceState.getInt(“curChoice”, 0); //从保存的状态中取出数据
}

if (mDualPane) {
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

showDetails(mCurCheckPosition);
}
}

@Override
public void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);

outState.putInt(“curChoice”, mCurCheckPosition);//保存当前的下标
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
showDetails(position);
}

void showDetails(int index) {
mCurCheckPosition = index;
if (mDualPane) {
getListView().setItemChecked(index, true);
DetailsFragment details = (DetailsFragment) getFragmentManager()
.findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
details = DetailsFragment.newInstance(mCurCheckPosition);

//得到一个fragment 事务(类似sqlite的操作)
FragmentTransaction ft = getFragmentManager()
.beginTransaction();
ft.replace(R.id.details, details);//将得到的fragment 替换当前的viewGroup内容,add则不替换会依次累加
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);//设置动画效果
ft.commit();//提交
}
} else {
new AlertDialog.Builder(getActivity()).setTitle(
android.R.string.dialog_alert_title).setMessage(
array[index]).setPositiveButton(android.R.string.ok,
null).show();
}
}
}

/**
* 作为界面的一部分,为fragment 提供一个layout
* @author terry
*
*/
public static class DetailsFragment extends Fragment {

public static DetailsFragment newInstance(int index) {
DetailsFragment details = new DetailsFragment();
Bundle args = new Bundle();
args.putInt(“index”, index);
details.setArguments(args);
return details;
}

public int getShownIndex() {
return getArguments().getInt(“index”, 0);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
if (container == null)
return null;

ScrollView scroller = new ScrollView(getActivity());
TextView text = new TextView(getActivity());

int padding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
.getResources().getDisplayMetrics());
text.setPadding(padding, padding, padding, padding);
scroller.addView(text);

text.setText(array[getShownIndex()]);
return scroller;
}
}
}

复制代码

注意:

 

  1. 如果你想在Fragment 里面创建menu,则必须在onCreate的时候设置让它可以存在optionMenu才可以创建,代码为:
    复制代码
    public static class DetailsFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    }
    }

    复制代码

    之后的操作即可以像平常Android的menu用法一样,代码为:

    复制代码
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO Auto-generated method stub
    super.onCreateOptionsMenu(menu, inflater);
    menu.add(“Menu 1a”).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    menu.add(“Menu 1b”).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    Toast.makeText(getActivity(), “index is”+getShownIndex()+” && menu text is “+item.getTitle(), 1000).show();
    return super.onOptionsItemSelected(item);
    }

    复制代码

更多详细的使用方法,请参考SDK和APIDEMO中相关的例子和解释。

DEMO下载:

Android基础类之BaseAdapter

BaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口类Adapter,
1、Adapter类简介
1)、Adapter相关类结构如下图所示:
Adapter
自定义Adapter子类,就需要实现上面几个方法,其中最重要的是getView()方法,它是将获取数据后的View组件返回,如ListView中每一行里的TextView、Gallery中的每个ImageView。
     2)、Adapter在Android应用程序中起着非常重要的作用,应用也非常广泛,它可看作是数据源和UI组件之间的桥梁,其中Adapter、数据和UI之间的关系,可以用下图表示:
t2A9A
3)、常用子类
Adapter常用子类
2、BaseAdapter简介
BaseAdapter是实现了ListAdapter和SpinnerAdapter两个接口,当然它也可以直接给ListView和Spinner等UI组件直接提供数据。
相关类结构如下图所示:
tCCA2
3、示例
示例一:Gallery显示一组图片
运行结果:

说明:上面一行图片是Gallery画廊,每次点击一个Gallery图片时,会同时在下面以大图形式显示出来该图片
布局文件:

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/hello”
/>

<Gallery
android:id=”@+id/gallery1″
android:layout_width=”match_parent”
android:spacing=”5px”
android:layout_height=”wrap_content”
></Gallery>
<ImageView
android:id=”@+id/iv”
android:layout_gravity=”center_vertical”
android:layout_marginTop=”20px”
android:layout_width=”320px”
android:layout_height=”320px”
></ImageView>

</LinearLayout>

MainActivity类:
package com.magc.adapter;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;

public class MainActivity extends Activity {
private Gallery gallery;
private ImageView imgview;
private int[] imgs = {R.drawable.a6,R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4,R.drawable.a5};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgview = (ImageView)findViewById(R.id.iv);
gallery = (Gallery)findViewById(R.id.gallery1);
MyImgAdapter adapter = new MyImgAdapter(this);
gallery.setAdapter(adapter);
gallery.setOnItemClickListener(new OnItemClickListener() {
//用户点击图片时,将该图片的ResourceID设到下面的ImageView中去,
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position,
long arg3) {

imgview.setImageResource(imgs[position]);

}
});
}

class MyImgAdapter extends BaseAdapter {
//自定义图片Adapter以内部类形式存在于MainActivity中,方便访问MainActivity中的各个变量,特别是imgs数组
private Context context;//用于接收传递过来的Context对象
public MyImgAdapter(Context context) {
super();
this.context = context;
}

/* (non-Javadoc)
* @see android.widget.Adapter#getCount()
*/
@Override
public int getCount() {
return imgs.length;
}

/* (non-Javadoc)
* @see android.widget.Adapter#getItem(int)
*/
@Override
public Object getItem(int position) {
return position;
}

/* (non-Javadoc)
* @see android.widget.Adapter#getItemId(int)
*/
@Override
public long getItemId(int position) {
return position;
}

/* (non-Javadoc)
* @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//针对每一个数据(即每一个图片ID)创建一个ImageView实例,
ImageView iv = new ImageView(context);//针对外面传递过来的Context变量,
iv.setImageResource(imgs[position]);
Log.i(“magc”, String.valueOf(imgs[position]));
iv.setLayoutParams(new Gallery.LayoutParams(80, 80));//设置Gallery中每一个图片的大小为80*80。
iv.setScaleType(ImageView.ScaleType.FIT_XY);
return iv;
}

}

}

android头像设置:从本地照片库或拍照获取并剪裁

功能介绍

制作android应用时,用户注册的功能必不可少,往往还需要具备用户头像的编辑功能,设置过程如下图:

        界面设计

建立一个缩略图ImageView,点击时,弹出设置头像的对话框,设置完成后,刷新缩略图;

[code lang="xml"]</code>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#F3F1DA"
android:orientation="vertical" >

<!-- title -->

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/title_bg"
android:gravity="center"
android:orientation="horizontal" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/title_bar_txt"
android:textColor="@android:color/white" />
</LinearLayout>

<!-- image switch -->

<RelativeLayout
android:id="@+id/switch_face_rl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="20dip"
android:background="@drawable/item_edit_bg"
android:clickable="true"
android:padding="5dip" >

<ImageView
android:id="@+id/face"
android:layout_width="42dip"
android:layout_height="42dip"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dip"
android:src="@drawable/mini_avatar" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:layout_toRightOf="@id/face"
android:layout_gravity="center"
android:text="点击设置头像"
android:textColor="@android:color/black" />
</RelativeLayout>

</LinearLayout>

[/code]

Activity设计

MainActivity.java:

[code lang="java"]</code>

package com.xzw.picture;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.xzw.utils.Tools;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;

/**
*
* @author XuZhiwei (xuzw13@gmail.com) Create at 2012-8-17 上午10:14:40
*/
public class MainActivity extends Activity {
/* 组件 */
private RelativeLayout switchAvatar;
private ImageView faceImage;

private String[] items = new String[] { "选择本地图片", "拍照" };
/* 头像名称 */
private static final String IMAGE_FILE_NAME = "faceImage.jpg";

/* 请求码 */
private static final int IMAGE_REQUEST_CODE = 0;
private static final int CAMERA_REQUEST_CODE = 1;
private static final int RESULT_REQUEST_CODE = 2;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // 去掉标题
setContentView(R.layout.main);
switchAvatar = (RelativeLayout) findViewById(R.id.switch_face_rl);
faceImage = (ImageView) findViewById(R.id.face);
// 设置事件监听
switchAvatar.setOnClickListener(listener);
}

private View.OnClickListener listener = new View.OnClickListener() {

@Override
public void onClick(View v) {
showDialog();
}
};

/**
* 显示选择对话框
*/
private void showDialog() {

new AlertDialog.Builder(this)
.setTitle("设置头像")
.setItems(items, new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
Intent intentFromGallery = new Intent();
intentFromGallery.setType("image/*"); // 设置文件类型
intentFromGallery
.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intentFromGallery,
IMAGE_REQUEST_CODE);
break;
case 1:
Intent intentFromCapture = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
// 判断存储卡是否可以用,可用进行存储
if (Tools.hasSdcard()) {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File file = new File(path,IMAGE_FILE_NAME);
intentFromCapture.putExtra(
MediaStore.EXTRA_OUTPUT,
Uri.fromFile(file));
}

startActivityForResult(intentFromCapture,CAMERA_REQUEST_CODE);
break;
}
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//结果码不等于取消时候
if (resultCode != RESULT_CANCELED) {

switch (requestCode) {
case IMAGE_REQUEST_CODE:
startPhotoZoom(data.getData());
break;
case CAMERA_REQUEST_CODE:
if (Tools.hasSdcard()) {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File tempFile = new File(path,IMAGE_FILE_NAME);
startPhotoZoom(Uri.fromFile(tempFile));
} else {
Toast.makeText(MainActivity.this, "未找到存储卡,无法存储照片!",Toast.LENGTH_LONG).show();
}
break;
case RESULT_REQUEST_CODE: //图片缩放完成后
if (data != null) {
getImageToView(data);
}
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}

/**
* 裁剪图片方法实现
*
* @param uri
*/
public void startPhotoZoom(Uri uri) {

Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 340);
intent.putExtra("outputY", 340);
intent.putExtra("return-data", true);
startActivityForResult(intent, RESULT_REQUEST_CODE);
}

/**
* 保存裁剪之后的图片数据
*
* @param picdata
*/
private void getImageToView(Intent data) {
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
Drawable drawable = new BitmapDrawable(this.getResources(),photo);
faceImage.setImageDrawable(drawable);
}
}

}
[/code]

Tools.java

[code lang="java"]</code>

package com.xzw.utils;

import android.os.Environment;
/**
*
* @author XuZhiwei (xuzw13@gmail.com)
* Create at 2012-8-17 上午10:14:40
*/
public class Tools {
/**
* 检查是否存在SDCard
* @return
*/
public static boolean hasSdcard(){
String state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
return true;
}else{
return false;
}
}
}
[/code]

天气预报接口API

国家气象局提供的天气预报接口

接口地址:

http://www.weather.com.cn/data/sk/101010100.html

http://www.weather.com.cn/data/cityinfo/101010100.html

http://m.weather.com.cn/data/101010100.html

 

对于第三个接口,返回信息比较全面,也是以json格式提供,格式如下

{“weatherinfo”: {
//基本信息;
“city”:”北京”,”city_en”:”beijing”,
“date_y”:”2012年2月16日”, “date”:””, “week”:”星期四”, “fchh”:”11″, “cityid”:”101010100″,
//摄氏温度
“temp1″:”2℃~-7℃”,
“temp2″:”1℃~-7℃”,
“temp3″:”4℃~-7℃”,
“temp4″:”7℃~-5℃”,
“temp5″:”5℃~-3℃”,
“temp6″:”5℃~-2℃”,
//华氏温度;
“tempF1″:”35.6℉~19.4℉”,
“tempF2″:”33.8℉~19.4℉”,
“tempF3″:”39.2℉~19.4℉”,
“tempF4″:”44.6℉~23℉”,
“tempF5″:”41℉~26.6℉”,
“tempF6″:”41℉~28.4℉”,
//天气描述;
“weather1″:”晴”,
“weather2″:”晴”,
“weather3″:”晴”,
“weather4″:”晴转多云”,
“weather5″:”多云”,
“weather6″:”多云转阴”,
//天气描述图片序号
“img1″:”0”,
“img2″:”99”,
“img3″:”0”,
“img4″:”99”,
“img5″:”0”,
“img6″:”99”,
“img7″:”0”,
“img8″:”1”,
“img9″:”1”,
“img10″:”99”,
“img11″:”1”,
“img12″:”2”,
“img_single”:”0″,
//图片名称;
“img_title1″:”晴”,
“img_title2″:”晴”,
“img_title3″:”晴”,
“img_title4″:”晴”,
“img_title5″:”晴”,
“img_title6″:”晴”,
“img_title7″:”晴”,
“img_title8″:”多云”,
“img_title9″:”多云”,
“img_title10″:”多云”,
“img_title11″:”多云”,
“img_title12″:”阴”,
“img_title_single”:”晴”,
//风速描述
“wind1″:”北风3-4级转微风”,
“wind2″:”微风”,
“wind3″:”微风”,
“wind4″:”微风”,
“wind5″:”微风”,
“wind6″:”微风”,
//风速级别描述
“fx1″:”北风”,
“fx2″:”微风”,
“fl1″:”3-4级转小于3级”,
“fl2″:”小于3级”,
“fl3″:”小于3级”,
“fl4″:”小于3级”,
“fl5″:”小于3级”,
“fl6″:”小于3级”,
//今天穿衣指数;
“index”:”冷”,
“index_d”:”天气冷,建议着棉衣、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣或冬大衣。”,
//48小时穿衣指数
“index48″:”冷”,
“index48_d”:”天气冷,建议着棉衣、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣或冬大衣。”,
//紫外线及48小时紫外线
“index_uv”:”弱”,
“index48_uv”:”弱”,
//洗车
“index_xc”:”适宜”,
//旅游
“index_tr”:”一般”,
//舒适指数
“index_co”:”较不舒适”,

“st1″:”1”,
“st2″:”-8″,
“st3″:”2”,
“st4″:”-4″,
“st5″:”5”,
“st6″:”-5″,
//晨练
“index_cl”:”较不宜”,
//晾晒
“index_ls”:”基本适宜”,
//过敏
“index_ag”:”极不易发”}}

 

全车各城市代码如下:

101010100=北京
101010200=海淀
101010300=朝阳
101010400=顺义
101010500=怀柔
101010600=通州
101010700=昌平
101010800=延庆
101010900=丰台
101011000=石景山
101011100=大兴
101011200=房山
101011300=密云
101011400=门头沟
101011500=平谷
101011600=八达岭
101011700=佛爷顶
101011800=汤河口
101011900=密云上甸子
101012000=斋堂
101012100=霞云岭

101020100=上海
101020200=闵行
101020300=宝山
101020400=川沙
101020500=嘉定
101020600=南汇
101020700=金山
101020800=青浦
101020900=松江
101021000=奉贤
101021100=崇明
101021101=陈家镇
101021102=引水船
101021200=徐家汇
101021300=浦东

101030100=天津
101030200=武清
101030300=宝坻
101030400=东丽
101030500=西青
101030600=北辰
101030700=宁河
101030800=汉沽
101030900=静海
101031000=津南
101031100=塘沽
101031200=大港
101031300=平台
101031400=蓟县

101040100=重庆
101040200=永川
101040300=合川
101040400=南川
101040500=江津
101040600=万盛
101040700=渝北
101040800=北碚
101040900=巴南
101041000=长寿
101041100=黔江
101041200=万州天城
101041300=万州龙宝
101041400=涪陵
101041500=开县
101041600=城口
101041700=云阳
101041800=巫溪
101041900=奉节
101042000=巫山
101042100=潼南
101042200=垫江
101042300=梁平
101042400=忠县
101042500=石柱
101042600=大足
101042700=荣昌
101042800=铜梁
101042900=璧山
101043000=丰都
101043100=武隆
101043200=彭水
101043300=綦江
101043400=酉阳
101043500=金佛山
101043600=秀山
101043700=沙坪坝

101050101=哈尔滨
101050102=双城
101050103=呼兰
101050104=阿城
101050105=宾县
101050106=依兰
101050107=巴彦
101050108=通河
101050109=方正
101050110=延寿
101050111=尚志
101050112=五常
101050113=木兰
101050201=齐齐哈尔
101050202=讷河
101050203=龙江
101050204=甘南
101050205=富裕
101050206=依安
101050207=拜泉
101050208=克山
101050209=克东
101050210=泰来
101050301=牡丹江
101050302=海林
101050303=穆棱
101050304=林口
101050305=绥芬河
101050306=宁安
101050307=东宁
101050401=佳木斯
101050402=汤原
101050403=抚远
101050404=桦川
101050405=桦南
101050406=同江
101050407=富锦
101050501=绥化
101050502=肇东
101050503=安达
101050504=海伦
101050505=明水
101050506=望奎
101050507=兰西
101050508=青冈
101050509=庆安
101050510=绥棱
101050601=黑河
101050602=嫩江
101050603=孙吴
101050604=逊克
101050605=五大连池
101050606=北安
101050701=大兴安岭
101050702=塔河
101050703=漠河
101050704=呼玛
101050705=呼中
101050706=新林
101050707=阿木尔
101050708=加格达奇
101050801=伊春
101050802=乌伊岭
101050803=五营
101050804=铁力
101050805=嘉荫
101050901=大庆
101050902=林甸
101050903=肇州
101050904=肇源
101050905=杜蒙
101051002=七台河
101051003=勃利
101051101=鸡西
101051102=虎林
101051103=密山
101051104=鸡东
101051201=鹤岗
101051202=绥滨
101051203=萝北
101051301=双鸭山
101051302=集贤
101051303=宝清
101051304=饶河

101060101=长春
101060102=农安
101060103=德惠
101060104=九台
101060105=榆树
101060106=双阳
101060201=吉林
101060202=舒兰
101060203=永吉
101060204=蛟河
101060205=磐石
101060206=桦甸
101060207=烟筒山
101060301=延吉
101060302=敦化
101060303=安图
101060304=汪清
101060305=和龙
101060306=天池
101060307=龙井
101060308=珲春
101060309=图们
101060310=松江
101060311=罗子沟
101060312=延边
101060401=四平
101060402=双辽
101060403=梨树
101060404=公主岭
101060405=伊通
101060406=孤家子
101060501=通化
101060502=梅河口
101060503=柳河
101060504=辉南
101060505=集安
101060506=通化县
101060601=白城
101060602=洮南
101060603=大安
101060604=镇赉
101060605=通榆
101060701=辽源
101060702=东丰
101060801=松原
101060802=乾安
101060803=前郭
101060804=长岭
101060805=扶余
101060901=白山
101060902=靖宇
101060903=临江
101060904=东岗
101060905=长白

101070101=沈阳
101070102=苏家屯
101070103=辽中
101070104=康平
101070105=法库
101070106=新民
101070107=于洪
101070108=新城子
101070201=大连
101070202=瓦房店
101070203=金州
101070204=普兰店
101070205=旅顺
101070206=长海
101070207=庄河
101070208=皮口
101070209=海洋岛
101070301=鞍山
101070302=台安
101070303=岫岩
101070304=海城
101070401=抚顺
101070403=清原
101070404=章党
101070501=本溪
101070502=本溪县
101070503=草河口
101070504=桓仁
101070601=丹东
101070602=凤城
101070603=宽甸
101070604=东港
101070605=东沟
101070701=锦州
101070702=凌海
101070703=北宁
101070704=义县
101070705=黑山
101070706=北镇
101070801=营口
101070802=大石桥
101070803=盖州
101070901=阜新
101070902=彰武
101071001=辽阳
101071002=辽阳县
101071003=灯塔
101071101=铁岭
101071102=开原
101071103=昌图
101071104=西丰
101071201=朝阳
101071202=建平
101071203=凌源
101071204=喀左
101071205=北票
101071206=羊山
101071207=建平县
101071301=盘锦
101071302=大洼
101071303=盘山
101071401=葫芦岛
101071402=建昌
101071403=绥中
101071404=兴城

101080101=呼和浩特
101080102=土默特左旗
101080103=托克托
101080104=和林格尔
101080105=清水河
101080106=呼和浩特市郊区
101080107=武川
101080201=包头
101080202=白云鄂博
101080203=满都拉
101080204=土默特右旗
101080205=固阳
101080206=达尔罕茂明安联合旗
101080207=石拐
101080301=乌海
101080401=集宁
101080402=卓资
101080403=化德
101080404=商都
101080405=希拉穆仁
101080406=兴和
101080407=凉城
101080408=察哈尔右翼前旗
101080409=察哈尔右翼中旗
101080410=察哈尔右翼后旗
101080411=四子王旗
101080412=丰镇
101080501=通辽
101080502=舍伯吐
101080503=科尔沁左翼中旗
101080504=科尔沁左翼后旗
101080505=青龙山
101080506=开鲁
101080507=库伦旗
101080508=奈曼旗
101080509=扎鲁特旗
101080510=高力板
101080511=巴雅尔吐胡硕
101080512=通辽钱家店
101080601=赤峰
101080602=赤峰郊区站
101080603=阿鲁科尔沁旗
101080604=浩尔吐
101080605=巴林左旗
101080606=巴林右旗
101080607=林西
101080608=克什克腾旗
101080609=翁牛特旗
101080610=岗子
101080611=喀喇沁旗
101080612=八里罕
101080613=宁城
101080614=敖汉旗
101080615=宝过图
101080701=鄂尔多斯
101080703=达拉特旗
101080704=准格尔旗
101080705=鄂托克前旗
101080706=河南
101080707=伊克乌素
101080708=鄂托克旗
101080709=杭锦旗
101080710=乌审旗
101080711=伊金霍洛旗
101080712=乌审召
101080713=东胜
101080801=临河
101080802=五原
101080803=磴口
101080804=乌拉特前旗
101080805=大佘太
101080806=乌拉特中旗
101080807=乌拉特后旗
101080808=海力素
101080809=那仁宝力格
101080810=杭锦后旗
101080811=巴盟农试站
101080901=锡林浩特
101080902=朝克乌拉
101080903=二连浩特
101080904=阿巴嘎旗
101080905=伊和郭勒
101080906=苏尼特左旗
101080907=苏尼特右旗
101080908=朱日和
101080909=东乌珠穆沁旗
101080910=西乌珠穆沁旗
101080911=太仆寺旗
101080912=镶黄旗
101080913=正镶白旗
101080914=正兰旗
101080915=多伦
101080916=博克图
101080917=乌拉盖
101080918=白日乌拉
101080919=那日图
101081000=呼伦贝尔
101081001=海拉尔
101081002=小二沟
101081003=阿荣旗
101081004=莫力达瓦旗
101081005=鄂伦春旗
101081006=鄂温克旗
101081007=陈巴尔虎旗
101081008=新巴尔虎左旗
101081009=新巴尔虎右旗
101081010=满洲里
101081011=牙克石
101081012=扎兰屯
101081014=额尔古纳
101081015=根河
101081016=图里河
101081101=乌兰浩特
101081102=阿尔山
101081103=科尔沁右翼中旗
101081104=胡尔勒
101081105=扎赉特旗
101081106=索伦
101081107=突泉
101081108=霍林郭勒
101081201=阿拉善左旗
101081202=阿拉善右旗
101081203=额济纳旗
101081204=拐子湖
101081205=吉兰太
101081206=锡林高勒
101081207=头道湖
101081208=中泉子
101081209=巴彦诺尔贡
101081210=雅布赖
101081211=乌斯太
101081212=孪井滩

101090101=石家庄
101090102=井陉
101090103=正定
101090104=栾城
101090105=行唐
101090106=灵寿
101090107=高邑
101090108=深泽
101090109=赞皇
101090110=无极
101090111=平山
101090112=元氏
101090113=赵县
101090114=辛集
101090115=藁城
101090116=晋洲
101090117=新乐
101090201=保定
101090202=满城
101090203=阜平
101090204=徐水
101090205=唐县
101090206=高阳
101090207=容城
101090208=紫荆关
101090209=涞源
101090210=望都
101090211=安新
101090212=易县
101090213=涞水
101090214=曲阳
101090215=蠡县
101090216=顺平
101090217=雄县
101090218=涿州
101090219=定州
101090220=安国
101090221=高碑店
101090301=张家口
101090302=宣化
101090303=张北
101090304=康保
101090305=沽源
101090306=尚义
101090307=蔚县
101090308=阳原
101090309=怀安
101090310=万全
101090311=怀来
101090312=涿鹿
101090313=赤城
101090314=崇礼
101090402=承德
101090403=承德县
101090404=兴隆
101090405=平泉
101090406=滦平
101090407=隆化
101090408=丰宁
101090409=宽城
101090410=围场
101090411=塞罕坎
101090501=唐山
101090502=丰南
101090503=丰润
101090504=滦县
101090505=滦南
101090506=乐亭
101090507=迁西
101090508=玉田
101090509=唐海
101090510=遵化
101090511=迁安
101090601=廊坊
101090602=固安
101090603=永清
101090604=香河
101090605=大城
101090606=文安
101090607=大厂
101090608=霸州
101090609=三河
101090701=沧州
101090702=青县
101090703=东光
101090704=海兴
101090705=盐山
101090706=肃宁
101090707=南皮
101090708=吴桥
101090709=献县
101090710=孟村
101090711=泊头
101090712=任丘
101090713=黄骅
101090714=河间
101090715=曹妃甸
101090801=衡水
101090802=枣强
101090803=武邑
101090804=武强
101090805=饶阳
101090806=安平
101090807=故城
101090808=景县
101090809=阜城
101090810=冀州
101090811=深州
101090901=邢台
101090902=临城
101090903=邢台县浆水
101090904=内邱
101090905=柏乡
101090906=隆尧
101090907=南和
101090908=宁晋
101090909=巨鹿
101090910=新河
101090911=广宗
101090912=平乡
101090913=威县
101090914=清河
101090915=临西
101090916=南宫
101090917=沙河
101090918=任县
101091001=邯郸
101091002=峰峰
101091003=临漳
101091004=成安
101091005=大名
101091006=涉县
101091007=磁县
101091008=肥乡
101091009=永年
101091010=邱县
101091011=鸡泽
101091012=广平
101091013=馆陶
101091014=魏县
101091015=曲周
101091016=武安
101091101=秦皇岛
101091102=青龙
101091103=昌黎
101091104=抚宁
101091105=卢龙
101091106=北戴河

101100101=太原
101100102=清徐
101100103=阳曲
101100104=娄烦
101100105=太原古交区
101100106=太原北郊
101100107=太原南郊
101100201=大同
101100202=阳高
101100203=大同县
101100204=天镇
101100205=广灵
101100206=灵邱
101100207=浑源
101100208=左云
101100301=阳泉
101100302=盂县
101100303=平定
101100401=晋中
101100402=榆次
101100403=榆社
101100404=左权
101100405=和顺
101100406=昔阳
101100407=寿阳
101100408=太谷
101100409=祁县
101100410=平遥
101100411=灵石
101100412=介休
101100501=长治
101100502=黎城
101100503=屯留
101100504=潞城
101100505=襄垣
101100506=平顺
101100507=武乡
101100508=沁县
101100509=长子
101100510=沁源
101100511=壶关
101100601=晋城
101100602=沁水
101100603=阳城
101100604=陵川
101100605=高平
101100701=临汾
101100702=曲沃
101100703=永和
101100704=隰县
101100705=大宁
101100706=吉县
101100707=襄汾
101100708=蒲县
101100709=汾西
101100710=洪洞
101100711=霍州
101100712=乡宁
101100713=翼城
101100714=侯马
101100715=浮山
101100716=安泽
101100717=古县
101100801=运城
101100802=临猗
101100803=稷山
101100804=万荣
101100805=河津
101100806=新绛
101100807=绛县
101100808=闻喜
101100809=垣曲
101100810=永济
101100811=芮城
101100812=夏县
101100813=平陆
101100901=朔州
101100902=平鲁
101100903=山阴
101100904=右玉
101100905=应县
101100906=怀仁
101101001=忻州
101101002=定襄
101101003=五台县豆村
101101004=河曲
101101005=偏关
101101006=神池
101101007=宁武
101101008=代县
101101009=繁峙
101101010=五台山
101101011=保德
101101012=静乐
101101013=岢岚
101101014=五寨
101101015=原平
101101100=吕梁
101101101=离石
101101102=临县
101101103=兴县
101101104=岚县
101101105=柳林
101101106=石楼
101101107=方山
101101108=交口
101101109=中阳
101101110=孝义
101101111=汾阳
101101112=文水
101101113=交城

101110101=西安
101110102=长安
101110103=临潼
101110104=蓝田
101110105=周至
101110106=户县
101110107=高陵
101110108=杨凌
101110200=咸阳
101110201=三原
101110202=礼泉
101110203=永寿
101110204=淳化
101110205=泾阳
101110206=武功
101110207=乾县
101110208=彬县
101110209=长武
101110210=旬邑
101110211=兴平
101110300=延安
101110301=延长
101110302=延川
101110303=子长
101110304=宜川
101110305=富县
101110306=志丹
101110307=安塞
101110308=甘泉
101110309=洛川
101110310=黄陵
101110311=黄龙
101110312=吴起
101110401=榆林
101110402=府谷
101110403=神木
101110404=佳县
101110405=定边
101110406=靖边
101110407=横山
101110408=米脂
101110409=子洲
101110410=绥德
101110411=吴堡
101110412=清涧
101110501=渭南
101110502=华县
101110503=潼关
101110504=大荔
101110505=白水
101110506=富平
101110507=蒲城
101110508=澄城

appcan 一种很方便的真机调试方法

这个方法绝对原创,也是自己在实践中总结的,可以避免如题那么的问题的放生。
操作如下:
第一,你在WEB模式里,创建一个http://192.168.0.88/index.html(自己服务器的IP)然后成成APK,步骤如下图:

第二,下载并安装APK到手机上
第三,安装配置IIS,新建一个网站,地址就指向你开发APPCAN的目录
OK了步骤都完成了,日后你就可以在计算机上开发代码,手机上直接运行那个APK直接看效果了,

避免了模拟题的不给力,避免了繁琐的生成安装等步骤。

以上是自己总结出来的东西,希望对开发的人有帮助,还有补充一下,如上操作必须有WIFI做支持,你懂的。

AppCan IDE 中常用的几个js

zy_anim.js
->function zy_anim_slide(p1,p2,t,cb);

说明:在同一个html中多个page之间切换的动画效果。由于AppCan的框架允许一个html中放多个page,每个page是一个div,可以实现在不刷新html的情况下,实现多个页面的切换展示。
p1:为当前显示page的id,
p2:为需要切换到的page的id,
t:为切换效果,枚举值为:slide_left,slide_right,slide_up,slide_down
cb:切换完成后的回调方法

zy_control.js
->function zy_fix(header,footer,run,cb)

说明:固定header区域和footer区域。如果你的界面布局是有header,content,footer区域,而且需要content区域具有 滚动条。那么Appcan提供方案是在当前窗口(window)中uexWindow.openSlibing两个辅窗口,分别作为header和 footer。这样,就能够固定住header和footer区域,避免在有些不支持position:fixed css属性的手机上,footer区域会跟中content区域滚动条一起滚动。
header:为header区域div的id
footer:为footer区域div的id
run:初始化完后需要再次调用uexWindow.Onload的话,run为“真”值,否则为“伪”值。
cb:为初始化完后的回调方法

->function zy_parse()
说明:解析url中“?”后的参数,以key-value形式存放到params对象中。

zy_tmpl.js
说明:zy_tmpl.js提供了一套模板,在跨域访问后获取回来的数据,需要迭代出html代码,然后赋值给某一div或ul等(常见的如获取新闻列表,返回json数据,然后解析给一个ul下)。

使用示例:
比如DEV文档中新浪微博的例子:
var tmpl='<div><div >${user.name}</div><div class=”ui-li-desc ui-smaller ui-float-right” >${cb:created_at}</div><p></p><h3 class=”ui-li-heading” style=”white-space:normal”>${text}</h3>${cb:thumbnail_pic}<div onclick=”event.preventDefault();” >来自${source}</div><div >转发${reposts_count}</div><div class=”ui-li-desc ui-smaller ui-float-right” >|</div><div class=”ui-li-desc ui-smaller ui-float-right” >收藏${favourites_count}</div><div >|</div><div >评论${comments_count}</div></div><p></p>’
return zy_tmpl_s(tmpl,d.retweeted_status,j2vCb);
JSON数据示例:
{
“statuses”: [
{
“created_at”: “Tue May 31 17:46:55 +0800 2011”,
“id”: 11488058246,
“text”: “求关注。”,
“source”: “<a href=”http://weibo.com” rel=”nofollow”>新浪微博</a>”,
“favorited”: false,
“truncated”: false,
“in_reply_to_status_id”: “”,
“in_reply_to_user_id”: “”,
“in_reply_to_screen_name”: “”,
“geo”: null,
“mid”: “5612814510546515491”,
“reposts_count”: 8,
“comments_count”: 9,
“annotations”: [],
“user”: {
“id”: 1404376560,
“screen_name”: “zaku”,
“name”: “zaku”,
“province”: “11”,
“city”: “5”,
“location”: “北京 朝阳区”,
“description”: “人生五十年,乃如梦如幻;有生斯有死,壮士复何憾。”,
“url”: “http://blog.sina.com.cn/zaku”,
“profile_image_url”: “http://tp1.sinaimg.cn/1404376560/50/0/1”,
“domain”: “zaku”,
“gender”: “m”,
“followers_count”: 1204,
“friends_count”: 447,
“statuses_count”: 2908,
“favourites_count”: 0,
“created_at”: “Fri Aug 28 00:00:00 +0800 2009”,
“following”: false,
“allow_all_act_msg”: false,
“remark”: “”,
“geo_enabled”: true,
“verified”: false,
“allow_all_comment”: true,
“avatar_large”: “http://tp1.sinaimg.cn/1404376560/180/0/1”,
“verified_reason”: “”,
“follow_me”: false,
“online_status”: 0,
“bi_followers_count”: 215
}
},

],
“previous_cursor”: 0,
“next_cursor”: 11488013766,
“total_number”: 81655
}

返回的json数据,会以tmpl为模板,每个tmpl都是一条微博内容的html结构。调用zy_tmpl_s,会把d.retweeted_status里的json数据去替换${user.name}等以“$”开头,”{}”包围的区域。

用法说明:

${first: name}:碰到对象数据(如果多条)第一条数据的时,用name代替,其中name可以为字符串,也可以为对象数据的某一对象”name”。

${last:name}:碰到对象数据(如果多条)最后一条数据的时,用name代替,其中name可以为字符串,也可以为对象数据的某一对象”name”。

${index:}:返回对象数据(如果多条)当前迭代的索引值,从0开始。

${cb:name}:以content内容作为参数,去调用cb回调方法。

${name}:以对象数据里属性name对于的value值代替

->zy_tmpl(t,dd,l,cb)

说明:迭代多条数据,返回迭代好的html代码
t:为用户自定义模板
dd:为迭代数据,json对象或其它对象
l:为dd数据(多条数据情况下)的长度
cb:碰到${cb:name}时用来回调的方法

->zy_tmpl_s(t,dd,cb)

说明:迭代单条数据,返回迭代好的html代码
t:为用户自定义模板
dd:为迭代数据,json对象或其它对象
cb:碰到${cb:name}时用来回调的方法

zy_json.js
->$.getJSON(a,b[,c,d])

说明:跨域访问请求方法,当为本地html访问网络数据时,调用uexXmlHttpMgr;当为网络环境调用网络环境时,如果是跨域请求使用JSONP 方式调用,如果非跨域请求,使用ajax方式调用;当为本地html访问本地文件时,使用uexFileMgr读取数据内容。
a:为访问url
b:为成功回调方法
c:为返回数据格式,当为”text”时,返回字符串数据,当为”json”,返回json对象数据。默认为”json”
d:失败的回调方法

Google Guice使用入门

本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单。

Google Guice需要使用JDK1.5以上java环境。

下载Google Guice之后,有以下几个文件:

Java代码
  1. aopalliance.jar
  2. guice-1.0.jar
  3. guice-servlet-1.0.jar
  4. guice-spring-1.0.jar
  5. guice-struts2-plugin-1.0.jar

本例只使用到guice-1.0.jar文件,将其加入到class path中。

下面简单地介绍范例:

范例1:使用com.google.inject.Module接口实现类
 

文件名
说明
HelloGuice.java
业务逻辑接口定义文件
HelloGuiceImpl.java
业务逻辑接口实现文件
HelloGuiceModule.java
该文件必须实现com.google.inject.Module接口
TestGuice.java
测试文件

HelloGuice.java

Java代码
  1. package cn.jcourse.guice;
  2. /**
  3.  * @author zhangtao
  4.  * HelloGuice接口,用于表达问候
  5.  */
  6. public interface HelloGuice {
  7.     public void sayHello();
  8. }

上面接口中,我们定义了一个方法,sayHello,用于向用户问候。这里我只是做演示用,在实际的业务中,业务逻辑很可能不是这么简单。

HelloGuiceImpl.java

Java代码
  1. package cn.jcourse.guice.impl;
  2. import cn.jcourse.guice.HelloGuice;
  3. /**
  4.  * @author zhangtao
  5.  * HellGuice实现类
  6.  */
  7. public class HelloGuiceImpl implements HelloGuice {
  8.     /* (non-Javadoc)
  9.      * @see cn.jcourse.guice.HelloGuice#sayHello()
  10.      */
  11.     public void sayHello() {
  12.         System.out.println(“Hello Guice!”);
  13.     }
  14. }

该类是HelloGuice接口的实现类,这里我们仅仅是向控制台输出了一个Hello Guice!字符串。

HelloGuiceModule.java

Java代码
  1. package cn.jcourse.guice;
  2. import cn.jcourse.guice.impl.HelloGuiceImpl;
  3. import com.google.inject.Binder;
  4. import com.google.inject.Module;
  5. /**
  6.  * @author zhangtao
  7.  * HelloGuice模块
  8.  */
  9. public class HelloGuiceModule implements Module {
  10.     /*
  11.      * (non-Javadoc)
  12.      *
  13.      * @see com.google.inject.Module#configure(com.google.inject.Binder)
  14.      */
  15.     public void configure(Binder binder) {
  16.         binder.bind(HelloGuice.class).to(HelloGuiceImpl.class);
  17.     }
  18. }

上面的代码用于告知Guice将接口和实现类绑定。

TestGuice.java

Java代码
  1. package cn.jcourse.guice.test;
  2. import cn.jcourse.guice.HelloGuice;
  3. import cn.jcourse.guice.HelloGuiceModule;
  4. import com.google.inject.Guice;
  5. import com.google.inject.Injector;
  6. import junit.framework.TestCase;
  7. /**
  8.  * @author zhangtao
  9.  * 测试Guice
  10.  */
  11. public class TestGuice extends TestCase {
  12.     public void testHelloGuice() {
  13.         Injector injector = Guice.createInjector(new HelloGuiceModule());
  14.         HelloGuice helloGuice = injector.getInstance(HelloGuice.class);
  15.         helloGuice.sayHello();
  16.     }
  17. }

上面的代码我们使用JUnit来进行单元测试,这里的代码也相对比较简单。

在编写完上述代码后,我们运行TestGuice类,将会发现它向控制台输出了Hello Guice!。

范例2:使用Java Annotation

范例1中,我们自己手工的去配置了绑定关系,当然我们也可以不用那么做。我们可以直接为HelloGuice加上@ImplementedBy注释,而省略掉对com.google.inject.Module的实现。

HelloGuice.java

Java代码
  1. package cn.jcourse.guice;
  2. import cn.jcourse.guice.impl.HelloGuiceImpl;
  3. import com.google.inject.ImplementedBy;
  4. /**
  5.  * @author zhangtao
  6.  * HelloGuice接口,用于表达问候
  7.  */
  8. @ImplementedBy(HelloGuiceImpl.class)
  9. public interface HelloGuice {
  10.     public void sayHello();
  11. }

这里我们使用了Guice提供的注解,ImplementedBy,表示该接口由HelloGuiceImpl类实现。这样我们就可以不手动的去配置依赖关系。再看看TestGuice.java。

TestGuice.java

Java代码
  1. package cn.jcourse.guice.test;
  2. import junit.framework.TestCase;
  3. import cn.jcourse.guice.HelloGuice;
  4. import com.google.inject.Guice;
  5. import com.google.inject.Injector;
  6. /**
  7.  * @author zhangtao
  8.  * 测试Guice
  9.  */
  10. public class TestGuice extends TestCase {
  11.     public void testHelloGuice() {
  12.         //Injector injector = Guice.createInjector(new HelloGuiceModule());
  13.         Injector injector = Guice.createInjector();
  14.         HelloGuice helloGuice = injector.getInstance(HelloGuice.class);
  15.         helloGuice.sayHello();
  16.     }
  17. }

可以看出,我们不需要自己去new一个Module了,Guice会根据我们提供的注解自己来配置依赖关系。

我们运行例子的时候可以看出,它也输出了Hello Guice!到控制台。

 

 

 

通过 Guice 进行依赖项注入(1)

2009-01-12 作者:

zhangtaolv

本教程是转载教程,目的是让大家了解又一个很强大的依赖注入框架Guice.

Guice 是一个依赖项注入(DI)框架。几年来我一直建议开发人员使用 DI,因为它提高了可维护性、可测试性和灵活性。通过观察工程师对 Guice 的反馈,我发现说服程序员去采用一种新技术的最好方法是使这种技术简单易用。Guice 让 DI 变得很简单,因此 Google 采用了这种方法。我希望本文能帮助您轻松学习 Guice。

Guice 2.0 beta

在写这篇文章时,Guice 开发团队正在奋力编写 Guice 2.0,希望能在 2008 年底之前发布。早期的 beta 发布在 Google 代码下载站点。这是一个好消息,因为 Guice 团队添加了一些新功能,使 Guice 代码的使用和理解变得更简单。beta 版没有最终版中的一些功能,但是 beta 很稳定,质量也很好。事实上,Google 在产品软件中使用的是 beta 版。我建议您使用 beta 版。这篇文章是专门为 Guice 2.0 编写的,介绍了 Guice 的一些新功能,但没有讨论 1.0 中已经废弃的一些功能。Guice 团队向我保证:这里讨论的功能在最终发行版和当前 beta 版中都是一样的。

如果您已经了解了 DI,而且知道为什么要借助一个框架来使用 DI,那么您可以跳到 通过 Guice 进行基本注入 小节。否则,请继续阅读,了解 DI 的好处。

DI 案例

我将以一个例子开始。假设我正在编写一个超级英雄(superhero)应用程序,同时实现一个名为 Frog Man 的 hero(英雄)。清单 1 是相关代码和第一个测试(您一定明白编写单元测试的重要性,这里就不多说了)。

清单 1. 一个基本 hero 及其测试

Java代码
  1. public class FrogMan {
  2.   private FrogMobile vehicle = new FrogMobile();
  3.   public FrogMan() {}
  4.   // crime fighting logic goes here…
  5. }
  6. public class FrogManTest extends TestCase {
  7.  public void testFrogManFightsCrime() {
  8.     FrogMan hero = new FrogMan();
  9.     hero.fightCrime();
  10.     //make some assertions…
  11.   }
  12. }

似乎一切正常,但在运行测试时出现了如清单 2 所示的异常:

清单 2. 依赖项出现问题

Java代码
  1. java.lang.RuntimeException: Refinery startup failure.
  2.   at HeavyWaterRefinery.<init>(HeavyWaterRefinery.java:6)
  3.   at FrogMobile.<init>(FrogMobile.java:5)
  4.   at FrogMan.<init>(FrogMan.java:8)
  5.   at FrogManTest.testFrogManFightsCrime(FrogManTest.java:10)

似乎 FrogMobile 构建了一个 HeavyWaterRefinery,假设我不能在测试中构建其中一个依赖项。当然,我可以在生产环境中实现这一点,但是不能保证能在测试中构建第二个 提炼厂(refinery)。在现实生活中,您不可能提炼出氧化氘,但您可以依赖远程服务器和强大的数据库。原理是一样的:这些依赖项很难启动,交互起来 也很慢,这使得测试比平时更容易失败。

输入 DI

为了避免这个问题,您可以创建一个接口(例如 Vehicle),使 FrogMan 类接受 Vehicle 作为一个构造函数参数,如清单 3 所示:

清单 3. 依赖接口并注入它们

Java代码
  1. public class FrogMan {
  2.   private Vehicle vehicle;
  3.   public FrogMan(Vehicle vehicle) {
  4.     this.vehicle = vehicle;
  5.   }
  6.   // crime fighting logic goes here…
  7. }

这种用法就是 DI 的本质 — 使类通过引用接口而不是构建接口(或使用静态引用)来接受它们的依赖项。清单 4 显示了 DI 如何使测试变得更简单:

清单 4. 测试可以使用 mock 而不是麻烦的依赖项

Java代码
  1. static class MockVehicle implements Vehicle {
  2.   boolean didZoom;
  3.   public String zoom() {
  4.     this.didZoom = true;
  5.     return “Mock Vehicle Zoomed.”;
  6.   }
  7. }
  8. public void testFrogManFightsCrime() {
  9.   MockVehicle mockVehicle = new MockVehicle();
  10.   FrogMan hero = new FrogMan(mockVehicle);
  11.   hero.fightCrime();
  12.   assertTrue(mockVehicle.didZoom);
  13.   // other assertions
  14. }

这个测试使用了一个手动编写的 mock 对象来替换 FrogMobile。DI 不仅在测试中省去了麻烦的 refinery 启动过程,而且使测试不用了解 FrogMobile 具体细节。需要的仅是一个 Vehicle 接口。除了使测试变得更简单之外,DI 还有助于提高代码的总体模块性和可维护性。现在,如果想将 FrogMobile 切换为 FrogBarge,可以不修改 FrogMan。所有 FrogMan 都依赖于 Vehicle 接口。

不过这里有一个陷阱。如果您是第一次阅读 DI,可能会想:“这下好了,现在所有 FrogMan 的调用方 都必须知道 FrogMobile(refinery、refinery 的依赖项,依此类推……)”。但如果是这样,DI 就永远不会这么流行。您可以不增加调用方的负担,而是编写一些工厂 来管理对象及其依赖项的创建。

工厂是存放框架的地方。工厂需要大量冗长重复的代码。工厂往往会让程序员(和读者)很痛苦,他们甚至会嫌它麻烦而放弃编写。Guice 和其他 DI 框架可作为 “超级工厂”,您可以通过配置它们来构建对象。配置 DI 框架比自己编写工厂容易得多。因此,程序员编写的代码大部分是 DI 样式的。测试越多代码就越好,程序员以后也就越省事。

通过 Guice 进行基本注入

我希望在我的介绍之后,您会相信 DI 能为您的设计增加价值,而且使用框架会使工作更轻松。现在让我们从 @Inject 注释和模块开始深入讨论 Guice。

告诉 Guice 给类添加 @Inject

FrogMan 与 Guice 上的 FrogMan 之间的唯一区别是 @Inject。清单 5 显示了 FrogMan 带有注释的构造函数:

清单 5. FrogMan 已经加上 @Inject

Java代码
  1. @Inject
  2. public FrogMan(Vehicle vehicle) {
  3.   this.vehicle = vehicle;
  4. }

一些工程师不喜欢给类添加 @Inject。他们更喜欢一个完全忽略 DI 框架的类。这种说法有一定道理,但是我不大赞同。依赖项的注入会使注释的作用更加明显。@Inject 标记只在您要求 Guice 构建类时才有意义。如果不要求 Guice 构建 FrogMan,这个注释对代码行为就没有任何影响。这个注释恰当地指出了 Guice 将参与构建类。但是,使用它需要源代码级别的访问。如果这个注释带来不便,或者正在使用 Guice 创建无法控制其源代码的对象,那么 Guice 就会用一个替代机制。

告诉 Guice 您需要哪个依赖项

Guice 知道您的 hero 需要一个 Vehicle 后,它需要知道提供什么 Vehicle。清单 6 包含一个 Module:一个特殊的类,用于告诉 Guice 各个接口对应的实现。

清单 6. HeroModule 将 Vehicle 绑定到 FrogMobile

Java代码
  1. public class HeroModule implements Module {
  2.   public void configure(Binder binder) {
  3.     binder.bind(Vehicle.class).to(FrogMobile.class);
  4.   }
  5. }

模块就是一个具有某种单实例对象方法的接口。Guice 传递给模块的 Binder 用于告诉 Guice 您想如何构造对象。绑定程序 API 形成一种 区域特定语言。这种小语言允许您编写表达式代码,比如 bind(X).to(Y).in(Z)。后面将提供更多有关绑定程序作用的例子。每次调用 bind 都会创建一个绑定,Guice 将使用绑定集解析注入请求。

使用 Injector 启动

然后,使用 Injector 类启动 Guice。通常需要尽早在程序中创建注入器。这样 Guice 能够帮助您创建大部分对象。清单 7 包含一个以 Injector 开始的示例 main 程序:

清单 7 使用 Injector 启动应用程序

Java代码
  1. public class Adventure {
  2.   public static void main(String[] args){
  3.     Injector injector = Guice.createInjector(new HeroModule());
  4.     FrogMan hero = injector.getInstance(FrogMan.class);
  5.     hero.fightCrime();
  6.   }
  7. }

为了获取注入器,需要在 Guice 类上调用 createInjector。向 createInjector 传递一个模块列表,用于配置它本身(本例只有一个,但您可以添加一个配置 evildoer 的 VillainModule)。拥有注入器后,使用 getInstance 向它请求对象,传递您想返回的 .class(细心的读者会注意到您不需要告诉 Guice 有关 FrogMan 的信息。如果您请求一个具体类,而它有一个 @Inject 构造函数或公共非参数构造函数的话,Guice 就会创建这个类,而无需调用 bind)。

这是 Guice 构造对象的第一种方式:显式询问。但是,您不会希望在启动例程之外使用这个操作。更好、更简单的方式是让 Guice 注入依赖项、依赖项的依赖项,依此类推(正如谚语所说:“背起地球的海龟站在另一个海龟的背上”)。最初看来,这似乎比较麻烦,但您很快就会习惯这种用 法。例如,清单 8 显示了一个注入了 FuelSource 的 FrogMobile:

清单 8. FrogMobile 接受一个 FuelSource

Java代码
  1. @Inject
  2. public FrogMobile(FuelSource fuelSource){
  3.   this.fuelSource = fuelSource;
  4. }

这意味着,当您检索 FrogMan 时,Guice 会构建一个 FuelSource、一个 FrogMobile,最后是一个 FrogMan。即使应用程序与注入器只交互一次,也是如此。

当然,您并不总是有机会控制应用程序的 main 例程。例如,许多 Web 框架自动构建 “操作”、“模板” 或其他一些初始服务。总是可以找到一个地方插入 Guice,不管是使用该框架的一个插件,还是使用一些自己手动编写的代码(例如,Guice 项目发布了一个 Struts 2 插件,它允许 Guice 配置您的 Strut 操作)。

 

 

通过 Guice 进行依赖项注入(2)

2009-01-12 作者:

zhangtaolv

其他注入形式

到目前为止,我展示了 @Inject 应用于构造函数的用法。当 Guice 找到注释时,它会挑选构造函数参数,并试图为每个参数找到一个配置绑定。这称为 构造函数注入。根据 Guice 的最佳实践指南,构造函数注入是询问依赖项的首选方式。但这不是唯一的方式。清单 9 显示了配置 FrogMan 类的另一种方式:

清单 9. 方法注入

Java代码
  1. public class FrogMan{
  2.   private Vehicle vehicle;
  3.   @Inject
  4.   public void setVehicle(Vehicle vehicle) {
  5.     this.vehicle = vehicle;
  6.   }
  7. //etc. …

注意,我没有使用注入的构造函数,而是改用一个带有 @Inject 标记的方法。Guice 会在构造好 hero 之后立即调用此方法。Spring 框架的忠实用户可以将此方法视为 “setter 注入”。不过,Guice 只关心 @Inject;您可以任意命名这个方法,它可以带有多个参数。此方法可以是包保护的,也可以是私有方法。

如果您认为 Guice 访问私有方法不是很好,可以参见清单 10,其中 FrogMan 使用了字段注入:

清单 10. 字段注入

Java代码
  1. public class FrogMan {
  2.   @Inject private Vehicle vehicle;
  3.   public FrogMan(){}
  4. //etc. …

同样,所有 Guice 都只关心 @Inject 注释。字段注入查找注释的所有字段并试图注入相应的依赖项。

哪种方法最好

三个 FrogMan 版本都展示了相同的行为:Guice 在构建时注入相应的 Vehicle。不过,像 Guice 的作者一样,我更喜欢构造函数注入。下面简单分析这三种方式:

  • 构造函数注入 很简单。因为 Java 技术能保证构造函数调用,您不用担心出现未初始化的对象 — 不管是不是由 Guice 创建的。您还可以将字段标记为 final。
  • 字段注入 会影响可测试性,特别是将字段标记为 private 时。这破坏了使用 DI 的主要目的。应该尽量少使用字段注入。
  • 方法注入 在您不控制类的实例化时很有用。如果您有一个需要某些依赖项的超类,也可以使用方法注入(构造函数注入会使这种情况变得很复杂)。

选择实现

现在,假设应用程序中有多个 Vehicle。一样英勇的 Weasel Girl 无法驾驭 FrogMobile!同时,您不想在 WeaselCopter 上硬编码依赖项。清单 11 显示了 Weasel Girl 请求一种更快的传输模式:

清单 11. 使用注释请求某种特定的实现

Java代码
  1. @Inject
  2. public WeaselGirl(@Fast Vehicle vehicle) {
  3.   this.vehicle = vehicle;
  4. }

在清单 12 中,HeroModule 使用绑定函数告诉 Guice WeaselCopter 是 “很快” 的:

清单 12. 告诉 Guice Module 中的相关注释

Java代码
  1. public class HeroModule implements Module {
  2.  public void configure(Binder binder) {
  3.     binder.bind(Vehicle.class).to(FrogMobile.class);
  4.     binder.bind(Vehicle.class).annotatedWith(Fast.class).to(WeaselCopter.class);
  5.   }
  6. }

注意,我选择了一个注释,描述我想以抽象形式描述的工具种类(@Fast),而不是与实现太接近的注释(@WeaselCopter)。如果您使用 的注释将想要的实现描述得太精确,就让读者觉得创建一个隐式依赖项。如果使用 @WeaselCopter,而且 Weasel Girl 借用了 Wombat Rocket,就会对程序员阅读和调试代码造成混淆。

要创建 @Fast 注释,需要复制清单 13 中的模板:

清单 13. 复制粘贴这段代码以创建一个绑定注释

Java代码
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ElementType.FIELD, ElementType.PARAMETER})
  3. @BindingAnnotation
  4. public @interface Fast {}

如果您编写了大量 BindingAnnotations,就会得到许多这样的小文件,每个文件只是注释名称不同。如果您觉得这很繁琐,或者需要执行快速的原型设计,可以考 虑 Guice 的内置 @Named 注释,它接受一个字符串属性。清单 14 展示了这种替代方法:

清单 14. 使用 @Named 代替自定义注释

Java代码
  1. // in WeaselGirl
  2. @Inject
  3. public WeaselGirl(@Named(“Fast”) Vehicle vehicle) {
  4.   //…
  5. }
  6. // in HeroModule
  7. binder.bind(Vehicle.class)
  8.   .annotatedWith(Names.named(“Fast”)).to(WeaselCopter.class);

这种方法是可行的,但由于名称只在字符串内有效,所以这不能利用编译时检查和自动补齐。总的来说,我更愿意自己编写注释。

如果您根本不想使用注释,怎么办?即使添加 @Fast 或 @Named(“Fast”) 都会使类在某种程度上影响配置本身。如果想知道如何解决这个问题,请接着阅读。

provider 方法

如果每次探险都派遣 Frog Man,您可能会厌烦。您喜欢在每个场景中出现的 hero 是随机的。但是,Guice 的默认绑定程序 API 不允许出现 “每次调用时将 Hero 类绑定到一个不同的实现” 这样的调用。不过,您可以 告诉 Guice 使用一种特殊的方法来创建每个新的 Hero。清单 15 显示了将一个新方法添加到 HeroModule 中,并用特殊的 @Provides 注释进行注释:

清单 15. 使用 provider 编写自定义创建逻辑

Java代码
  1. @Provides
  2. private Hero provideHero(FrogMan frogMan, WeaselGirl weaselGirl) {
  3.   if (Math.random() > .5) {
  4.     return frogMan;
  5.   }
  6.   return weaselGirl;
  7. }

Guice 会自动发现具有 @Provides 注释的 Module 中的所有方法。根据 Hero 的返回类型,在您请求某个 hero 时,Guice 会进行计算,它应该调用 provider 方法来提供 hero。您可以为 provider 方法添加逻辑以构建对象并在缓存中查询它,或者通过其他方式获得它。provider 方法是将其他库集成到 Guice 模块中的很好方式。它们也是从 Guice 2.0 开始提供的新方法(Guice 1.0 中只编写自定义 provider 类,这比较乏味,而且更加繁琐。如果您已经决定使用 Guice 1.0,用户指南中有这种旧方法的文档,而且在本文随附的 示例代码 中,您可以找到一个自定义 provider)。

在清单 15 中,Guice 自动使用正确的参数注入 provider 方法。这意味着 Guice 将从它的绑定列表中找到 WeaselGirl 和 FrogMan,您无需在 provider 方法中手动构建它们。这演示了 “海龟背地球” 原则(海龟背地球,哪海龟下面是什么呢?是由另一只海龟背着,如此反复)。您依靠 Guice 来提供依赖项,即使是配置 Guice 模块本身。

请求一个 Provider 而不是一个依赖项

假设一个故事(Saga)中要有多个 hero。如果要求 Guice 注入一个 Hero,只会得到一个 hero。但如果您请求一个 “hero provider”,就可以根据需要创建任意多的 hero,如清单 17 所示:

清单 17. 注入 provider 来控制实例化

Java代码
  1. public class Saga {
  2.   private final Provider<Hero> heroProvider;
  3.   @Inject
  4.   public Saga(Provider<Hero> heroProvider) {
  5.     this.heroProvider = heroProvider;
  6.   }
  7.   public void start() throws IOException {
  8.     for (int i = 0; i < 3; i++) {
  9.       Hero hero = heroProvider.get();
  10.       hero.fightCrime();
  11.     }
  12.   }
  13. }

提供者也可以推迟英雄的出场时间,直到传奇真正开始。如果英雄依赖于时间敏感或上下文敏感的数据,这就会很方便。

Provider 接口有一个方法:get<T>。要访问提供的对象,调用这个方法即可。每次有没有获取新对象以及对象如何配置取决于 Guice 是如何配置的(参阅下面的 作用域 部分,了解单实例对象和其他长生命周期对象的详细信息)。在本例中,Guice 使用 @Provides 方法,因为它是构建新 Hero 的注册方式。这意味着该传奇应该由任意三位英雄混合而成。

不要把提供者与 provider 方法弄混淆了(在 Guice 1.0,这两者更难区分开来)。尽管该 Saga 是从自定义 @Provides 方法中获得它的英雄,但您可以请求任意 Guice 实例化依赖项的一个 Provider。如果需要,可以根据清单 18 重新编写 FrogMan 的构造函数:

清单 18. 请求 Provider 而不是依赖项

Java代码
  1. @Inject
  2. public FrogMan(Provider<Vehicle> vehicleProvider) {
  3.   this.vehicle = vehicleProvider.get();
  4. }

(注意您完全不用更改这个模块代码)。重新编写没有任何作用;只是说明您总是可以请求 Provider,而不用直接请求依赖项。

作用域

默认情况下,Guice 为每个请求的依赖项创建一个新实例。如果对象是轻量级的,这个策略可以很好地工作。但是,如果有一个创建开销很大的依赖项,就可能需要在几台客户机之间共 享实例。在清单 19 中,HeroModule 将 HeavyWaterRefinery 作为一个单实例对象绑定:

清单 19. 将 HeavyWaterRefinery 绑定为一个单实例对象

Java代码
  1. public class HeroModule implements Module {
  2.   public void configure(Binder binder) {
  3.     //…
  4.     binder.bind(FuelSource.class)
  5.       .to(HeavyWaterRefinery.class).in(Scopes.SINGLETON);
  6.   }
  7. }

这意味着 Guice 会一直保持 “提炼厂” 可用,只要另一个实例需要燃料源,Guice 就会注入相同 的 “提炼厂”。这避免了在应用程序中启动多个 “提炼厂”。

在选择作用域时,Guice 提供了一个选项。可以使用绑定程序配置它们,或者直接注释依赖项,如清单 20 所示:

清单 20. 改用注释选择作用域

Java代码
  1. @Singleton
  2. public class HeavyWaterRefinery implements FuelSource {…}

Guice 提供了超出范围的 Singleton 作用域,但它允许您定义自己的作用域(如果您愿意)。例如,Guice servlet 包提供了两个其他作用域:Request 和 Session,它们为 servlet 请求和 servlet 会话提供类的一个独特实例。

常量绑定和模块配置

HeavyWaterRefinery 需要一个许可密钥才能启动。Guice 可以绑定常量值和新实例。请查看清单 21:

清单 21. 在模块中绑定常量值

Java代码
  1. public class HeavyWaterRefinery implements FuelSource {
  2.   @Inject
  3.   public HeavyWaterRefinery(@Named(“LicenseKey”) String key) {…}
  4. }
  5. // in HeroModule:
  6. binder.bind(String.class)
  7.   .annotatedWith(Names.named(“LicenseKey”)).toInstance(“QWERTY”);

这里有必要使用绑定注释,否则 Guice 将不能区分不同的 String。

注意,尽管前面不推荐使用,我还是选择使用 @Named 注释。因为我想显示清单 22 所示的代码:

清单 22. 使用属性文件配置模块

Java代码
  1. //In HeroModule:
  2. private void loadProperties(Binder binder) {
  3.   InputStream stream =
  4.     HeroModule.class.getResourceAsStream(“/app.properties”);
  5.   Properties appProperties = new Properties();
  6.   try {
  7.     appProperties.load(stream);
  8.     Names.bindProperties(binder, appProperties);
  9.   } catch (IOException e) {
  10.     // This is the preferred way to tell Guice something went wrong
  11.     binder.addError(e);
  12.   }
  13. }
  14. //In the file app.properties:
  15. LicenseKey=QWERTY1234

这段代码使用 Guice Names.bindProperties 实用函数,通过恰当的 @Named 注释将 app.properties 文件中的每个属性与一个常量绑定。这本身就很好,而且还显示了您可以使模块代码更复杂。如果喜欢,可以从数据库或 XML 文件加载绑定信息。模块是纯 Java 代码,这提供了很大的 灵活性。

结束语

Guice 主要概念小结:

  • 使用 @Inject 请求依赖项。
  • 将依赖项与 Module 中的实现绑定。
  • 使用 Injector 引导应用程序。
  • 使用 @Provides 方法增加灵活性。

需要了解的 Guice 知识还很多,但您应该先掌握这篇文章中讨论的内容。我建议下载它,以及本文的 示例代码。当然,您也可以创建自己的示例应用程序,这就更好了。通过示例深入了解概念但又不用考虑生产代码是很有意思的。如果要了解更多 Guice 高级功能(比如面向方面编程支持),建议您访问 参考资料 中的一些链接。

说到生产代码,DI 的一个缺点是它可能感染病毒。注入一个类后,它会导致注入下一个类,依此类推。不过这很好,因为 DI 使代码更好。另一方面,这需要大量重构现有代码。为了使工作易于管理,可以将 Guice Injector 存储在某处并直接调用它。应该将这当作一根临时需要的拐杖,但最后一定可以摆脱它。

Guice 2.0 即将推出。有一些功能我还没有讨论,它可以使模块的配置更简单,而且能支持更大、更复杂的配置方案。

我希望您会考虑将 Guice 添加到工具包中。根据我的经验,DI 对于实现灵活的可测试代码库特别有用。Guice 使 DI 变得简单而有趣。还有什么比容易编写的、灵活的、可测试的代码更好呢?

Google Guice 小试牛刀

Google Guice是一个轻量级Dependency Injection依赖注入框架,能够提供动态注入,即当不知道注射的这个对象注射给谁呢,需要在运行时才能得到的的这个接口的实现,这是Spring DI所不具有的,Spring DI所有配置都是写死的,并且Spring DI在应用程序启动时所有依赖注入关系都会初始好,而Google Guice则可以根据需要进行依赖注入初始化,也就是说只有当需要时,就可以对依赖注入关系进行初始化。

 

引入Google Guice包,从这个网址可以下载http://google-guice.googlecode.com/files/guice-3.0.zip

 

一。CommentDao.java

[java]

package com.template.guice;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:37
*/
public interface CommentDao {

public void comment(String message);
}
[/java]

二。CommentDaoImpl.java

[java]

package com.template.guice;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:38
*/
public class CommentDaoImpl implements CommentDao {

public CommentDaoImpl() {
}

@Override
public void comment(String message) {
System.out.print(message);
}
}

[/java]

三。CommentService.java

[java]

package com.template.guice;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:39
*/
public interface CommentService {

public void comment();
}

[/java]

四。CommentServiceImpl.java

[java]

package com.template.guice;

import com.google.inject.Inject;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:39
*/
public class CommentServiceImpl implements CommentService {

private CommentDao commentDao;

@Inject
public CommentServiceImpl(CommentDao commentDao) {
this.commentDao = commentDao;
}

@Override
public void comment() {
commentDao.comment("This is a comment message!");
}

public void setCommentDao(CommentDao commentDao) {
this.commentDao = commentDao;
}
}

[/java]

五。CommentModule.java

[java]

package com.template.guice;

import com.google.inject.AbstractModule;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:46
*/
public class CommentModule extends AbstractModule {

@Override
protected void configure() {
bind(CommentDao.class).to(CommentDaoImpl.class);
}
}

[/java]

六。Main.java

[java]

package com.template.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;

/**
* Created by IntelliJ IDEA.
* User: Zhong Gang
* Date: 11-8-2
* Time: 下午9:55
*/
public class Main {

public static void main(String[] args) {
Injector injector = Guice.createInjector(new CommentModule());
CommentService commentService = injector.getInstance(CommentServiceImpl.class);
commentService.comment();
}
}

[/java]

@Inject表示Guice会隐式调用CommentServiceImpl的构造方法,而CommentModule则表示需要将CommentDao以CommentDaoImpl来注入对象中。

eclipse 快捷键大全

1. 常用快捷键
(1)Ctrl+Space
说明:内容助理。提供对方法,变量,参数,javadoc等得提示,应运在多种场合,总之需要提示的时候可先按此快捷键。
注:避免输入法的切换设置与此设置冲突

(2)Ctrl+Shift+Space
说明:变量提示
(3)Ctrl+/
说明:添加/消除//注释,在eclipse2.0中,消除注释为Ctrl+\

(4)Ctrl+Shift+/
说明:添加注释

(5)Ctrl+Shift+\
说明:消除注释

(6)Ctrl+Shift+F
说明:自动格式化代码

(7)Ctrl+1
说明:批量修改源代码中的变量名,此外还可用在catch块上.

(8)Ctril+F6
说明:界面切换

(9)Ctril+Shift+M
说明:查找所需要得包

(10)Ctril+Shift+O
说明:自动引入所需要得包

(11)Ctrl+Alt+S
说明:源代码得快捷菜单。其中的Generate getters and setters 和 Surround with try/catch
block比较常用.建议把它们添加为快捷键.快捷键设置在windows->preferences->Workbench->Keys

2. 快捷键列表

编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?Alt+Shift+?Ctrl+Shift+Space
Java编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y

查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-

窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-

导航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L

搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G

文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓

文件
作用域 功能 快捷键
全局 保存 Ctrl+X Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N

项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B

源代码
作用域 功能 快捷键
Java编辑器 格式化 Ctrl+Shift+F
Java编辑器 取消注释 Ctrl+\
Java编辑器 注释 Ctrl+/
Java编辑器 添加导入 Ctrl+Shift+M
Java编辑器 组织导入 Ctrl+Shift+O
Java编辑器使用try/catch块来包围未设置,太常用了,所以在这里列出,建议自己设置。也可以使用Ctrl+1自动修正。

运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上