[TOC] ## 一、什么是活动 Android四大组件之一,用于与用户之间进行交互,你在Android上所看到的可以交互的程序界面都属于活动. ## 二、活动的创建 创建活动一般需要2个步骤: * 创建活动类继承自`AppCompatActivity`. * 在AndroidManifest.xml文件中进行注册. ```xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.activitytest"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--注册活动name = .活动类名--> <activity android:name=".FirstActivity"></activity> <activity android:name="..."></activity> </application> </manifest> ``` ## 三、主活动 什么是主活动?就是你打开Android程序后第一个看到的界面,同样在AndroidManifest.xml文件中进行设置. ```xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.activitytest"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--注册活动--> <!--label中设置活动标题--> <!--android.intent.action.MAIN" "android.intent.category.LAUNCHER"表示设置为主活动--> <activity android:name=".FirstActivity" android:label="This is FirstActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ``` ## 四、在活动间穿梭 **Intent**(中文翻译为'意图')是Android程序中各组件之间进行交互的一种重要方式. ### 4.1 显式Intent 从FirstActivity跳转到SecondActivity. ```java //public Intent(Context packageContext, Class<?> cls) Intent intent = new Intent(FirstActivity.this,SecondActivity.class); startActivity(intent); ``` ### 4.2 隐式Intent * 在AndroidManifest.xml文件中为Activity注册action和category信息. * 通过intent发送action和category,当系统检测到某个activity匹配到相同的action和category时就会启动该Activity. **Demo1** 自定义action+系统缺省category. ``` <activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.example.activitytest.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> ``` ```java button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Intent intent = new Intent("com.example.activitytest.ACTION_START"); startActivity(intent); } }); ``` **Demo2** 自定义action+自定义category. ``` <activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.example.activitytest.ACTION_START" /> <!--实验证明android.intent.category.DEFAULT这条必须得有否则会崩溃.--> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.example.activitytest.MY_CATEGORY" /> </intent-filter> </activity> ``` ```java button1.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Intent intent = new Intent("com.example.activitytest.ACTION_START"); intent.addCategory("com.example.activitytest.MY_CATEGORY"); startActivity(intent); } }); ``` PS:细心的朋友可以发现,Android程序的主活动其实就是通过隐式Intent实现的. ### 4.3 更多隐式的Intent的用法 * 如何打开一个指定网址的Activity页面. ```java Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent); ``` 可以看到我们这里是通过匹配action和data来匹配到合适的Activity的(Uri.parse("http://www.baidu.com")会把一个网址解析为Uri对象). * data标签的配置. |配置内容|解释| |-|-| |android:scheme|指定数据的协议部分,例如http| |android:host|指定数据的主机部分,例如www.baidu.com| |android:port|指定数据的端口部分| |android:path|指定域名之后的内容| |android:miniType|指定可以处理的数据类型| * 自定义一个可以响应data中scheme部分为http的activity. ```xml <activity android:name=".ThridActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="http" /> </intent-filter> ``` ![](https://box.kancloud.cn/144977f1e17e136a0f1be1f84ff805c8_526x833.png) * 当然你可以可以通过设置data打开其他内置activiy(如通讯录) ```java Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); ``` ### 4.4 向下一个活动传递数据 既然Intent能完成一个activity到另一个activity的跳转,那么它必然也会具备跳转时传输数据的能力. 通过跳转时为intent附加上键值对的方式进行数据传输. ```java // FirstActivity String data = "Hello SecondActivity"; Intent intent = new Intent(FirstActivity.this,SecondActivity.class); intent.putExtra("extra_data",data); startActivity(intent); ``` ```java //SecondActivity Intent intent = getIntent(); String data = intent.getStringExtra("extra_data"); Log.d("SecondActivity",data); ``` ### 4.5 返回数据给上一个活动 在4.4 小节中数据传递是从FirstActivity到SecondActivity,如果我们希望数据从SecondActivity-FirstActivity呢? * FirstActivity跳转时调用startActivityForResult方法. * FirstActivity覆盖onActivityResult方法监听返回结果. * SecondActivity创建intent通过setResult进行传递. ```java // FirstActivity public class FirstActivity extends AppCompatActivity { public Button button1 = null; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // requestCode为请求码,与startActivityForResult(intent,1)第二个参数对应. switch (requestCode) { case 1: if (resultCode == RESULT_OK){ String returnedData = data.getStringExtra("data_return"); Log.d("FirstActivity",returnedData); } break; default: break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.first_layout); button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Intent intent = new Intent(FirstActivity.this,SecondActivity.class); // 第二个参数1表示请码,可以自己定义. startActivityForResult(intent,1); } }); } } ``` ```java //SecondActivity public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_layout); Intent intent = new Intent(); intent.putExtra("data_return","Hello FirstActivity"); setResult(RESULT_OK,intent); finish(); } } ``` 上面代码会在跳转到SecondActivity时马上返回FirstActivity,我们也可以把返回数据的工作放到点击手机的返回按键时进行. ```java public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_layout); } @Override public void onBackPressed() { Intent intent = new Intent(); intent.putExtra("data_return","Hello FirstActivity"); setResult(RESULT_OK,intent); finish(); } } ``` ## 五、 活动的生命周期 ### 5.1 活动的管理方式 * 任务(Task):Android使用任务来管理活动. * 返回栈(Back Stack):一个任务就是存放在栈里活动的集合,这个栈称为返回栈. * 当按下back按键或者调用finish()方法去销毁一个活动时,栈顶元活动会出栈。 ![](https://box.kancloud.cn/dedc16a30cf79c4013e788397c4e496e_543x366.png) ### 5.2 活动状态 * 运行状态 当活动位于返回栈栈顶时。 * 暂停状态 当活动不在栈顶的,但仍然可见时,例如打开一个对话框时(对话框并不占满整个屏幕),对话框背后的活动就是暂停状态. * 停止状态 活动不在栈顶,并且完全不可见. * 销毁状态 当活动从栈中移除. ### 5.3 活动的生命周期 * onCreate() 创建 * onStart() 不可见 to 可见 * onResume() 活动位于栈顶,马上就要与用户进行交互了. * onPause() 准备启动或者恢复另一个活动. * onStop() 可见 to 不可见(不在栈顶,并完全不可见) * onDestroy() 销毁 * onRestart() 停止 to 运行 * 除了onRestart()上面方法凉凉相对 * 完整生命周期,onCreate() to onDestroy() * 可见生命周期,onStart() to onStop() * 前台生命周期,onResume() to onPause() ![](https://box.kancloud.cn/c0cc434d86651592fef1025329169ae6_761x988.png) ### 5.4 活动被系统自动回收了怎么办 一个活动进入了停止状态后是可能被系统回收的,但如果这个活动中保存了临时数据我们不想它被回收怎么办,那就需要在系统要回收资源的时候将临时数据保存起来,等该活动再创建时将数据再回复出来. * 重载onSaveInstanceState,将临时数据保存到Bundle对象的键值对中. * 在onCreate函数中从Bundle对象中取出数据. ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_layout); if (savedInstanceState!=null){ String tempData = savedInstanceState.getString("data_key"); Log.d("tag",tempData); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); String tempData = "Someteing you just typed"; outState.putString("data_key",tempData); } ``` ### 5.5 活动的启动模式 1. 如何设置Activity的启动模式? 在AndroidManifest.xml中设置activity标签的android:launchMode属性来实现. 2. 活动模式的种类. * standard 默认活动的启动模式,每当启动活动A时都会创建一个新的活动A放到栈顶,不管活动A在返回栈中是否已经存在. ![](https://box.kancloud.cn/d8885c8ee24e90fb61112ed393d19b57_440x257.png) * singleTop 当活动A已经位于栈顶时,不会再创建A活动,当其他活动B位于栈顶时可以创建A活动。 ![](https://box.kancloud.cn/2a4c6d246f11376d81b6d0bf1351336c_509x263.png) * singleTask 当活动A再返回栈中已经存在,但是活动A并不位于栈顶,此时再创建活动A时,不会创建真正的实例,而是会从返回栈中唤醒A活动放到栈顶. ![](https://box.kancloud.cn/10bdba3b7ad56934deb9ef08d30a2c99_419x267.png) * singleInstance 每个Android程序都会有自己返回栈来管理活动,但是使用singleInstance启动模式的活动在启动时会被放到一个新的返回栈中,并且这个新的返回栈是所有Android程序中使用了singleInstance作为启动模式的活动所共用的. 例:有三个Activity FirstActivity SecondActivity ThirdActivity,将SecondActivity的启动模式设置为singleInstance,其它默认,我们让三个Activity依次启动并在三个Activity中分别打印下返回栈的TaskId,你会发现FirstActivity和ThirdActivity的TaskId是相同的,SecondActivity有自己的TaskId. 如果你连续按下返回键你会发现Activity回退的顺序是ThirdActivity FirstActivity SecondActivity,因为ThirdActivity与FirstActivity是在一个返回栈中的. ```xml <!--AndroidManifest.xml--> <activity android:name=".SecondActivity" android:launchMode="singleInstance"> <intent-filter> <action android:name="com.example.activitytest.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="com.example.activitytest.MY_CATEGORY" /> </intent-filter> </activity> ``` ```java //FirstActivity public class FirstActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.first_layout); Log.d("FirstActivity","Task id is "+getTaskId()); Button button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Intent intent = new Intent(FirstActivity.this,SecondActivity.class); startActivityForResult(intent,1); } }); } } ``` ```java //SecondActivity public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_layout); Log.d("SecondActivity","Task id is "+getTaskId()); Button button2 = (Button)findViewById(R.id.button_2); button2.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { Intent intent = new Intent(SecondActivity.this,ThridActivity.class); startActivity(intent); } }); } } ``` ```java //ThirdActivity public class ThirdActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.thrid_layout); Log.d("ThirdActivity","Task id is "+getTaskId()); } } ``` ![](https://box.kancloud.cn/42880f76db678f90be94b325ec8c8dca_551x256.png)