安卓activity生命周期详解。由一个activity跳转到另外一个activity。

查看: 4566|回复: 6
Android开发者面试题之Activity生命周期详解
该用户从未签到主题帖子e币
没有eoe的账号,级别还太低,出门如何吹牛逼?
才可以下载或查看,没有帐号?
【Android面试】Android面试题集锦
==========帖子正文============================
  真的挺全面呢。
  1.& & 请描述下Activity的生命周期。
  2.& & 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
  3.& & 如何将一个Activity设置成窗口的样式。(Edited by Sodino)
  4.& & 如何退出Activity?如何安全退出已调用多个Activity的Application?
  5.& & 请介绍下Android中常用的五种布局。
  6.& & 请介绍下Android的数据存储方式。(Edited by Sodino)
  7.& & 请介绍下ContentProvider是如何实现数据共享的。(Edited by Sodino)
  8.& & 如何启用Service,如何停用Service。(Edited by Sodino)
  9.& & 注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。
  10.& & 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
  11.& & AIDL的全称是什么?如何工作?能处理哪些类型的数据?
  12.& & 请解释下Android程序运行时权限与文件系统权限的区别。(Edited by Sodino)
  13.& & 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。
  14.& & 有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。
  15.& & 你如何评价Android系统?优缺点。
  1.& & 请描述下Activity的生命周期
      
  详细介绍一下这几个方法中系统在做什么以及我们应该做什么:
  onCreate:& &在这里创建界面 ,做一些数据的初始化工作
  onStart:& & 到这一步变成用户可见不可交互 的
  onResume:& &变成和用户可交互 的,(在activity 栈系统通过栈的方式管理这些个
  Activity的最上面,运行完弹出栈,则回到上一个Activity)
  onPause:& &&&到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU 的事情
  从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候
  你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在
  onResume里读出来,注意:这个方法里做的事情时间要短,因为下一
  个activity不会等到这个方法完成才启动
  onstop:& &&&变得不可见 ,被下一个activity覆盖了
  onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方
  法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判
  断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里
  把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛
  异常的。
  onPause,onstop, onDestroy,三种状态 下 activity都有可能被系统干掉
  为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库)。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制 [Handler,Message]来处理多线程和界面交互的问题。这个我后面会讲一些,最近因为这些东西头已经很大了,等我理清思绪再跟大家分享。
  2.& & 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
  当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B
  这个时候A会执行
  Java代码
[mw_shl_code=java,true]  public
  void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putLong(&id&, );
  public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putLong(&id&, );}[/mw_shl_code]
  B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回
  收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数
  savedInstanceState,没被收回的就还是onResume就好了。
  savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。
  Java代码
