首页 Android 学习(通俗易懂)

Android 学习(通俗易懂)

举报
开通vip

Android 学习(通俗易懂) Android 学习笔记(1)-永远不变的 Hello World Google 的 Android SDK 发布也有一段时间了,一直想研究一下却苦于找不到时间。利用这个周未,开始强迫自己再次进入学习状态,原因很 简单:我看好开放的 gPhone。 SDK 的下载与安装并不复杂,网上也有不少同学已经进入状态了,我就不再重复了吧。 今天主要讨论的,还是永远不变的话题:Hello World. 1.最简单的 HelloWorld 安装了SDK后,直接生成一个Android Project,一句代码不用...

Android 学习(通俗易懂)
Android 学习笔记(1)-永远不变的 Hello World Google 的 Android SDK 发布也有一段时间了,一直想研究一下却苦于找不到时间。利用这个周未,开始强迫自己再次进入学习状态,原因很 简单:我看好开放的 gPhone。 SDK 的下载与安装并不复杂,网上也有不少同学已经进入状态了,我就不再重复了吧。 今天主要讨论的,还是永远不变的话题:Hello World. 1.最简单的 HelloWorld 安装了SDK后,直接生成一个Android Project,一句代码不用写,就能跑出一个最简单的HelloWorld例程。我们看一下它的代码: public void onCreate(Bundle icicle) { super.onCreate(icicle); setTheme(android.R.style.Theme_Dark); setContentView(R.layout.main); } 看上去实在很简单,只有两句话而已。关键在这个R.layout.main上,凭直觉,这应该是定义的资源。的确,在R.java中只是定义了一个static int 而已,真正的资源描述在res/layout/main.xml文件里(注意:这里的R.java不要手工 编辑,每次build project时它都会根据res下的资源描述被自动修 改)。 这个文件很好读,一个描述了这是一个线性排列的布局,android:orientation=vertical 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示所有组件将纵向排布。而经典的Hello World是用一个 TextView来展示的。 由此,我们知道,Android 的程序从一个 Activity 派生出来,并且从它的 onCreate 开始启动;Android 里要显示的组件用 XML 文件描述而不用 在代码中硬编码(这是一个好的习惯,我们应该从一开始就坚持下去); 2.让 Button 来说 Hello World 上面的例子是 ADT 自动生成的代码,似乎与我们一点关系也没有。那我们来改一下代码,因为在 windows 平台上的 Helloworld 经常是由一个按钮 触发的,所以,我们想第二个 Helloworld 应该是这样的:加一个按钮和文本输入框,单击按钮后在原来的 TextView 后面加上输入框中输入的文 字。 第一步是,增加一个 Button 和一个 EditText,与 TextView 一样,它们也在 main.xml 里描述一下: 这里有两个地方要注意:id=@+id/go,这表示需要一个唯一的 UID 来作为 Button 的 ID,它的引用名是 go。还有一个是 android:text=@string/go 表示这个按钮的文本不是直接写有 main.xml 里了,而是来源于另一个资源描述文件 strings.xml 里,本例中的 strings.xml 如下: helloTwo 提示 你好,中国 确定 浏览 然后,在代码里(onCreate 函数中)我们加上以下代码(简单起见,用了嵌套类): Button btn = (Button)findViewById(R.id.go); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { EditText edt=(EditText)helloTwo.this.findViewById(R.id.edt); TextView txt= (TextView)helloTwo.this.findViewById(R.id.txt); txt.setText(getString(R.string.msg_dialog)+edt.getText()); } }); 为铵钮增加一个 onClick 事件处理器,在点击事件中,设置 txt 的文本为 R.string.msg_dialgo+edt.getText()。 这里的关键是两个函数的使用: findViewById(R.id.go)可以根据资源的名称加载 View 类型的资源,同样用函数 getString(R.string.msg_dialog)可以加载字符串资源。 编译,run 一下看看效果。 3. 再让菜单 Say Hello 从 API 文档中我们看到 Activity 中有两个函数:onCreateOptionsMenu 和 onOptionsItemSelected,显示,这个 OptionsMenu 就是所谓的上 下文菜单(在 GPhone 的模拟器上,有个键专用于弹出这个菜单)。下面我们就为这个 HelloWorld 例子加上一个菜单,并且让它可以 Say hello。 这次,我们不涉及到资源的描述文件了,而是直接使用这两个函数来实现,其实代码也很简单,所以,我们再增加一个退出应用的功能(否 则每次都是按取消键退出应用显示太不专业了)。 代码如下: public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0,1,"say hello"); menu.add(0,2,"exit"); return true; } public boolean onOptionsItemSelected(Item item) { super.onOptionsItemSelected(item); int id = item.getId(); switch(id){ case 1: AlertDialog.show(this,getString(R.string.app_name), getString(R.string.msg_dialog), getString(R.string.ok_dialog), true); break; case 2: finish(); break; } 在 CreateOptionsMenu 时,我们简单地增加两个菜单项,menu.add(组 ID,项 ID,显示文本),(注意:这里我直接将文字写在代码里,这并不 提倡)。然后,在 OptionsItemSelected 事件中,我们根据选中的菜单项做相应处理,如果选中 1,则弹出一个对话框显示资源文件中的“你好, 中国”,如果选中 2则退出应用。 AlertDialog.show 是一个静态方法,类似于我们在 WIN 平台上经常使用的 MessageBox 一样,很方便的。 来源:http://www.sf.org.cn/Android/lumen/20976.html Android 学习笔记(2)-初识 Activity 根据文档的解释,Activity是Android开发中非常重要的一个基础类。我把它想像成J2ME中的Display类,或者是Win32平台上的Form类,也许 不准确,但是它的重要性我觉得应该是一样的(当然,如果我们写的是一个没有界面的应用,例如后台运行的服务之类的,可以不用Display的)。 1. 在一个 Activity 中使用多个 View 如果把Activity看作MVC中的Control?它负责管理UI和接受事件(包括用户的输入),虽然说一个Activity通常对应一个屏幕,但事实上, 我们是可以只用一个Activity管理多个不同的View来实现简单的逻辑。 首先,我们增加一个新的资源描述layout/second.xml。 除了一个“Hello 中国”以外,增加一个按钮可以返回前一个界面。然后,在代码中我们要为 helloTwo 增加两个方法,setViewOneCommand 和 setViewTwoCommand,分别处理一下在不同界面时,从资源里加载组件并为组件绑定一个事件处理器。 public void setViewOneCommand() { Button btn = (Button)findViewById(R.id.go); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { helloTwo.this.setContentView(R.layout.second); helloTwo.this.setViewTwoCommand(); } }); Button btnExit=(Button)findViewById(R.id.exit); btnExit.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ helloTwo.this.finish(); } }); } public void setViewTwoCommand() { Button btnBack=(Button)findViewById(R.id.go2); btnBack.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ helloTwo.this.setContentView(R.layout.main); helloTwo.this.setViewOneCommand(); } }); } 最后,我们需要在 onCreate 的时候,也就是启动后的 main 界面上设置一下按钮事件处理器。新的 onCreate 方法如下: public void onCreate(Bundle icicle) { super.onCreate(icicle); setTheme(android.R.style.Theme_Dark); setContentView(R.layout.main); setViewOneCommand(); } 编译,运行,OK。 2. 还是回到正道上,多个 Activity 之间的跳转 Android 中提供一个叫 Intent 的类来实现屏幕之间的跳转,按文档的说法,似乎他们也建议采用这种方法,Intent 的用法比较复杂,现在我 先看看它最简单的用法。 先在应用中增加两个Activity,这需要修改AndroidManifest.xml文件了,如下: 很简单,就是加一个 标签而已,新标签的class是.HelloThreeB,显示的应用标题与前一个Activity一样而已,然后第二步就是修改一个 HelloThree类的实现,在onCreate方法中绑定按钮的事件处理器: public void onCreate(Bundle icicle) { super.onCreate(icicle); setTheme(android.R.style.Theme_Dark); setContentView(R.layout.main); setViewOneCommand(); } public void setViewOneCommand() { Button btn = (Button)findViewById(R.id.go); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(); intent.setClass(HelloThree.this, HelloThreeB.class); startActivity(intent); finish(); } }); Button btnExit=(Button)findViewById(R.id.exit); btnExit.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ HelloThree.this.finish(); } }); } 这里的跳转 功能用Intent来操作,它的最简单用法就是用函数setClass()设置跳转前后两个Activity类的实例,然后调用Activity自己的 startActivity(intent)即可。最后一句finish()表示将当前Activity关掉(如果不关掉会如何?你可以自己试一下看效果,事实上有时我们是不 需要关掉当前Activity的)。 然后,我们同样弄一个 Activity 类 HelloThreeB,代码与前面的差不多,只是将 setClass 的两个参数反一下,这样就可以简单地实现在两个 Activity 界面中来回切换的功能了。 3. 如果我想在两个 Activity 之间进行数据交换,怎么办? 前例中的 startActivity()只有一个参数,如果需要向新打开的 Activity 传递参数,我们得换一个函数了, Android 提供了 startSubActivity(Intent,int)这个函数来实现这个功能。 函数原型为: public void startSubActivity(Intent intent, int requestCode) 这里的 requestCode 用来标识某一个调用,一般由我们定义一个常量。 如何把参数传过去呢?Intent 类在提供 setClass()函数的同时也提供了一个 setData()函数。 函数原型为:public Intent setData(ContentURI data) 参数类型是 ContentURI,它的详细内容下回再分析,现在就把它当成一个 String 类型来用吧。 参数带到新的 Activity 后,同样用 Activity.getIntent()函数可以得到当前过来的 Intent 对象,然后用 getData()就取到参数了。 把参数带回来的方法是 Activity.setResult(),它有几个形式,现在先看最简单的一个吧。 函数原型是:public final void setResult(int resultCode, String data) resultCode 是返回代码,同样用来标识一个返回类型,而 data 则是它要返回的参数。 在原来的Activity中的事件处理回调函数onActivityResult,会被系统调用,从它的参数里可以得到返回值。 函数原型为:protected void onActivityResult(int requestCode, int resultCode,String data, Bundle extras) 这里的 requestCode 就是前面启动新 Activity 时的带过去的 requestCode,而 resultCode 则关联上了 setResult 中的 resultCode,data 是参数, extras 也是一个很重要的东西,后面再研究一下它的作用。 下面,我们来看一下代码吧,先看看 HelloThree 中的代码: public void setViewOneCommand() { Button btn = (Button)findViewById(R.id.go); btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { Intent intent = new Intent(); intent.setClass(HelloThree.this, HelloThreeB.class); intent.setData(new ContentURI("One")); startSubActivity(intent,REQUEST_TYPE_A); } catch(Exception ex){} } }); Button btnExit=(Button)findViewById(R.id.exit); btnExit.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ HelloThree.this.finish(); } }); } protected void onActivityResult(int requestCode, int resultCode, String data, Bundle extras) { if (requestCode == REQUEST_TYPE_A) { if (resultCode == RESULT_OK) { Log.v(TAG,data); TextView txt = (TextView)findViewById(R.id.txt); txt.setText(data); } } } 这里的 REQUEST_TYPE_A 是我们定义的一个常量。在 onActivityResult 中用它与 RESULT_OK 一起作为条件判断如何处理返回值,这里只是简 单将 TextView 显示值换成传来的字串。 再来看看另一个 HelloThreeB 类的实现代码: private Intent i; protected void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.second); i = getIntent(); android.util.Log.v(TAG,"onCreate"); Button btn = (Button)findViewById(R.id.go); btn.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ String result=HelloThreeB.this.i.getData().toString()+" And Two"; HelloThreeB.this.setResult(RESULT_OK,result); finish(); } }); TextView v = (TextView)findViewById(R.id.txt); v.setText("Param is "+i.getData().toString()); } 在按钮处理事件中,从 Intent 取出参数,处理一下再用 setResult 返回给前一个 Activity 即可。 编译运行即可。 来源:http://www.sf.org.cn/Android/lumen/20977.html Android 学习笔记(3)-Activity 的生命周期 注意到在Activity的API中有大量的onXXXX形式的函数定义,除了我们前面用到的onCreate以外,还有onStart,onStop以及onPause等等。从 字面上看,它们是一些事件回调,那么次序又是如何的呢?其实这种事情,自己做个实验最明白不过了。在做这个实验之前,我们先得找到在Android 中的Log是如何输出的。 显然,我们要用的是 android.util.log 类,这个类相当的简单易用,因为它提供的全是一些静态方法: Log.v(String tag, String msg); //VERBOSE Log.d(String tag, String msg); //DEBUG Log.i(String tag, String msg); //INFO Log.w(String tag, String msg); //WARN Log.e(String tag, String msg); //ERROR 前面的 tag 是由我们定义的一个标识,一般可以用“类名_方法名“来定义。 输出的LOG信息,如果用Eclipse+ADT开发,在LogCat中就可以看到,否则用adb logcat也行,不过我是从来都依赖于IDE环境的。 好了,现在我们修改前面的HelloThree代码: public void onStart() { super.onStart(); Log.v(TAG,"onStart"); } public void onStop() { super.onStop(); Log.v(TAG,"onStop"); } public void onResume() { super.onResume(); Log.v(TAG,"onResume"); } public void onRestart() { super.onRestart(); Log.v(TAG,"onReStart"); } public void onPause() { super.onPause(); Log.v(TAG,"onPause"); } public void onDestroy() { super.onDestroy(); Log.v(TAG,"onDestroy"); } public void onFreeze(Bundle outState) { super.onFreeze(outState); Log.v(TAG,"onFreeze"); } 在HelloThreeB中也同样增加这样的代码,编译,运行一下,从logcat中分析输出的日志。 在启动第一个界面Activity One时,它的次序是: onCreate (ONE) - onStart (ONE) - onResume(ONE) 虽然是第一次启动,也要走一遍这个 resume 事件。然后,我们点 goto 跳到第二个 Activity Two 中(前一个没有关闭),这时走的次序是: onFreeze(ONE) - onPause(ONE) - onCreate(TWO) - onStart(TWO) - onResume(TWO) - onStop(ONE) 说明,第二个 Activity Two 在启动前,One 会经历一个:冻结、暂停的过程,在启动 Two 后,One 才会被停止? 然后,我们再点 back 回到第一个界面,这时走的次序是: onPause(TWO) - onActivityResult(ONE) - onStart(ONE) - onRestart(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO) 说明,返回时,Two 没有经历冻结就直接暂停了,在 One 接收参数,重启后,Two 就停止并被销毁了。 最后,我们点一下 Exit 退出应用,它的次序是: onPause(ONE) - onStop(ONE) - onDestroy(ONE) 说明如果我们用了 finish 的话,不会有 freeze,但是仍会经历 pause - stop 才被销毁。 这里有点疑问的是:为什么回来时先是 Start 才是 Restart?可是文档中的图上画的却是先 restart 再 start 的啊?不过,后面的表格中的描述好 象是正确的,start 后面总是跟着 resume(如果是第一次)或者 restart(如果原来被 stop 掉了,这种情况会在 start 与 resume 中插一个 restart)。 下面不跑例子了,看看文档吧。 1.Android 用 Activity Stack 来管理多个 Activity,所以呢,同一时刻只会有最顶上的那个 Activity 是处于 active 或者 running 状态。其 它的 Activity 都被压在下面了。 2.如果非活动的Activity仍是可见的(即如果上面压着的是一个非全屏的Activity或透明的Activity),它是处于paused状态的。在系统内 存不足的情况下,paused状态的Activity是有可被系统杀掉的。只是不明白,如果它被干掉了,界面上的显示又会变成什么模样?看来下回有必 要研究一下这种情况了。 3.几个事件的配对可以比较清楚地理解它们的关系。Create与Destroy配成一对,叫entrie lifetime,在创建时分配资源,则在销毁时释放资源; 往上一点还有Start与Stop一对,叫visible lifetime,表达的是可见与非可见这么一个过程;最顶上的就是Resume和Pause这一对了,叫foreground lifetime,表达的了是否处于激活状态的过程。 4.因此,我们实现的Activity派生类,要重载两个重要的方法:onCreate()进行初始化操作,onPause()保存当前操作的结果。 除了 Activity Lifecycle 以外,Android 还有一个 Process Lifecycle 的说明: 在内存不足的时候,Android 是会主动清理门户的,那它又是如何判断哪个 process 是可以清掉的呢?文档中也提到了它的重要性排序: 1.最容易被清掉的是 empty process,空进程是指那些没有 Activity 与之绑定,也没有任何应用程序组件(如 Services 或者 IntentReceiver) 与之绑定的进程,也就是说在这个 process 中没有任何 activity 或者 service 之类的东西,它们仅仅是作为一个 cache,在启动新的 Activity 时可以提高速度。它们是会被优先清掉的。因此建议,我们的后台操作,最好是作成 Service 的形式,也就是说应该在 Activity 中启动一个 Service 去执行这些操作。 2.接下来就是 background activity 了,也就是被 stop 掉了那些 activity 所处的 process,那些不可见的 Activity 被清掉的确是安全的, 系统维持着一个 LRU 列表,多个处于 background 的 activity 都在这里面,系统可以根据 LRU 列表判断哪些 activity 是可以被清掉的,以及其中 哪一个应该是最先被清掉。不过,文档中提到在这个已被清掉的 Activity 又被重新创建的时候,它的 onCreate 会被调用,参数就是 onFreeze 时 的那个 Bundle。不过这里有一点不明白的是,难道这个 Activity 被 killed 时,Android 会帮它保留着这个 Bundle 吗? 3.然后就轮到 service process 了,这是一个与 Service 绑定的进程,由 startService 方法启动。虽然它们不为用户所见,但一般是在处理 一些长时间的操作(例如 MP3 的播放),系统会保护它,除非真的没有内存可用了。 4.接着又轮到那些 visible activity 了,或者说 visible process。前面也谈到这个情况,被 Paused 的 Activity 也是有可能会被系统清掉, 不过相对来说,它已经是处于一个比较安全的位置了。 5.最安全应该就是那个 foreground activity 了,不到迫不得已它是不会被清掉的。这种 process 不仅包括 resume 之后的 activity,也包括 那些 onReceiveIntent 之后的 IntentReceiver 实例。 在 Android Application 的生命周期的讨论中,文档也提到了一些需要注意的事项:因为 Android 应用程序的生存期并不是由应用本身直接 控制的,而是由 Android 系统平台进行管理的,所以,对于我们开发者而言,需要了解不同的组件 Activity、Service 和 IntentReceiver 的生命, 切记的是:如果组件的选择不当,很有可能系统会杀掉一个正在进行重要工作的进程。 来源:http://www.sf.org.cn/Android/lumen/20978.html Android 学习笔记(4)-学习 Intent 的使用 刚看到 Intent 的时候,我的确有点困惑:从字面上来说,它表示一种意图和目的;从使用上看,它似乎总是用于 Activity 之间的切换;而 从它所在包 android.content 来看,它似乎与内容有关。所以,我想或许可以这样理解它: Intent 类绑定一次操作,它负责携带这次操作所需要 的数据以及操作的类型等。 如果是这样的话,是否可以将它与事件处理联想起来?即一个 Intent 类似于一个 Event。从 Intent 的两个最重要的成员操作类型(Action) 和数据(Data)来看,似乎是有道理的。文档中说,Intent的 Action的取值主要是一些定义好了的常量,例如PICK_ACTION,VIEW_ACTION,EDIT_ACTION 之类的,而 Data 则是一个 ContentURI 类型的变量,这一点,我们前面提到过。 而且文档中说Intent分为两大类,显性的(Explicit )和隐性的(Implicit)。在前面的例子中,我们在两个Activity之间跳转时初步使用 了Intent类,当时是用setClass来设置 Intent的发起方与接收方,它被称为显性的Intent,而隐性的Intent则不需要用setClass或setComponent 来指定事件处理器,利用 AndroidMenifest.xml中的配置就可以由平台定位事件的消费者。 一般来说,intent 要定位事件的目的地,无外乎需要以下几个信息: 1.种类(category),比如我们常见的 LAUNCHER_CATEGORY 就是表示这是一类应用程序。 2.类型(type),在前面的例子中没用过,表示数据的类型,这是隐性 Intent 定位目标的重要依据。 3.组件(component),前面的例子中用的是 setClass,不过也可以用 setComponent 来设置 intent 跳转的前后两个类实例。 4.附加数据(extras),在 ContentURI 之外还可以附加一些信息,它是 Bundle 类型的对象。 Implicit Intent 的使用相对有点麻烦,我们来做一个例子。首先,我们需要增加一个类:HelloThreeProvider,它必须实现于 ConentProvider 接口,所以代码如下: public class HelloThreeProvider extends ContentProvider { public boolean onCreate() { return true; } public int delete(ContentURI url, String where, String[] whereArgs) { return 0; } public ContentURI insert(ContentURI url, ContentValues initialValues){ return url; } public Cursor query(ContentURI url, String[] projection, String selection, String[] selectionArgs, String groupBy, String having, String sort) { return null; } public int update(ContentURI url, ContentValues values, String where, String[] whereArgs) { return 0; } public String getType(ContentURI url) { return "vnd.sharetop.hello.three/vnd.hello.three"; } } 这里面有一堆方法要实现,因为它们都是 ContentProvider 中的 abstract 方法,但是今天的例子中它们多半没有什么用处,只是一个 getType 方法我们让它不管什么 url 都返回一个表示 Intent 所携带的数据类型是我们定义的一个长字串:vnd.sharetop.hello.three/vnd.hello.three。 然后,在 AndroidMenifest.xml 中我们将上面这个 HelloThreeProvider 类加入应用程序: 相对于前面的例子,主要修改了 HelloThreeB 的配置,包括增加了一个标签表示这是一个一般性的 activity 而已。增加了 标签,定义它负责处理 VIEW_ACTION 类型的操作。增加了标签给出一个数据类型的定义串 vnd.sharetop.hello.three/vnd.hello.three。 最主要的是在下增加的那个标签,有个 authorities 属性,我们给的值是 cn.sharetop.android.hello,待一会我们再 说它的用处。 最后就是修改以前的跳转代码如下: Intent intent = new Intent(); intent.setData(new ContentURI("content://cn.sharetop.android.hello/one")); intent.setAction(intent.VIEW_ACTION); startActivity(intent); 现在我们的 setData 里的东西可与以前不一样的,是吧?注意到它的格式了吗?content://是个 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 头,固定这样写就行了。然后就是那个 authorities 中定义的串了,再后面就是我们自定义的东西了,我这里很简单的写个 one,其它还可以更长一点,如 one/101 之类的。它负责去关 联上那个provider类。另外,增加了setAction的调用设置操作为VIEW_ACTION,与Menifest中的又挂上了。Android平台负责根据Intent 的 Data 信息中的 authorities,找到 ContentProvider,然后 getTyp
本文档为【Android 学习(通俗易懂)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_815621
暂无简介~
格式:pdf
大小:315KB
软件:PDF阅读器
页数:29
分类:互联网
上传时间:2012-04-14
浏览量:31