您的位置:首页 > 移动开发 > Android开发

Android深入探究笔记之一 -- 我的第一个 Android 程序,基于 Intent 的组件交互机制

2012-02-05 20:09 579 查看
1. 本文是临时写的。觉得有它才完整。距离我今天安排的睡觉时间还有 2 个小时,还有其它事情没做,因此仓促的凑上一篇吧。

2. 什么是 Android 。请 Google 之。

3. 搭建环境。

** 你需要有 Eclipse 或 Myeclipse 。当然还有 JDK 。

** 下载 Android SDK 和 ADT

SDK 即开发工具包( Software Development Kit )。

Android SDK 最新版本是 2.3 。但本笔记中的大部分范例都是基于 Android2.2 。下载方式直接搜就行了。所有妄图直接去 Android 官网上下载的行为,都将直接出发到我国和谐大局。切记。

安装 ADT 。

下载 Android ADT (Android Development Tools), 开发者工具。是一套基于 Eclipse 的插件。

最新的在仿佛是 0.9.9 吧。 依稀记得几天前一哥们硬盘里有这东西。

安装的方式有两种。

* 在线安装

1. 打开 Eclipse 。

( 突然想到关于兼容的问题,貌似我依稀记得,几个月前我安装的时候遇到过 Eclipse 和 ADT插件的版本兼容的问题。

表现就是 ADT 装完了,某些功能始终用不起来,比如模拟器,千呼万唤就是不出来。后来换了一个 Eclipse 3.5 的就好了(当时的 ADT 大概是 4 个月前的最新版)。

我没有无聊的仔细研究那个版本的 ADT 对应哪个版本的 Eclipse 。总之大家记得用Eclipse3.5 以上的版本就好 ,或者干脆去官网下最新的 Eclipse 。这应该就没什么问题,因为 Eclipse3.5、 3.6 我都有开发过 Android 的经验。没有问题 ) 。

2. 如图所式,点击 Eclipse 菜单栏, Help à Install New Software



“ Install New Software ”在 Eclipse 的不同版本有不同叫法,反正大概就那意思。

3. 如图所示,点击 “ Add.. ”,在出来的对话框,填入 “ http://dl-ssl.google.com/android/eclipse/



. 4 .这时候 Eclipse 会自动去搜寻可以安装的资源。要稍等一会,前提是你要联网。



5. 然后就一直下一步,在进行到某个时候,会让你选择是否同意某某协议才能继续,于是同意:



点击完成。

6. 等吧。要抱有打持久战的准备。

* 推荐另一种方式,下载安装包,离线安装,如:



然后,回到上面第三张图片,点击 “ Archive ”按钮,选择你现在的离线安装包,如图:



这样,也能继续安装步骤。

安装成功 后你将能在 Eclipse 工具栏上看到下图所示图标:





** 安装 SDK

解压它:





但是通过官方途径下载的 SDK 是不自带开发包的。

因为 Android 版本太多,你需要通过它的工具,自己去挑选需要的版本的 Android 开发包进行下载,点击下图所示的机器人:



然后就可以通过向导

选择你需要下载的 SDK 包,同时文档也需要你自己下载 ,这个很重要,一定要下载。建议选择下载的 SDK 版本时,别全选,选择 Android2.0 及其以上的就好, 2.3 我也是今天才听说,没试过水。就算你只选择了这几个包,也够你下很久的。

下载完成后,你的 android-sdk-windows 目录下会多出一个 platforms 目录,这下面就存放了你选择的下载好的 Android 开发包:



** 2.0 版本的对应的 API Level 是 5

** 2.1 版本的对应的 API Level 是 7

** 2.2 版本的对应的 API Level 是 8

** 至于我目录中的 2 、 3 、 4 是什么玩意我也没玩过。

** 配置 path 环境变量,便于命令窗口直接敲 Addroid 指令。需要将 Android SDK 安装目录中的 tools 文件夹路径添加到 path 环境变量中。

** 为 Eclipse 关联 SDK :

Window à Preferences ,然后如图:


点击 “ Browse ”选择 SDK 所在的路径,注意是跟目录