[mw_shl_code=java,true]  if(savedInstanceState != null){
  long id = savedInstanceState.getLong(&id&);
  if(savedInstanceState != null){& &&&long id = savedInstanceState.getLong(&id&);}[/mw_shl_code]
  就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦,没准你需要记住滚动条的位置...
  3.& & 如何将一个Activity设置成窗口的样式
  简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的
  地方一句话:
  Xml代码
[mw_shl_code=java,true]  android :theme=&@android:style/Theme.Dialog&
  android:theme=&@android:style/Theme.Dialog&[/mw_shl_code]
  这就使你的应用程序变成对话框的形式弹出来了,或者
  Xml代码
[mw_shl_code=java,true]  android:theme=&@android:style/Theme.Translucent&
  android:theme=&@android:style/Theme.Translucent&[/mw_shl_code]
  就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable
  上面说的是属性名称,具体有什么值是在android.R.style中可以看到,比如这个&@android:style/Theme.Dialog& 就对应于android.R.style.Theme_Dialog ,('_'换成'.' &--注意:这个是文章内容不是笑脸)就可以用在描述文件中了,找找类定义和描述文件中的对应关系就都明白了。
  4.& & 如何退出Activity
  对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。现提供几个方法,供参考:
  1、抛异常强制退出:该方法通过抛异常,使程序Force Close。验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
  2、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。
  3、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。
  4、递归退出在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。但是这样做同样不完美。你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。但至少,我们的目的达到了,而且没有影响用户使用。为了编程方便,最好定义一个Activity基类,处理这些共通问题。
  5.请介绍下Android中常用的五种布局 Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。
  一、FrameLayout
  这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。& &&&
& && &二、LinearLayout
  线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局(android:orientation=&vertical&)和水平布局(android:orientation=&horizontal& )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。& && &&&linearLayout中有一个重要的属性 android:layout_weight=&1&,这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
  三、AbsoluteLayout
  绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x=&20px& android:layout_y=&12px& 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
  四、RelativeLayout
  相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
  相对于某一个元素
  android:layout_below=&@id/aaa& 该元素在 id为aaa的下面
  android:layout_toLeftOf=&@id/bbb& 改元素的左边是bbb
  相对于父元素的地方
  android:layout_alignParentLeft=&true&&&在父元素左对齐
  android:layout_alignParentRight=&true& 在父元素右对齐
  还可以指定边距等,具体详见API
  五、TableLayout
  表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity=&& 。
  每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。
  6.& & 请介绍下Android的数据存储方式
  Android 提供了5种方式存储数据:
  --使用SharedPreferences存储数据;
  --文件存储数据;
  --SQLite数据库存储数据;
  --使用ContentProvider存储数据;
  --网络存储数据;
  先 说下,Preference,File, DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。
  在Android中通常使用File存储方式是用 Context.openFileOutput(String fileName, int mode)和Context.openFileInput(String fileName)。
  Context.openFileOutput(String fileName, int mode)生成的文件自动存储在/data/data/Package Name/files目录下,其全路径是/data/data/Package Name/files/fileName 。注意下,这里的参数fileName不可以包含路径分割符(如&/&)。
  通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(String fileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/Package Name/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data /Package Name/files目录下寻找文件名为fileName的文件。
  一:使用SharedPreferences存储数据
  首先说明SharedPreferences存储方式,它是 Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
[mw_shl_code=java,true]  void ReadSharedPreferences(){
  String strName,strP
  SharedPreferences& &user = getSharedPreferences(“user_info”,0);
  strName = user.getString(“NAME”,””);
  strPassword = user getString(“PASSWORD”,””);
  void WriteSharedPreferences(String strName,String strPassword){
  SharedPreferences& &user = getSharedPreferences(“user_info”,0);
  uer.edit();
  user.putString(“NAME”, strName);
  user.putString(“PASSWORD” ,strPassword);
  mit();
  }[/mw_shl_code]
  数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data/&package name&/shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:
[mw_shl_code=java,true]  &?xml version=”1.0″ encoding=”UTF-8″?&
  &string name=”NAME”&moandroid&/string&
  &string name=” PASSWORD”&SharedPreferences&/string&
  &/map&[/mw_shl_code]
  使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。
  二:文件存储数据
  文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与 Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。 FilterInputStream, FilterOutputStream等可以到Java io package说明中去详细学习,不再此详细说明,具体实例如下:
[mw_shl_code=java,true]  String fn = “moandroid.log”;
  FileInputStream fis = openFileInput(fn);
  FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);[/mw_shl_code]
  除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。
  三:网络存储数据
  网络存储方式,需要与Android 网络数据包打交道,关于Android 网络数据包的详细说明,请阅读Android SDK引用了Java SDK的哪些package?。
  四:ContentProvider
  1、ContentProvider简介
  当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。?
  2、Uri类简介
  Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
  1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
  2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
  3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
  ? 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
  ? 要操作contact表中id为10的记录的name字段, contact/10/name
  ? 要操作contact表中的所有记录,可以构建这样的路径:/contact?
  要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
  要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
  如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
  Uri uri = Uri.parse(&content://com.changcheng.provider.contactprovider/contact&)
  3、UriMatcher、ContentUrist和ContentResolver简介
  因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从 Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。
  ? UriMatcher:用于匹配Uri,它的用法如下:
  1.首先把你需要匹配Uri路径全部给注册上,如下:
  //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
  UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider /contact路径,返回匹配码为1
  uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
  //如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
  uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符
  2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用 addURI()方法传入的第三个参数,假设匹配 content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为
& && & 1.ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
   withAppendedId(uri, id)用于为路径加上ID部分
   parseId(uri)方法用于从路径中获取ID部分
  ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用 ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。
  五:总结说明
  以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
  8.如何启用Service,如何停用Service
  Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:
[mw_shl_code=java,true]  第一步:继承Service类
  public class SMSService extends Service {
  第二步:在AndroidManifest.xml文件中的&application&节点里对服务进行配置:
  &service android:name=&.SMSService& /&[/mw_shl_code]
  服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
  如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
  如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()--&onDestroy()方法。
  服务常用生命周期回调方法如下:
  onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
  onDestroy()该方法在服务被终止时调用。
  与采用Context.startService()方法启动服务有关的生命周期方法
  onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
  与采用Context.bindService()方法启动服务有关的生命周期方法
  onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
  onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用
  采用Context.startService()方法启动服务的代码如下:
[mw_shl_code=java,true]  public class HelloActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
  ......
  Button button =(Button) this.findViewById(R.id.button);
  button.setOnClickListener(new View.OnClickListener(){
  public void onClick(View v) {
  Intent intent = new Intent(HelloActivity.this, SMSService.class);
  startService(intent);
  }[/mw_shl_code]
  采用Context. bindService()方法启动服务的代码如下:
[mw_shl_code=java,true]  public class HelloActivity extends Activity {
  ServiceConnection conn = new ServiceConnection() {
  public void onServiceConnected(ComponentName name, IBinder service) {
  public void onServiceDisconnected(ComponentName name) {
  @Override public void onCreate(Bundle savedInstanceState) {
  Button button =(Button) this.findViewById(R.id.button);
  button.setOnClickListener(new View.OnClickListener(){
  public void onClick(View v) {
  Intent intent = new Intent(HelloActivity.this, SMSService.class);
  bindService(intent, conn, Context.BIND_AUTO_CREATE);
  //unbindService(conn);//解除绑定
  }[/mw_shl_code]
本帖被以下淘专辑推荐:
& |主题: 14, 订阅: 17
该用户从未签到主题帖子e币
百度的好像还比较全面些啊
签到天数: 19 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
该用户从未签到主题帖子e币
该用户从未签到主题帖子e币
该用户从未签到主题帖子e币
签到天数: 12 天连续签到: 1 天[LV.3]偶尔看看II主题帖子e币
社区认证会员
社区认证会员
QQ已认证,此人靠谱
推荐阅读热门话题
619901843415415374321272263257252249234223215715
半小时前1&小时前1&小时前1&小时前1&小时前2&小时前2&小时前2&小时前2&小时前2&小时前3&小时前3&小时前3&小时前3&小时前3&小时前4&小时前
Powered by
扫一扫 关注eoe官方微信Activity跳转时生命周期跟踪-android100学习网
Activity跳转时生命周期跟踪
android应用当中Activity间相互跳转比较常见。本文将通过例子跟踪一下2个Activity间跳转过程中生命周期的变化过程。 整个操作过程如下图所示:1. 打开应用,自动开启F
android应用当中Activity间相互跳转比较常见。本文将通过例子跟踪一下2个Activity间跳转过程中生命周期的变化过程。
整个操作过程如下图所示:
1. 打开应用,自动开启First Activity;
2. 按下“Jump Button”按钮,打开Second Activity;
3. 按下“回退”按钮,退出Second Activity,自动回到First Activity;
4. 按下“回退”按钮,退出应用,自动关闭First Activity。
注:两个Activity的启动模式都是默认的(standard)
在Fist Activity和Second Activity的相应“过程”方法里打印Log。这些“过程”方法包括:onCreate、onRestart、onStart、onResume、onPause、onStop、onDestroy。
打印结果如下
//----------1------------
First Activity: onCreate
First Activity: onStart
First Activity: onResume
//----------2------------
First Activity: onPause
Second Activity: onCreate
Second Activity: onStart
Second Activity: onResume
First Activity: onStop
//----------3------------
Second Activity: onPause
First Activity: onRestart
First Activity: onStart
First Activity: onResume
Second Activity: onStop
Second Activity: onDestroy
//----------4------------
First Activity: onPause
First Activity: onStop
First Activity: onDestroy
结果分析:
1. 步骤1(打开First Activity):经过onCreate、onStart、onResume后First Activity就展现啦;
2. 步骤2(跳转至Second Activity):首先First Activity暂停(onPause),接下来Second Activity展现(onCreate、onStart、onResume),最后First Activity停止(onStop);
3. 步骤3(返回到First Activity):首先Second Activity暂停(onPause),接下来First Activity重新打开并展现(onRestart、onStart、onResume),最后Second Activity停止并销毁(onStop、onDestroy);
4. 步骤4(退出First Activity):经过onPause、onStop、onDestroy后First Activity暂停、停止并最终销毁。

我要回帖

更多关于 安卓activity生命周期 的文章

 

随机推荐