Android中activity的详解

来源:互联网 发布:尚观linux培训 骗局 编辑:程序博客网 时间:2024/06/01 19:23

Activity(活动)是一种包含用户界面的组件,主要用于和用户进行交互。需要在清单文件AndroidManifest.xml中配置。

生命周期

这里写图片描述
- onCreate:第一次被创建时候调用,初始化。
- onStart:由不可见变为可见。
- onResume:界面可见,此时Activity处于栈顶并且在运行状态。
- onPause:暂停,启动或恢复另一个Activity时调用,通常在这个方法中释放一些占CPU的资源和保存一些关键数据。不要执行耗时操作会影响新栈顶Activity的创建。
- onRestart:重新可见
- onStop:停止,Activity完全不可见
- onDestroy:销毁

1、打开一个界面:onCreate、onStart、onResume;
2、最小化一个界面:onPause、onStop;
3、重新打开被最小化的界面:onRestart、onStart、onResume;
4、关闭一个界面:onPause、onStop、onDestroy;

两个activity分别为A和B ,在A中激活B组件:

  1. A —> onPause() (A在onPause后B才开始创建,所以onPause中不可执行耗时操作以免影响B的创建)
  2. B —> onCreate(),onStart(),OnResume()
  3. A —> onStop(),onSaveInstanceState() (B完全覆盖了A时调用onStop,如果B是透明的或是对话框、吐司, 就不会调用onStop方法)
  4. A —> onDestroy() (有可能会调用,当内存不足时会回收后台的Activity)

此时再finish掉B回到A中:

  1. B —> onPause()
  2. A —> onRestart() (当A被onStop且没有onDestory时)
  3. A —> onCreate() (当A中onDestory时)
  4. A —> onStart(),OnResume()
  5. B —> onStop(),onDestroy()

    • onStart()和onStop是一对表示Activity是否可见
    • onResume和onPause是一对表示Activity是否位于前台
    • 点击Back键调用onPause(),onStop(),onDestroy()
    • 点击Home键调用onPause(),onSaveInstanceState(),onStop()
    • 不要在onPause和onStop中执行耗时操作(尤其是onPause),这样可以使新的Activity尽快显现出来

onSaveInstanceState和onRestoreInstanceState方法

onSaveInstanceState方法在Activity即将被销毁并且有机会重新显示的情况下才会被调用(在Activity.finish()时不调用)

用来保存Activity被杀之前的状态(savedInstanceState.putString(String key, String value)),在onStop()之前被触发(和onPaus的执行没有固定的先后关系),当系统为了节省内存销毁了Activity(用户本不想销毁)时就需要重写这个方法了,当此Activity再次被实例化时会通过onCreate(Bundle savedInstanceState)将已经保存的临时状态数据传入(savedInstanceState.getString(String key))。

  • 因为onSaveInstanceState()方法不总是被调用,触发条件为(按下HOME键,按下电源按键关闭屏幕,横竖屏切换情况下),你应该仅重写onSaveInstanceState()来记录activity的临时状态,而不是持久的数据。应该使用onPause()来存储持久数据。

  • 在onCreat和onRestoreInstanceState中恢复临时状态的区别是在onCreat中savedInstanceState不是每次都有值得所以要进行空判断,而onRestoreInstanceState只要被调用就一定会有值不需要进空判断

  • 在客户端每次进入某个界面的时候都要看到最新的数据,这个刷新列表的操作 就放在onStart()的方法里面填充数据,这样保证每次用户看到的数据都是最新的.

横竖屏切换时生命周期的变化

使用快捷键Ctrl+F11让横竖屏切换
1、默认情况下切屏会重新调用各个生命周期切横屏时会执行一次,切竖屏时会执行两次
默认首先销毁当前activity,然后重新加载
Onpause onstop ondestory oncreate onstart onresume
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
游戏开发中, 屏幕的朝向都是写死的.
固定横竖屏的方法:在清单文件的activity表现中定义android:screenOrientation=””
常见类型:portrait竖屏、landscape横屏、sensor感应器类型(默认类型)可以横竖屏自适应。

启动Activity的两种方法

  1. 显示开启

    Intent intent = new Intent(MainActivity.this , OtherActivity.class);startActivity(intent);
  2. 隐式开启

    Intent intent = new Intent();//设置目标activity的动作(必须与配置文件的aciton一致)intent.setAction("android.intent.action.HAVORLD");//设置目标类别(必须与配置文件的category一致)intent.addCategory("android.intent.category.DEFAULT");//开启一个新的activity(打开一个新的界面)startActivity(intent);

    注意:隐式开启时需要再想要开启的Activity在清单文件中配置对应的信息

    <activity android:name="com.havorld.OtherActivity" >    <intent-filter>        <action android:name="android.intent.action.HAVORLD" />        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></activity>
    • 在AndroidManifest.xml中的<action>和<category>必须同时匹配上代码中Intent指定的action和category时,这个Activity才能响应该Intent。清单文件中<action>和<category>标签必须定义,<data>标签可选。
    • android.intent.category.DEFAULT是一种默认的category,在调用startActivity时可会自动将这个category添加到Intent中去,因此代码中的intent.addCategory(“android.intent.category.DEFAULT”)可以省略。因为代码中会默认添加这个属性,所以在清单文件中必须定义以保证一一对应。

- 一个Intent可以在AndroidManifest.xml中指定多个action和多个category:

    <activity android:name="com.havorld.OtherActivity" >        <intent-filter>            <action android:name="android.intent.action.MENG"/>            <action android:name="android.intent.action.HAVORLD"/>            <category android:name="android.intent.category.DEFAULT"/>            <category android:name="android.intent.category.HAVORLD"/>        </intent-filter>    </activity>

在使用Intent开启Activity时只需要匹配其中一个和 就可以了。
- 一个Activity在清单文件中可以配置多组<intent-filter>,Intent只需要匹配一组就可以开启此Activity。

Activity的启动模式

standard(标准模式)

系统默认的启动模式,每启动一个Activity都会创建一个新的实例,哪个Activity(A)启动了新的Activity(B),这个Activity(B)就运行在那个Activity(A)所在的栈中。

  • 当我们使用ApplicationContext去启动OtherActivity(standard模式)时会报错,这是因为启动standard模式的Activity时会进入启动它的Activity所属的任务栈中,而ApplicationContext没有任务栈。可以给Activity添加一个标志位新建一个任务栈解决:

    Intent intent = new Intent(getApplication(),OtherActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);

singleTop(栈顶复用模式)

当有一个实例Activity(A)位于栈顶时,再启动此Activity(A)时不会再重建Activity(A)会调用onNewIntent方法。当实例Activity(A)没有位于栈顶时再次启动Activity(A)依然会创建新的Activity(A)实例。

singleTask(单一任务栈模式)

当启动一个设置为singleTop的Activity(A)被启动时会首先在栈中检查是否存在该活动的实例,如果存在则把这个实例上面的Activity全部弹栈Activity(A)处于栈顶。

singleInstance(单例模式)

当在Activity(A)中启动一个singleInstance的Activity(B)时,会启用一个新的栈来存放这个Actitity(B),在Activity(B)中再启动Activity(C);此时A、B在一个任务栈中,C在另一个单独的任务栈中。当我们按下返回键时Activity的展示顺序为:C—>A—>B,这是因为C、A处于同一任务栈,当在C界面按下Back时C出栈A就处于栈顶显示在界面上,然后再A界面按下Back键这时这个返回栈就空了于是显示另一个返回栈的栈顶活动B,再在B界面按下Back键所有栈都空了也就退出了程序。

  • 给Activity设置启动模式有两种方法:
    1. 清单文件配置

Intent和<intent-filter>标签的更多使用

Intent指定打开系统浏览器

Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("https://www.baidu.com"));startActivity(intent);

- Intent.ACTION_VIEW是系统的一个内置action其值为android.intent.action.VIEW,也可使用intent.setAction(Intent.ACTION_VIEW)。

Intent打开系统通讯录拨号

Intent intent = new Intent(Intent.ACTION_DIAL);intent.setData(Uri.parse("tel:10086"));startActivity(intent);

代码中Intent.setData(Uri data)

data由两部分组成:mimeType和URI

mimeType:指定媒体类型比如 image/jpeg,audio/mpeg4-generic、video/*URI的结构:<scheme>://<host>:<port>/[<path>]如 https://www.baidu.com:8080/search/havorld如在intent.setData(Uri.parse("https://www.baidu.com"))中,https://www.baidu.com是URI,mimeType没有指定。

<intent-filter>中的<data>标签

  • data标签中的配置内容:
    1. android:scheme。 用于指定数据的协议部分,如http、file、content部分
    2. android:host。 用于指定数据的主机部分,如www.baidu.com部分
    3. android:port。 用于指定数据的端口部分,一般紧随在主机名之后如8080
    4. android:path。 用于指定主机和端口之后的部分,如一段网址中跟在域名之后的内容
    5. android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定

Intent添加data匹配AndroidManifest.xml中的<data>标签

  • 清单文件中配置

    <activity android:name="com.havorld.MyActivity" >    <intent-filter>        <action android:name="android.intent.action.HAVORLD" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="image/*" />    </intent-filter></activity>
  • 代码中
    Intent intent = new Intent();
    intent.setAction(“android.intent.action.HAVORLD”);
    intent.addCategory(“android.intent.category.DEFAULT”);
    intent.setDataAndType(Uri.parse(“file://abc”), “image/*”);
    //intent.setDataAndType(Uri.parse(“content://abc”), “image/*”);
    startActivity(intent);

在清单文件中指定了type,没有指定URI,URI的默认值为content和file。Intent指定完整的data时需要使用setDataAndType,不能先setData再setType,因为他们会彼此清除对方的值

0 0