** 关联 Android 源码,特别是 Android 学习,通过看源码,能解决很多学习上的问题。对学习有非常大的帮助。 很快你们就发现,安装传统的方式,是无法关联 Android 源码的。幸好某某大婶研究出了一个方案,就是对应版本的开发包下面新建一个 sources 目录,然后将你下载的源码仍在里面。例如,我下载了一份Android 2.2 的源码 ( 网上淘的,只是一些常用的类库啊之类的,不是全部的,全部的据说有几个 G ) ,那么,我需要在 platforms/android-8/ 这个目录下新建一个 sources 目录 ,将解压开的源码扔进去。

4. 写一个 HelloWorld 程序

** 没多少步骤,只需要新建一个 Android 项目就可以,点击 “ New ” --- “ Android Project ”,在非“ Java ” 透视图下,你可能需要点击 “ Other ”,到创建向导中的 “ Android ”目录下,才能选择到 “Android Project ”,具体细节如图:





5 .项目虽然刚刚才创建出来,其实我们的 HelloWorld 程序就已经写好了。 Android 项目创建出来以后,什么都不用做,直接部署到手机上,就能够看见 “ Hello World! ”。

那么这个项目怎样才能运行得起来呢,你也可以将他不部署到真实手机,但是一般情况下,我们用 Android提供的模拟器就可以完成应用程序的初步测试了。

6. 创建模拟器,点击图标:


在模拟器列表界面,点击 New ,进入到创建向导:



创建了之后,将回到模拟器列表页面,选中创建的模拟器,点击“ Start ”,再在弹出界面中点击“Launch ”,如图: :



7 . 怀着虔诚的心态等待模拟器启动,若迟迟不见动静,则找到占用端口号为 “5544” 的进程, Kill 丫的。,启动成功后,将看到模拟器界面,如图(忘了写模拟器编程汉语环境了,简单步骤为,进入。。。额。。欢迎使用google和baidu):



8 .下面部署我们的 HelloWorld ,选中项目,右键点击“ Run As ” — “ Android Application ”

9. 等候运行结果,查看模拟器,运行后,模拟器画面为:



9 .解析以及说明项目目录结构:

粗略的看几个文件夹:

“ src ”当然是用来存放源文件的。

“ res ”肯定是“ Resources ”的缩写,一个良好的 Android 应用程序,应该要尽量将所有应用中用到的资源,如图片, XML 配置,甚至包括字符串等等,都存放在这个文件夹底下统一管理。

“ gen ”下是一些由系统控制的资源,例如 R 文件,或者后面笔记中接触到的 AIDL 实现服务之间的进程通信时所自动产生的类文件。它们不由我们控制。

然后再来细看它们底下的子文件夹和文件:

先来看“ gen ”下的“ R.java “ 。这个文件如果你尝试着去更改它,会发现是无效的。并且它默认是存放在与应用包名相同的包下面的,尝试去移动它也必将失败。因为它不由我们管理。每当我们在“ res ”文件夹及其子文件件下添加一个资源时,然后刷新 R 文件 ,都会发现它会生成一个变量名和资源文件名相同的静态变量。再结合“ res “文件夹的意义,我们不难猜出这个 R 文件就是访问“ res ”文件夹下的资源的索引集合 。只要是在“ res ”下的资源,我们都能通过 R 文件 访问到。这个类的代码为:

public final class R {
public static final class drawable {
public static final int icon=0x7f020001;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}





可以看到,它的机制类似于这样,每一个 res 目录下的子目录都对应 R 这个类 中的一个静态内部类(drawable-hdpi 等三个对应一个 drawable 类)。

例如, layout 文件夹下我们观察到有一个 main.xml 文件,于是观察 R 文件,果然是有一个 layout 内部类,它里面又有一个 main 静态变量。

那么是不是我们通过 R.layout.main 就可以访问到 main.xml 呢。因为我们的分析结果不是 R 文件里的变量都是到某一个具体资源的索引么 ? 完全正确!说 R.java.main 可以访问到 main.xml 完全没问题。只不过这个访问是由 Android 内部完成的。

相当于送快递一样,寄的人给个地址,说送到某某某地某某街某某门牌某某公司某某人,因为这个地址足够详细,所以快递很快找到目标,然后完成任务。

那么 Android 为什么要采取这种机制呢?将应用的资源与应用本身剥离,有什么好处?我觉得首先有一个好处就是,加载资源这一行为由 Android 来做,它肯定比程序员更了解该怎样来管理这个资源 ,例如,资源过大,不能持久保存、资源很小,我加载在内存里,先保存着,下次有人用的时候,我再拿出来。操作系统本身最了解自己的内存状态和运行效率 ,因此,它也更会管理内存和优化软件的运行效率。个人看法。

AndroidManifest.xml 文件

这个文件我将他看成应用的功能清单,类似于 struts 中的 struts-config.xml 。每当我们要到一种组件时,总是要现在这个文件中声明(或者说注册)。它初始时就默认定义了应用的一些基本属性,文件内容为:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wjh.android.helloworld"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>


先介绍跟元素 manifest ,这是站在整个程序角度来描述整个应用,此元素内部可以声明组件,申请权限等等,其属性:
xmlns:android :命名空间,这没什么说的,照着写就是了。
package :应用所在的包,包名要尽量避免大众化——我的意思是,要尽量降低你的应用和世界上其它应用包名相同的情况。因为当应用安装软件到手机后,包名将作为操作系统的进程名。这个应用包名仿佛承载着区别应用与应用的一个标志。只要遵守一般 Java 项目中的包命名规范,这种情况应该也很少,就算有,让这本来几率就低的两个软件正好运行在同一部手机上,几率更是直逼彩票获奖率。
而且也许 Android 有处理这种问题的机制,我还在查。
android:versionCode :应用的版本号,默认为 1
android:versionName :版本名称

application :此标签用来描述应用中的组件声明和应用的全局属性。此标签只能有一个。
android:icon :应用的图标: @drawable/donkey 这个表达式将在后面进一步说明。
android:label : @string/app_name 对应了一个字符串,也可以给这个标签直接写上一个字符串,如“宇宙级五子棋”等。这个属性设置的值,将出现在用户的手机软件标题上,例如用户安装了你的软件,那么他的软件列表里就将出现你的软件,那么显示的软件名称就是这家伙。这个值还将默认作为主窗口的默认标题。

Activity 标签 :一个 Activity 通常表现为软件上一个单独的屏幕界面,它们或者独占软件的整个屏幕,或者被改造为一个对话框。它通常对应一个继承了 Activity 的类,因此,若我们要新建一个窗口,一个办法是新建一个类,继承 Activity ,再将此 Activity 照猫画虎注册在本 XML 文件中,并在合适的实际,激活它就可以了。
Activity 这个名字乍看有点怪,起个名字叫“活动“,明明就是一个界面嘛。
其实这是另一个角度的抽象,我们想,其实一个程序,不就是一个“大的活动”么,这个“活动”里又包含了多个“子活动”。
那么 Android 将一个通常作为窗口这样一个控件称之为“活动”,那么,肯定是将它看做一个“活动”的容器,它可以承载很多活动。
例如,“鼠标点击”,“键盘按下”等等。或者从另一个角度,例如“用户输入数据”、“用户想看一个对话框”、“用户想把一个控件拖动一下”等等活动。这些活动都是发生在“窗口”上的,或者是通过“窗口”来触发的(其实这种情况下,也可以看成是窗口在处理活动,只是它调用了另一个控件来辅助而已)。于是,从这个角度来看,将这个控件取名为 Activity 再合适不过了。

android:name :这个属性指定 Activity 的类名。 ”.MainActivity” 中的 “ . ” ( 点 ) 就表示当前应用的包名,也就是 manifest 标签的 package 属性的值: wjh.android.helloworld 。这样 ”.MainActivity” 就成了:wjh.android.helloworld.MainActivity ,查看“ src ”文件夹下,发现果然存在这个包和这个类。
试验表明,此处可以直接写成 “ MainActivity ” ( 扔掉前面的点 ) ,这是一种特殊情况,因为这个类刚好在wjh.android.helloworld 包下面。
另外,试验也表明,将这里直接写成: wjh.android.helloworld.MainActivity 类的完整路径也是可以的。
最可怕的是,将这个 Activity 类,定义在一个与应用包名完全不相关的包下面,如“ aa.bb.cc ”,然后将这里改成 “ aa.bb.cc.HelloActivity ”居然也是可以的。我发誓在两分钟之前,我一直觉得是不可以的。现在想想为什么我会这么觉得呢——经验和思想带出的直觉而已。直觉真可怕。
android:label :既然上面分析 Activity 可以看着一个屏幕窗口,那么,这个窗口也应该有标题,此属性设置的值将作为窗口的标题。这里可以直接写上想显示在窗口上的标题的字符串。
intent-filter: 我现在觉得我不该这样一个个说,好像泄露了很多不该在 HelloWorld 中说的话题。这个标签有体现了一个 Android 的设计思想,它将用户与软件组件之间、组件与组件之间的交互行为抽象为 Intent (意图)。很形象也很抽象。
例如,用户想看到另一个窗口,于是他点击了现在的窗口的 “ Open New Window ”,另一个窗口打开了。这其中,经历了一个转换,就是程序,将用户的“意图”转换成了程序能描述出来的、并能执行的指令。
这个转换最后就成了,“将现在的 Activity( 现在的窗口 ) 切换到另一个 Activity( 用户想看到的新的窗口 )”。处理方式就是,将现在的 Activity 关闭掉或者暂停掉,然后激活另一个 Activity —— Android 只允许应用程序中同时最多存在一个正激活的 Activity 。由此转换,成功破译用户的需求,并执行成功。
这有一个问题。想想 struts 里面,当 ActionServlet 接收到用户的请求,表达了要连接到一个 Action 时,它是怎么处理的——它需要解析 ActionMapping ,得到 path ,再得到 Action 。这里的 path ,相当于提供了外界访问到此 Action 的一种途径。
我想要说的问题是,用户说:“我想要看到一个显示最新新闻列表的窗口,快给我”。
程序破译后,要停止现在的 Activity 而打开一个新的 Activity 。但是它如何知道要打开哪一个 Activity 才能满足用户的 “最新新闻列表的窗口”需求呢?或者就算我们知道,可是要如何连接到这个 Activity 呢?写死?当然可以。但是太笨,太不灵活。这样的软件,没有持久生命力。
那么 struts 是通过 path 来找到 Action 的。 Android 是通过什么来找 Activity 的呢(这里我们只讨论 Activity,其实这套机制同样适用于 Android 的其它组件)?就是 Intent !意图!
那么上面的这段配置:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
就是定义了一个对 Activity 的访问规则。既然 Activity 是通过意图来实现激活的,那么,很显然要说明的是,哪些意图才能够激活我?这就有点过滤器的概念了,过滤掉不能访问我的意图,或者不是准备访问我的意图。这里这段意图过滤器就是说明:当一个 Intent 以“ android.intent.action.MAIN ”作为 action( 动作 ) 名称的、并且以“ android.intent.category.LAUNCHER ”作为 category( 类别 ) 名称的时候,这个时候,他将被我的 ( 当前intent-filter 的 Activity)
Filter 截获,并允许它激活我。
(我希望我说清楚了。因为这个机制很重要。现在不明白,建议在一个月后再回头来看,也许会发现我的说法有误,请一定发邮件告诉我)。

理清楚这个机制以后,我们应该能明白为什么这个 “ MainActivity ”可以作为启动窗体? 一定是 Android内部弄出了一个 Intent ,然后让这个 Intent 的 action 等于“ android.intent.action.MAIN ”,并设置它的category 为“ android.intent.category.LAUNCHER ”。于是这个 Intent 满足了被 MainActivity 截获 (或者说识别?或者说接收?反正你能明白这个意思就好)到的条件
其内部判断是哪一个 Activity 已经满足条件啦?是 “ ManActivity ”呗,于是启动它,就让他作为应用显示的第一个窗口,做为主窗口!因此,又额外得出一个结论,若想让一个 Activity 成为主窗口,只需要定义它的intent-filter 为上面两项就可以了 —— 因为, Android 内部就是在匹配这两项。
这样,也许我们能看到, intent-filter 的好处之一。就像 struts 一样, ActionServlet 只知道:http://localhost:8080/android/intent.do 这个请求,要找 Path 为 “ /intent.do ”这个 Action 去处理。但是它不关心这个 Action 是谁,类名是什么。不关心,这个由你配!

Intent 也一样,它的机制之一是可以不关心将连接到的 Activity 是谁,并且能够激活这个组件。

好了,这里同样可以这么干。我不是要启动一个窗口么?如果我的程序要足够灵活,就是说我要让我具体启动哪一个窗口(激活哪一个 Activity )可配。
我就可以借鉴这种方式,给这个要启动的窗口 (Activity) 定义一个 intent-filter ,说,只要你在程序中表示出 action 为 “aaa” 就行了,我就知道你要启动我这个 intent-filter 对应的 Activity 啦:

<activity android:name=".NewActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="aaa" />
</intent-filter>
</activity>


于是程序中,当你需要打开 NewActivity 这个屏幕窗口时,只需要:

Intent intent = new Intent();
intent.setAction("aaa");
startActivity(intent);


这几行代码细节读者若没有这些经验可以不比理会,只需要知道,这里通过一个 “ aaa ”就激活 “NewActivity ” 这个窗口啦!我要是以后对程序改动,想让这个窗口更换为 NewActivity222 ,只需要该配置就可以啦:

<activity android:name=" .NewActivity222"
android:label="@string/app_name">
<intent-filter>
<action android:name="aaa" />
</intent-filter>
</activity>


Android 底层一定有个机制,实现了,根据 Intent 的 “ aaa ” 找到 “ .NewActivity222 ” 。有 MVC 经验的人,或者有 struts 经验的人可能更深刻,这不是控制器么?!
这整个过程,不是 MVC 模式么?!
实际上就是这样的,我说这么多不该在 HelloWorld 中说的话,就是想说这个意思!
J2EE 的兄弟们!咱们回老本行啦!
( 忽然想: R.java 这个文件好像也和这个模式占点边了。 )
这只是 Intent 的特点之一,它与 struts 的 path 还是有区别的 , 于是引出第二大特点 。 path 的值是一个简单的字符串。而此处是一个复杂的 Java 对象,这意味着,它可以携带数据 。例如,当我要修改员工的信息时,是不是要在一个页面中跳转到另一个页面呢?并且传入要修改的员工的 id 。在 Android ,这个 id 怎样从一个组件传递到另一个组件呢?很简单,我们不是依靠 Intent 来联系的么? Intent 不是一个 Java 对象么?那么好,我在设计 Intent 的时候就考虑到这样一种情况,给 Intent 设计一个用于携带数据的属性,当需要两个页面交互数据时,通过向 Intent 的这个属性存取参数即可。

接着说目录下的其它文件:
values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HelloActivity!</string>
<string name="app_name">Hello Word</string>
</resources>


这个文件首先有点意思的是,我们观察知道: stringx.xml 这个文件最终在 R 文件中对应了一个名为string 的内部类。并且每一个有效的 <string> 标签,对应其内部的一个常量。
那么上文中我在描述“大概目录结构”时的说法是有误的 ,我说, res 目录下的子目录都对应了 R 文件的一个静态内部类。应该说这个情况在大多数时候是这样的,但是在 values 文件夹却除外 (并不严谨,因为我没有做很仔细的实验,有可能还有其它情况也排除在外)。首先我们并没有看到在 R 类中新添加一个 values子类。哦,那么它肯定是用文件名来做为静态内部类的类名的 ~~~ 额,可是,我这个文件名叫 strings 也,而 R文件中对应的内部类却是 string 。如果说这个还不能说明问题的话,那么我们再在这个文件夹下新建一个文件,右键 — 新建 Android
XML File ,然后选择文件类型为 Values —— 这文件夹下只能放这种类型的 XML 文件,其实也就是,这个文件夹下,只能放以 <resources> 作为根元素的 XML 文件。
于是我们新建一个 aaa.xml 的 values 文件,打开看,果然自动添加了一对 <resources></resources>。
那按照我们的猜想, R 文件中,应该产生一个 aaa 的内部类吧。打开一看,希望落空,没有这东西。
那么我们在 aaa.xml 中写点东西吧,也许是没有东西才没生成呢?
于是我们写一对 : <string name="ns">sss</string>
再看 R 类。还是没有 aaa 这个类。那 ns 这个定义的字符串资源哪去了呢?——跑到 string 里面去了。
我觉得我这说得有点偏了,于是直接说结论吧: values 下只能放 Values 这种类型的 XML 文件,也就是说,此文件夹下虽然有多少个 xml 文件不确定,但是有几种标签是确定的,因为他们都是 <resources></resources> 的子元素嘛, Android 规定了其下面只能有八种标签(但是 Item 除外),都是用来定义一些常量的。例如颜色值,样式等等。
实际上是每一种标签对应一个静态类,比如,我们在 aaa.xml 写上一对:
<color name="dialog_back">#330000FF</color>
看 R 文件,马上发现生成了一个 color 类。当写第二个这种标签时,就只是在原有基础上添加常量,不会新建类。其它六种都是这样。
为什么 Item 标签除外呢,它干的事吧,我写一段大家就明白:
<item type="string" name="nihao"> 您好 </item>
<item type="string" name="c1">#7f040000</item>
这种写法,同样会在 R 类的 string 和 color 中添加两个新的变量。
有什么用呢?倒确实会在有时候用到,例如我们可以这样写:
<item type="cus" name="My"> 我自己分类的资源类型 </item>
查看 R 文件,发现新建了一个 cus 类。
这是我至今发现的唯一一个能自己在 R 中添加静态类的方法。

layout/main,xml : 界面布局文件

<?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"
/>
</LinearLayout>


<LinearLayout> :布局方式——线性布局。关于几种布局的详细情况请参看文档:



<TextView>: 相当于 html 中的 <label> 标签,显示一段文本。
android:layout_width="fill_parent" :控件宽度为填充父元素,在这里,父元素就是整个屏幕,所以就是满屏宽。
android:layout_height="wrap_content" :控件高度为包裹内容,就是刚刚好能够满足内容正常显示的高度。

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}


