android-Activity详解.doc_第1页
android-Activity详解.doc_第2页
android-Activity详解.doc_第3页
android-Activity详解.doc_第4页
android-Activity详解.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Activity详解1. 什么是Activity?Activity是一个应用程序组件,代表用来与用户进行交互的界面.比如,发邮件,拍照等的交互界面.一个应用程序通常由多个Activity松耦合的组成,典型的,当用户启动一个应用程序时见到的第一个交互界面(Activity)就叫做主Activity.当然,为了完成相应的动作,一个Activity可以启动另一个Activity;比如qq登陆界面,填写信息之后,发送一个信息去验证,通过之后就启动主界面Activity.每当启动一个新的Activity,前一个Activity将停止,但是系统将仍然保存这个对象在后台栈(back stack)里面。当启动一个新的Activity,它将被放入back stack中,并且获得用户焦点。Back stack遵循后进先出原则,所以当用户按手机上的back按钮时,当前的activity将会从back stack中移除,前一个Activity将被恢复。(Back stack请参考Tasks and Back Stack文档)。当然,Activity的创建,启动,恢复,暂停,停止,销毁都对应了一系列Activity的回调函数。2. 创建Activity。 创建一个Activity,需要继承Activity超类或继承自继承了Activity的子类。在你实现的子类中,你需要实现由系统在Activity状态发生变化时调用的各个回调函数。例如创建,暂停,停止等时会由系统调用对应的方法。这里介绍两个很重要的方法:onCreate() : 这个方法是必须实现的。当在创建一个Activity时候由系统调用。在该方法里面,你应当初始化一些组件;最重要的是,你必须设置setContentView()方法来设置activity布局。onPause() : 当你离开该activity时将被调用,在这个方法里你可以保存一些信息到数据库或文件等。一 实现用户界面。用户交互界面(Activity)由一系列由View衍生出来的类组成。每个view都占据activity窗口的一个矩形区域,并能产生相应的事件。比如button,当点击它可以产生点击事件等。你可以使用android提供的现成的组件来设计和组织你的布局。Widgets:通过屏幕产生视觉和互动效果的元素,比如按钮,文本框之类。Layouts:是一类通过ViewGroup派生的视图组件用来为放置在其中的其它view提供一个唯一布局,比如线性布局,网格布局,相对布局等。你也可以通过继承View和ViewGroup类或它们的子类来实现你自己的小部件和布局,并且把它们应用到自己的应用程序里的Activity里面。以XML文件来定义布局和使用View元素是最常用的方式,这些XML文件存放在你的应用的res目录下。通过这种方式,你可以把定义Activity的页面布局和Activity的行为分开来。你可以把资源文件所对应的ID通过setContentView()方法来设置UI的布局。当然,设置View元素与布局也可以在Activity代码里面创建。用户自定义接口(View 或 ViewGroup),参考User Interface文档。二 在manifest文件中定义activity元素。为了系统能够访问你的Activity,你必须在manifest文件中配置相对应于你Activity的activity元素,如下: . .三.使用intent filters在manifest文件中的activity元素可以通过元素指定不同的intent过滤器。它的作用是为了使其它应用程序(包括自身)组件可以访问该activity。假如你用Android SDK来创建你的android项目的话,你在manifest文件中可以看到一个intent-filter包含了一个响应的动作action和存放的类别category。文件如下所示: -Tip:元素指定这是应用程序的切入点,元素指定该activity应当被列入系统应用启动列表里,以便用户能够登入到这个Activity。通过上述表述,即如果你的应用程序都是由自己应用程序内的Activity访问或不允许外部应用访问你的Activity,那么就不需要配置这些多余的intent-filter(当然,如上所示的处代码是必不可少的,因为系统至少要有一个入口点才可以启动你的程序)。然而,如果你想隐式的启动Activity或别的应用程序访问你的Activity,那么你必须增加额外的intent-filter。想要了解更多的Intent or Intent-filter,参考文档Intents and Intent Filters。3. 启动Activity。通过startActivity(Intent intent)方法启动。Intent对象可以精确指定你要启动的Activity或者描述你要启动Activity的类型。当然Intent还可以传递少量的额外数据。一:当你仅设计在应用程序内访问Activity时,那么启动的方式如下,比如现在你要启动一个名叫SignInActivity的Activity。Intent intent = new Intent(this, SignInActivity.class);startActivity(intent);二:然而,当你的应用程序需要用到例如发邮件,写短信等功能时,但是你的应用程序本身不具备这个功能,所以,你可能会用到含有该功能的在该手机上的其他应用程序的Activity,那么此时就体现了intent的价值,你只要创建一个Intent,描述Intent想要执行的动作,那么系统就会自动去匹配该动作的Activity并启动之。Intent intent = new Intent(Intent.ACTION_SEND);intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);startActivity(intent);三:启动Activity并取得结果返回有时候你想接收从你启动的Activity返回的信息,那么此时就应当使用startActivityForResult()来代替 startActivity(),并且在接收返回信息的Activity里面重载onActivityResult()方法,该方法将接收并处理返回的信息。private void pickContact() / Create an intent to pick a contact, as defined by the content provider URI Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST);Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) / If the request went well (OK) and the request was PICK_CONTACT_REQUEST if (resultCode = Activity.RESULT_OK & requestCode = PICK_CONTACT_REQUEST) / Perform a query to the contacts content provider for the contacts name Cursor cursor = getContentResolver().query(data.getData(), new String Contacts.DISPLAY_NAME, null, null, null); if (cursor.moveToFirst() / True if the cursor is not empty int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name = cursor.getString(columnIndex); / Do something with the selected contacts name. 这个例子表述了你接收返回信息的基本逻辑。首先判断请求是否成功,如果成功的话,resultCode将被赋值为RESULT_OK,并且requestCode将与你在startActivityForResult(intent, PICK_CONTACT_REQUEST)方法里面的code相同,即同为PICK_CONTACT_REQUEST,如果都成立,那么你可以通过返回的Intent对象做相应的操作。Tip:ContentResolver参考Content Providers文档。更多Intent信息参考Intents and Intent Filters文档。4. 关闭Activity通过Activity的finish()方法来关闭本Activity;若是通过startActivityForResult (Intent intent, int requestCode)启动的Activity,那么可以通过finishActivity(int requestCode)来关闭。TIP:请慎用finish()方法,Activity的生命周期是由系统来维持和管理的,如果你调用了该方法,可能有会影响用户体验,比如按手机的back按钮将跳到上上个页面去。所以,除非你肯定的不希望用户再次返回到该Activity才使用。5. 管理Activity的生命周期通过实现Activity的回调方法来管理你的Activity是开发一个健壮和灵活应用程序的至关重要的条件。一个Activity的生命周期直接受与它关联的其他Activity以及进程和back stack影响。Activity的存在可以划分为三种情况:一:Resumed(运行状态的):即当前屏幕可见视图代表的Activity,可以获取用户焦点。二:Paused(暂停状态的):在当前Activity前端有一个Resumed状态的Activity,但是Resumed状态的Activity部分覆盖当前Activity;在这个状态下当前Activity是存活的。Paused状态的Activity当系统内存不足时有可能被杀死掉。三:Stopped(已停止状态的):该Activity被一个Resumed状态的Activity完全覆盖掉;在这个状态下Activity是存活的。当长时间没有访问和系统内存不足时有可能被杀死掉。 实现Activity生命周期内的回调函数当一个Activity在上述Activity存在状态中切换时,将对应不同的回调方法。下面该Activity类列出了基本的可重写的回调方法:public class ExampleActivity extends Activity Override public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); / The activity is being created. Override protected void onStart() super.onStart(); / The activity is about to become visible. Override protected void onResume() super.onResume(); / The activity has become visible (it is now resumed). Override protected void onPause() super.onPause(); / Another activity is taking focus (this activity is about to be paused). Override protected void onStop() super.onStop(); / The activity is no longer visible (it is now stopped) Override protected void onDestroy() super.onDestroy(); / The activity is about to be destroyed. Tip:当你在实现任意以上重写方法时,必须首先调用父类的该方法;如上面例子代码所示。例如super.onDestroy();如上所示方法,定义了整个Activity的生命周期。你可以通过实现这些方法来达到管理entire lifetime,visible lifetime,foreground lifetime三个嵌套循环的不同生命周期段的实现动作。一:entire lifetime (整个生命周期)从调用onCreate()方法开始,到调用onDestory()结束。你应当在onCreate()方法里面定义全局状态,比如设置布局,开始一个后台下载线程。在onDestory()方法里面释放资源,比如停止下载资源线程。二:visible lifetime (可见生命周期)从调用onStart()方法开始,到调用onStop()结束。在这个时间段内你可以在屏幕上看到该Activity并与之交互。你可以在onStart()方法里面注册一个BroadcastReceiver对象来监听正在显示的Activity发生改变时调用事件,而当这个Activity不再显示时将调用onStop()方法,在该方法里我们可以用来取消BroadcastReceiver对象的监听。三:foreground lifetime (可操作生命周期)从调用onResume()方法开始,到调用onPause()结束。在这段时间内,该Activity位于所有的其他Activity之上并且可以获得用户输入焦点。一个Activity在这个时间段将会频繁的进入和淡出屏幕,比如当用户待机或弹出一个窗体的时候,将会调用onPause()方法,由于这操作比较频繁,所以在这个方法中一般做耗时较少的操作以确保用户体验流畅。以下是Activity生命周期的图示:下表更加详细的列出了Activity生命周期中各个方法的详细描述以及系统在调用相应方法后能否杀死对应的Activity。方法描述Killable after?下一个调用的方法onCreate()在Activity第一次创建的时候调用。在这个方法里你应当做所有全局的操作,比如创建视图,填充activity需要的数据等。这个方法通过Bundle对象获取前一个Activity的数据。NOonStart()onRestart()在Activity停止后,再次被启动前调用。Called after the activity has been stopped, just prior to it being started again.NOonStart()onStart()刚好在Activity将要被用户可见前调用,此时还不可以看到Activity所代表的界面。NOonResume()或onStop()onResume()当Activity所代表的页面可见的时候调用,在这个时候,该Activity位于Activity栈顶,拥有用户输入焦点。NOonPause()onPause()当系统启动另一个Activity时调用。这个方法通常用于持久化未保存的数据的更改,停止动画,以及一些消耗CPU的操作。尽管CPU的处理速度很快,但是它必须做上述操作,应为onPause方法没有返回的话是不能创建下一个Activity的(前提:那些操作在主线程里个人见解)。YESonResume()或onStop()onStop()当用户看不到该Activity所代表的界面时调用。这个方法调用有两种情况:1.当该Activity正在销毁。2.另一个Activity启动或恢复并覆盖当前Activity。YESonRestart()或onDestory()onDestory()Activity正在销毁时调用,这是一个Activity生命周期中接受的最后一个回调方法。在正在调用Activity的finish方法前调用或者是系统内存不足导致不得不回收;想知道是哪一种销毁方式可以通过isFinishing()得知。YES以下对上图做一个简单的注释:Killable after?指出系统是否可以在任何上述方法执行完并返回后杀死持有当前Activity的进程。onPause,onStop,onDestory三个方法被标注为YES,由于onPause方法是Activity创建后最有可能保证执行的方法,因此,当系统遇到紧急情况需要恢复内存,那么onStop,onDestory可能不被执行,因此你应当在onPause里保存一些至关重要的状态属性,当然你应当有选择性的做一些操作,不能太耗时,如果太耗时,那么其他的activity将不能被创建直到该activity的onPause方法执行完毕并返回。注:上表中标注为NO的方法执行后也可能杀死进程,不过这是一种非常极端的情况,要了解进程与线程,参考Processes and Threading文档。 保存Activity状态管理Activity的生命周期这段简单的提到了当一个Activity处于暂停或停止状态,该activity的状态仍然保存。当Activity执行onPause或onStop方法后,Activity对象仍然存在内存里,所以当你按手机上的back按钮时,会跳到上一个Activity,并且假如上一个Activity里面有一些EditText控件并填有值的话,那么返回之后还是会带值的。然而,当系统为了回收内存而销毁一个Activity,当系统把该Activity销毁掉后,我们再导航到这个Activity时,系统不能就仅仅是简单的恢复该Activity,因为我们先前可能在Activity里填写了一些数据;相反的,我们要达到的一种效果是,当用户再返回到这个Activity时,就好像用户先前访问的一样,根本不会知道先前的Activity已经销毁而这个是重新构造的。因此,在这种情况下,你可能需要一个可以保存你Activity状态的回调方法以确保你Activity的一些重要状态在销毁前被保存,当重新启动的时候再恢复这些状态,这个方法就是onSaveInstanceState(Bundle outState),outState所代替的Bundle对象就是你可以以键值形式保存Activity状态数据的地方,保存数据方法比如:putString()。此时,若是系统杀死了你的Activity所在进程,而当用户重新访问这个Activity时候,系统将把你先前所保存状态的Bundle对象传给这个Activity的create()方法,因此,你可以恢复Activity先前所持有的状态;如果没有状态恢复,那么传递给create()方法的参数为null。Note:这里不能确保你的Activity对象销毁前一定调用onSaveInstanceState(Bundle outState)方法,比如,你按手机的BACK键,那么这是你确切的要销毁某个Activity对象,在这种情况下,onSaveInstanceState(Bundle outState)方法不会被调用,因为没有必要。如果onSaveInstanceState(Bundle outState)方法被调用,那么它总是在onStop()被调用前调用,也许有可能在onPause()方法前被调用。然而,即使你什么都不做或者不实现onSaveInstanceState(Bundle outState)方法,系统将可以以Activity的默认实现保存一部分你的Activity状态。具体来说,默认的实现调用onSaveInstanceState(Bundle outState)方法时,会保存当前Activity布局中的每一个View控件的需要不存的基本状态。几乎每一个view小部件都在onSaveInstanceState(Bundle outState)有适当的保存状态实现,因此当你Activiy UI的任何改变都会被动态的保存并且当Activity重建时候恢复数据。例如,EditText将保存用户输入的任何文本,CheckBox的选择状态。当然,要达到自动保存的效果有一个必须条件,那就是必须为每个控件提供一个id(配置layout中的android:id),如果没有提供id,那么没有id的控件状态将不会被保存,例如没有id的EditText的文本不会保存,即重新创建Activity时不可恢复。当然你也可以在layout布局文件里面加了id的控件再加一个android:saveEnabled=”false”属性,照样达到不可保存状态的目的。当然,尽管默认的onSaveInstanceState(Bundle outState)实现能为你的Activity界面保存有有的状态,但是你同样需要重写该方法,为什么呢?因为,假如你在做订单支付的账户,假如账户开始有10块钱,现在做了系列操作,用去了5块钱,如果存在需要恢复的可能,你肯定不会再给账户页面显示10块钱吧,这样的话,你的生意没的做了。上面陈述的情况是默认操作不能达到的。由于默认实现非常有用,而用户重写onSaveInstanceState(Bundle outState)方法只是加一些额外的操作或变一些默认操作,所以在实现该方法的任何效果前,我们应该做到必须先调用super. onSaveInstanceState(Bundle outState);Note:由于onSaveInstanceState(Bundle outState)方法不能确定一定会被调用,所以你只能用其做一些短暂的UI状态(如EditText的值)保存,而不能做一些比如持久化数据的操作。因此,我们要在onPause()方法里面做一些譬如持久化一些小数据的操作,当用户离开当前

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论