一、Activity简介

  1. Activity是四大组件之一,用于表现功能。
  2. 一个Activity通常就是一个单独的屏幕(窗口)。
  3. Activity之间通过Intent进行通信。
  4. android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。

二、创建一个Activity

  1. 自定义类继承系统Activity
  2. 复写Activity中Onreate方法
  3. 在布局文件夹中书写相应的布局文件
  4. 调用setContent(R.layout.activity_main)
    //参数为布局文件中的相应的文件名
  5. 在AndroidManifest.xml注册Activity
    否则报:ActivityNotFoundException
public class BActivity extends Activity {

    /**
     * 复写Activity中Onreate方法
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);// 调用setContentView方法
    }
}
// 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</LinearLayout>
// Activity组件注册,一律在<application></application>根标签中进行
<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <!--
                此处<intent-filter></intent-filter>声明,默认首次打开MainActivity界面
                可将此代码复制到MyActivity的声明中,则表明首次打开MyActivity界面
              -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--
            android:name    包名全路径 + 类名
            如果需要注册的Activity在pagegeName文件夹中,则不需要指定包名
        -->

        <activity android:name=".BActivity" >
            <intent-filter>
                <action android:name="com.vince.day06.b"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <activity android:name="com.vince.utils.CActivity" >
            <intent-filter>
                <action android:name="com.vince.day06.c"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
</application>

三、启动/跳转一个Activity

1. 显示跳转:指出具体跳转的Activity名称

/**
 * 源Activity
 * 
 * @param view
 */
public void startB(View view) {
    // 创建Intent意图对象,指定要跳转到的界面--BActivity.class
    Intent intent = new Intent(this, BActivity.class);
    // 通过putExtra()方法,设置传递值
    intent.putExtra("key", "启动B成功!");
    // 启动
    startActivity(intent);
}
// 目标Activity
Intent newIntent = getIntent();// 获取启动BActivity的intent对象
String content = newIntent.getstringExtra("key");// 获取对象中的信息

2. 隐式跳转:系统根据action和category计算出跳转哪个界面

2.1 第一种情况:A传值—–>B接收

/**
 * 源Activity
 * 
 * @param view
 */
public void startB(View view) {
    // 创建Intent意图对象
    Intent intent = new Intent();
    // 设置action、category
    intent.setAction("com.vince.day06.b");
    // intent.addCategory(Intent.CATEGORY_DEFAULT); 默认添加
    // 通过putExtra()方法,设置传递值
    intent.putExtra("intkey", 20);
    // 启动
    startActivity(intent);
}
// 目标Activity
Intent newIntent = getIntent();// 获取启动BActivity的intent对象
String content = newIntent.getstringExtra("intkey");// 获取对象中的信息

2.2 第二种情况:A传值—–>B接收,B返值—–>A接收

/**
 * 源Activity
 * 
 * @param view
 */
public void startC(View view) {
    // 创建Intent意图对象
    Intent intent = new Intent();
    // 设置action、category
    intent.setAction("com.vince.day06.c");
    // 通过putExtra()方法,设置传递值
    intent.putExtra("intkey", 15);
    // 启动(请求码可随意取,此处取10)
    startActivityForResult(intent, 10);
}

/**
 * 重写onActivityResult(int requestCode, int resultCode, Intent data)方法
 * 
 * @param requestCode
 *            :请求码
 * @param resultCode
 *            :是在目标Activity调用setResult时返回的结果码
 * @param data
 *            :是在目标Activity调用setResult时传入返回的对象
 */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (data != null) {
        Toast.makeText(this, "返回值为" + data.getStringExtra("return"), 1000).show();
    }
}
// 目标Activity
Intent intent = getIntent();// 获取启动CActivity的intent对象
int a = intent.getIntExtra("intkey", -1);// 获取对象中的信息
if (a != -1) {
    Toast.makeText(this, "接收MainActivity传递过来的值为" + a, 2000).show();
}
// 新建一个Intent意图对象,用于返回值
Intent newIntent = new Intent();
// 通过putExtra()方法,设置返回值
newIntent.putExtra("return", "接收成功!");
setResult(2, newIntent);// 参数中,结果码2可以随意取
// 结束CActivity
finish();

注意:如果有多个Activity注册同样的intent-filter(即action和category相同),在启动Activity时,则会弹出多个选择框,提供给用户自主选择

四、Activity生命周期

生命周期流程图如下:

Android activity 什么时候用弱引用 <activity>_android

1. Activity一生中有七种不同状态

(1)onCreate()
(2)onStart()
(3)onResume()
(4)onPause()
(5)onStop()
(6)onRestart()
(7)onDestroy()
package com.danny_jiang.day06_lifecycle;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

    private int progress;

    /**
     * 创建一个新的Activity实例时,此方法被调用
     * 
     * @param savedInstanceState
     * 当第一次创建Activity时,此实例为null 只有当Activity发生配置改变,或者被异常杀死时
     * 此参数才有具体的实现
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("TAGA", "onCreate---" + savedInstanceState);

        if (savedInstanceState != null) { // 说明之前发生过配置改变
            int savedProgress = savedInstanceState.getInt("progress");
            progress = savedProgress;
        }
    }

    /**
     * 当点击Button按钮时,动态的修改模拟播放进度
     * 
     * @param view
     */
    public void progress(View view) {
        Toast.makeText(this, "播放到了 " + progress++, 1000).show();
    }

    /**
     * 当Activity发生配置改变,或者被异常杀死时,此方法会被自动调用
     * 一般在此方法中做数据的保存工作,重新打开Activity时,可以取出保存的数据
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // 将当前的progress值保存到outState Bundle对象中
        // 当onCreate被重新调用时,可以从此Bundle中取出progress值
        outState.putInt("progress", progress);
    }

    /**
     * 当一个Activity由不可见状态改为可见状态时,此方法会被调用
     */
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e("TAGA", "onRestart");
    }

    /**
     * 当调用到此方法后,Activity会被显示到屏幕上
     * 注意:Activity并不会获取焦点
     */
    @Override
    protected void onStart() {
        super.onStart();
        Log.e("TAGA", "onStart");
    }

    /**
     * Activity获取焦点,用户可以与之进行交互
     */
    @Override
    protected void onResume() {
        super.onResume();
        Log.e("TAGA", "onResume");
    }

    /**
     * Activity失去焦点,但是Activity还是显示在屏幕上
     */
    @Override
    protected void onPause() {
        super.onPause();
        Log.e("TAGA", "onPause");
    }

    /**
     * Activity从屏幕上消失
     */
    @Override
    protected void onStop() {
        super.onStop();
        Log.e("TAGA", "onStop");
    }

    /**
     * Activity实例被销毁,Activity声明周期结束
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("TAGA", "onDestroy");
    }

    public void btnClick(View view) {
        startActivity(new Intent(this, BActivity.class));
    }
}

2. 典型的几种操作分析:

2.1 打开一个应用,然后点击back键退出:

    onCreate()--->onStart()--->onResume()---按back键--->onPause()--->onStop()--->onDestroy()

2.2 打开一个应用,然后点击home键退出,再重新打开应用:

    onCreate()--->onStart()--->onResume()---点击home键--->onPause()---onStop()---重新打开应用--->onRestart()--->onStart()---onResume()

2.3 打开一个Activity,点击该Activity上的按钮跳转到SecondActivity:

    M-onCreate()--->M-onStart()--->M-onResume()---点击跳转按钮---M-onPause()-->S-onCreate()--->S-onStart()--->S-Resume()--->M-onStop()

2.4 打开一个Activity,点击该Activity上的按钮跳转到SecondActivity,然后点击back键退出SecondActivity:

    M-onCreate()--->M-onStart()--->M-onResume()---点击跳转按钮--->M-onPause()-->S-onCreate()--->S-onStart()--->S-Resume()--->M-onStop()
    ---点击back键退出SecondActivity--->S-onPause()-->M-onRestart()--->M-onStart()--->M-onResume()--->S-onStop()--->S-onDestroy()

2.5 打开一个Activity,然后从竖屏切换为横屏

    onCreate()--->onStart()--->onResume()--切换为横屏-->onPause()--->onStop()--->onDestroy()--->onCreate()--->onStart()--->onResume()

2.6 打开一个Activity,然后从竖屏切换为横屏(onSaveInstanceState,onRestoreInstanceState):

    onCreate()--->onStart()--->onResume()---切换为横屏--->onSaveInstanceState()--->onPause()--->>onStop()--->onDestroy()--->onCreate() 
    --->onStart()--->onRestoreInstanceState()--->onResume()

2.7 打开一个Activity,点击该Activity上的按钮跳转到ThirdActivity(ThirdActivity主题为Dialog模式),然后点击back键:

    M-onCreate()--->M-onStart()--->M-onResume()--点击跳转按钮-->M-onPause()--->T-onCreate()--->T--->onStart()--->T-onResume() 
    --点击back键-->T-onPause()--->M-onResume()--->T-onStop()--->T-onDestroy()

2.8 打开一个Activity,然后从竖屏切换为横屏(配置android:configChanges="orientation|screenSize")

    onCreate()--->onStart()--->onResume()---切换横屏--->onConfigurationChanged()

备注:
    A、七个生命周期组合:
        启动应用程序:onCreate、onStart、onResume
        失去焦点:onPause、onStop 
        重新获得焦点:onRestart、onStart、onResume
        退出应用程序:onPause、onStop、onDestroy 

    B、七个生命周期按阶段划分:
        完整生命周期(The entire lifetime):onCreate() --- onDestroy()
        可见生命周期(The visible lifetime):onStart() --- onStop()         
        前沿生命周期(焦点生命周期The foreground lifetime):onResume() --- onPause()

3. 生命周期的作用

① 当用户接到一个电话或切换到另一个程序时不会崩溃
    ② 当用户后台运行程序时,不会销毁有价值的系统资源
    ③ 当用户离开再返回某应用时,不会丢失用户的进程
    ④ 当手机屏幕进行横竖屏切换时,不会崩溃或者丢掉用户的进程

五、Activity启动模式

1. 任务

1.1 概念

    一个任务(task)就是在执行某项工作时与用户进行交互的Activity的集合。
    这些Activity按照被打开的顺序依次被安排在一个堆栈中(回退栈)。

1.2 主屏页面

    设备的主屏是大多数任务的启动位置,当用户触摸一个应用程序启动器图标(或者app快捷图标),应用程序的任务就会在前台显示。 
    如果相关应用程序的任务不存在,那么就会有一个新的任务被创建,并且应用程序打开的“主”Activity会作为任务中的根Activity。

2. 回退栈

1.1 概念

    在当前的Activity启动了另一个Activity时,这个新的Activity被放到了堆栈的顶部,并且带有焦点。前一个Activity并没有消失, 
    而是保存在回退栈中,此时它处于停止状态。
    当用户按下回退按钮时,当前的Activity会被从回退栈的顶部弹出(被销毁),而前一个Activity被恢复。
    如果用户继续按回退按钮,那么回退栈中的每个Activity会被依次弹出,前一个Activity会被显示,直到用户返回主屏(或者返回到任务开始时运行 
    的那个Activity)。当所有的Activity从回退栈中被删除时,这个任务就不再存在了。

    **注意:堆栈中的Activity不会被重新排列。因此,回退栈的操作跟后进先出的对象结构是一样的。**

3. Activity启动模式

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。
在Android中Activity的启动模式决定了Activity的启动运行方式。

3.1 Activity启动模式设置(AndroidManifest.xml配置文件):
<activity android:name=".BActivity"
     android:launchMode="standard">
</activity>

<activity android:name=".CActivity"
     android:launchMode="singleTop">
 </activity>

<activity android:name=".DActivity"
     android:launchMode="singleTask">
</activity>

<activity android:name=".EActivity"
     android:launchMode="singleInstance">
</activity>
3.2 Activity的四种启动模式:
    A.standard(系统默认):
        每次激活Activity时都会创建Activity,并放入任务栈中。
        每个窗体的getTaskId()保持不变,但是this.hashCode()发生改变。

    B.singleTop:
        如果在任务的栈顶正好存在该Activity的实例,就重用该实例,而不会创建新的Activity对象,不过它会调用
    onNewIntent()方法。

        如果栈顶部不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建
    实例),会回调onNewIntent()方法。

    C.singleTask:
        如果在栈中已有该Activity的实例,就重用该实例(调用实例的onNewIntent())。重用时,会让该实例回到
    栈顶。因此,在它上面的实例将会被移除栈。

        如果栈中不存在该实例,将会创建新的实例放入栈中。

        singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而singleTask则会检测栈中全部的
    Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检测到的我们需
    要的Activity置为栈顶。

    D.singleInstance:
        与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其他任何窗口对象。因此如果
    该窗口不存在,则要新建任务来存放该singleInstance模式窗口。

        也就是说getTaskId()会发现任务id发生了变化。此启动模式和我们使用的浏览器工作原理类似,在多个程序中
    访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。

        此模式会节省大量的系统资源,因为它能保证要请求的Activity对象在当前的栈中只存在一个。