这里是自定义一个 MainActivity 继承了 Activity 。表示这是一个可当做窗口展示的控件。并且我们希望它作为启动窗口,于是在定义它的配置文件里,为他定义了一个意图过滤器。
但是,这个控件到底怎样显示东西呢?
首先:
onCreate 方法:表示 Activity 已经准备就绪,只差显示了,这个时候系统会自动调用这个方法,因此它不由程序员管理。这个方法在 Activity 的整个生命周期内只会被调用一次。但是,这时候 Activity 还一片空白,什么也没有,我们希望让它能显示一个我们定义的界面,在这个时机就加上去最合适不过。于是:
调用 setContentView() 方法,这个方法能为整个 Activity 设置一个界面。而,这个界面被我们定义在了 layout/main,xml 里面了,怎样才能访问这个文件呢 ? 显然是 R.layout.xml ——注意此处的 R 是我们自己应用下的 R 类。系统本身也有这样一个类,因此,使用的时候,要按包名区分清楚。
于是 setContentView(R.layout.main); 这句代码的意思再清楚不过,就是将 main.xml 定义的内容,作为 MainActivity 的界面。

貌似终于要完了,但是我紧记还有一点很重要,就是如何在 XML 中访问 R 文件,其实在上面我们已经多次接触到了,第一处:
AndroidManifest,xml 中
< application> 节点的: android:icon="@drawable/icon"
它的意思表示访问 R. drawable.icon ,对应了 drawable 下面的一个 icon 图标文件
android:label="@string/app_name"
它的意思表示访问: R.string.app_name ,对应了 strings.xml 中的一个字符串
main,xml 中
< TextView > 的 android:text="@string/hello"
它表示访问 R.string.hello ,也就是字符串“ Hello World, HelloActivity! ”,这也是为什么我们能什么代码也不写,就在模拟器屏幕上看到这样一个字符串了。
总结:很重要。 @string/hello 中: @ 表示应用中的 R 文件, @string 就表示 R 文件下的 string内部类, / 表示访问其内部元素, hello 就是 R 文件下的 string 内部类里面的 hello 静态变量。这个表达式我们将用得很频繁 .

还有一个,有几个目录 :
drawable-hdpi :用于存放高分辨率的图片。
drawable-ldpi :用于存放低分辨率的图片。
drawable-mdpi :用于存放中等分辨率的图片。
它们对应 R 中的 drawable 子类。
为什么要有这样的区分。因为手机的特殊性,款式不同,它的分辨率差别可能很大:有的屏幕很小,有的很大。我需要能灵活的自动适应这种情况。
于是就把分辨率不同的但是文件名相同 的几幅图片分别存放在对应分辨率等级的文件夹下 ,例如,我们打开这几个文件夹,可以看到系统自带的 icon.png 图片,它作为了应用的图标。 Android 内部会自动根据用户手机的分辨率而挑选适合的图片挂上去。这也是将资源交给 Android 统一管理的另一个好处,它比我们更懂每个用户的手机特征 ,因此只有它最适合完成屏幕适配和国际化。这里就是屏幕适配。
这个机制不但适用于图片,还适应于所有 res 目录下的资源。例如新建 layout-320x240 文件夹,就表示此文件夹下的界面文件,适配 320x240 这种分辨率的手机。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: