Android学习笔记(二)活动(Activity)
版权声明:原创文章,开放分享,但请客官留个URL,蟹蟹~~如有纰漏,还请指出,以免误导后生! https://blog.****.net/qq_16313365/article/details/52700762
2.活动(Activity)
2.1 概念
活动是Android的基本组成单位,每个Activity都被定义为一个单独的类,且都继承自基类:android.app.Activity;它是一种包含用户界面的组件,主要用来与用户进行交互(通俗点讲,可以先理解为一个单独的屏幕、一个交互的窗口,但不完全是这样)。
2.2 基本使用
2.2.1 手动创建活动
新建一个类FirstActivity,并继承自基类Activity,重写Activity的onCreate()方法(项目中的任何活动都要重写此方法)。
- public class FirstActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- }
2.2.2 创建加载布局
Android应用讲究逻辑和视图分离,所以最好一个Activity对应一个XML布局文件。
创建activity_first.xml文件(在res-->layout目录下),并添加一个按钮:
- <?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">
- <!--
- android:id==>>给当前的元素定义一个唯一标识符,可在代码中调用。
- @+id/btn_1==>>需要引用一个id,则使用@id/id_name这种语法;需要定义一个id,则使用@+id/id_name这种语法,其他资源一致。
- android:layout_width==>>指定当前元素宽度,同理height为高度
- android:text==>>指定元素显示的文字内容,其实文字应该放在字符串文件中并在这里引用。
- -->
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Button"
- android:id="@+id/btn_1" />
- </LinearLayout>
在代码中调用此视图显示到activity中:
- setContentView(R.layout.activity_first);
2.2.3 在Androidmanifest.xml中注册
所有的活动都要在AndroidManifest.xml中进行注册才能生效:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.jastar.activitytest">
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <!--
- 1.所有活动都需通过activity标签来注册,且放在application标签中
- 2.android:name:指定注册哪一个活动;.FirstActivity是缩写,因为包名在manifest标签中已经定义了
- 3.android:label:活动标题栏的内容,显示在最顶部
- 4.给主活动指定的label还会成为启动器(Launcher)中应用程序显示的名称
- -->
- <activity android:name=".FirstActivity" android:label="This is the firstActivity">
- <intent-filter>
- <!--让活动成为主活动(main入口)就要声明这两句话-->
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
2.2.4 隐藏标题栏
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏,一定要写在setContentView方法前面
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_first);
- }
注意:
使用AS创建的activity隐藏标题栏时无效,是因为AS默认继承的是AppCompatActivity类,换成Activity类即可。
2.2.5 使用Toast悬浮提示
Toast是Android系统提供的提示方式,可将信息展示给用户,并在一段时间后消失。
可给按钮添加点击事件,并提示:
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_first);
- /**
- * 1.通过findViewById()来获得界面上的元素,返回View对象,并向下转型
- * 2.通过实现OnClicklistener接口的onClick()来给按钮添加点击事件
- */
- Button btn = (Button) findViewById(R.id.btn_1);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- /**
- * 别忘了调用.show()方法
- * param1:Context上下文,由于活动本身就是,所以传入活动对象即可
- * param2:提示内容
- * param3:提示显示时长,还有LENGTH_LONG
- */
- Toast.makeText(FirstActivity.this, "You click the button!", Toast.LENGTH_SHORT).show();
- }
- });
- }
2.2.6 使用menu菜单
(1)在res下新建menu文件夹
(2)在menu下新建一个名为main的菜单文件(在AS中直接new一个Menu resource file)
(3)AS创建之后默认是一个空的menu标签,需要添加菜单项代码:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/item_add"
- android:title="Add" />
- <item
- android:id="@+id/item_remove"
- android:title="Remove" />
- </menu>
(4)在活动中重写onCreateOptionsMenu()使得菜单展示
- /**
- * 重写展示菜单的方法
- * @param menu
- * @return
- */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- /**
- * 通过此方式给当前活动创建菜单
- * param1:指定哪个资源文件创建菜单
- * param2:指定菜单项将添加到哪个菜单中,直接使用方法中传入的参数即可
- * return:true允许菜单展示,false则不显示
- */
- getMenuInflater().inflate(R.menu.main,menu);
- return true;
- }
(5)在活动中重写onOptionsItemSelected()来响应菜单点击事件
- /**
- * 重写响应菜单点击事件的方法
- *
- * @param item
- * @return
- */
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- //item.getItemId()用来获取选中菜单的id
- switch (item.getItemId()) {
- case R.id.item_add:
- Toast.makeText(FirstActivity.this, "You click add menu!", Toast.LENGTH_SHORT).show();
- break;
- case R.id.item_remove:
- Toast.makeText(FirstActivity.this, "You click remove menu!", Toast.LENGTH_SHORT).show();
- break;
- }
- return true;
- }
2.2.7 销毁活动
返回键可以销毁;当然代码也能:finish();即可
2.3 意图(Intent)
2.3.1 概念
Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务、以及发送广播等场景。
Intent的用法大概分为两种:显式意图和隐式意图。
2.3.2 显式意图
同样方法创建第二个Activity——SecondActivity,并在FirstActivity中按钮点击事件中编写如下代码:
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- /**
- * param1:为当前活动上下文
- * param2:要启动的活动
- */
- Intent intent =new Intent(FirstActivity.this,SecondActivity.class);
- startActivity(intent);
- }
- });
2.3.3 隐式意图
指定了一系列更为抽象的 action和 category等信息,然后交由系统去分析这个 Intent,并帮我们找出合适的活动去启动。
隐式意图需要在activity标签下的intent-filter标签中指定action和category,只有action和category同时匹配的情况下(除去当category配置为默认 android:name="android.intent.category.DEFAULT" 时),该活动才能响应。如:
- <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代码如下:
- Intent intent=newIntent("com.example.activitytest.ACTION_START");
- startActivity(intent);
每个 Intent 中只能指定一个 action,但却能指定多个 category。
- intent.addCategory("...");
2.3.4 隐式意图更多用法
隐式意图不但能打开自己应用的activity,还能打开系统的activity,如浏览器、拨号等等。
- @Override
- public void onClick(View v) {
- /**
- * 1.Intent.ACTION_VIEW 这是系统内置动作,其常量值为android.intent.action.VIEW
- * 2.通过Uri.parse()方法将网址解析为Uri对象
- * 3.调用setData将Uri对象传递。
- */
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse("http://www.baidu.com"));
- startActivity(intent);
- //打电话
- //Intent intent=new Intent(Intent.ACTION_DIAL);
- //intent.setData(Uri.parse("tel:10086"));
- //startActivity(intent);
- }
2.3.5 向下一个Activity传递数据
(1)第一个activity:
- Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
- //使用putExtra()方法传递数据
- intent.putExtra("data", "这是我传递的数据");
- startActivity(intent);
(2)第二个activity:
- //通过getIntent()方法获取启动当前activity的意图对象
- Intent intent = getIntent();
- //什么类型的数据就get类型Extra("");
- String data = intent.getStringExtra("data");
- Log.d("SecondActivity", data);
2.3.6 返回数据给上一个Activity
Activity中提供了一个startActivityForResult()方法,此方法期望在活动销毁后能够返还一个数据给上一个活动。
(1)在第一个activity中如下编写:
- Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
- intent.putExtra("data", "这是我传递的数据");
- //startActivity(intent);
- /**
- * param1:仍然是意图对象
- * param2:请求码,用于在之后的回调中判断数据来源,只要是唯一值就可以了,这里传入1
- */
- startActivityForResult(intent, 1);
(2)第二个activity中重写onBackPressed()方法,此方法表示用户点击了返回键:
- @Override
- public void onBackPressed() {
- //声明意图,但此处的意图仅仅是为了传递数据,并不是要启动Activity
- Intent intent=new Intent();
- intent.putExtra("data_back","这是返回的数据~~~");
- /**
- * 通过setResult方法来返回数据,非常重要
- * param1:返回处理结果,常用的是RESULT_OK,RESULT_CANCELED
- * param2:意图对象,传递数据
- */
- setResult(RESULT_OK,intent);
- //销毁活动
- finish();
- }
(3)在第一个activity中重写回调方法onActivityResult():
- /**
- * 第二个活动处理完成后返回第一个活动的回调函数
- * @param requestCode 启动第二个活动时传入的请求码,即1
- * @param resultCode 第二个活动返回的处理结果
- * @param intent 携带着返回数据的intent
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
- switch (requestCode){
- // 判断请求码是不是我们所传递的
- case 1:
- if (resultCode==RESULT_OK){
- String dataBack= intent.getStringExtra("data_back");
- Toast.makeText(FirstActivity.this, "返回:"+dataBack, Toast.LENGTH_SHORT).show();
- }
- break;
- default:
- }
- }
2.4 生命周期
2.4.1 返回栈
Android中的活动是层叠的,每启动一个活动,就会覆盖在原来的活动上面,然后点击Back键就会销毁最上面的。
Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的集合,这个栈被称作返回栈(Back Stack)
2.4.2 状态
- 运行:当活动处于返回栈的栈顶时,则这个活动是运行状态
- 暂停:当一个活动不处于栈顶、但仍然可见时,这个活动处于暂停状态,
- 停止:当一个活动不在处于栈顶时,而且完全不可见时,则进入了停止状态。当其他地方需要内存时,停止状态的活动极有可能被回收
- 销毁:当一个活动从返回栈中移除后就变成了销毁状态。
2.4.3 生存期
- onCreate():活动初次创建时调用,做初始化工作
- onStart():对用户即将可见的时候调用
- onResume():将要与用户交互的时候调用(此时活动一定处于栈顶,且运行状态)
- onPause():准备去启动或者恢复另一个活动时调用
- onStop():完全不可见时调用
- onDestroy():被销毁之前调用,调用后则变为销毁状态
- onRestart():活动由停止状态变为运行状态之前调用(重新启动)
三种生存期:
(1)完整生存期:onCreate()-->onDestroy()的过程
(2)可见生存期:onStart()-->onStop()的过程
(3)前台生存期:onResume()-->onPause()
2.4.4 活动被回收如何处理
活动在停止状态是容易被系统回收的(比如系统内存不足情况下),如何解决活动被回收时临时数据得不到保存的问题?
Activity 中提供了一个onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用。
- /**
- * Bundle类型的参数提供了一系列的方法用于保存数据
- * @param outState
- */
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- /**
- * put系列方法,依次类推,如putInt....
- * param1:数据的键值
- * param2:数据
- */
- outState.putString("data_key","something you want to save.");
- }
保存完成后可以在onCreate方法里面获取数据(因为活动被回收之后再运行此活动就会重新创建),onCreate方法也有一个Bundle类型的参数savedInstanceState:
- if(savedInstanceState!=null){
- String data=savedInstanceState.getString("data_key");
- //其他操作....
- }
还可以结合intent传递数据(把数据放在Bundle中,再把Bundle放到Intent中)。
2.5 启动模式
- standard
活动默认的启动模式,在此模式下,每当启动一个新的活动,他就会在返回栈中入栈,并处于顶部,系统不会在乎这个活动在返回栈中是否已存在,每次启动都会创建一个活动的实例。
- singleTop
启动活动时如果发现返回栈栈顶已经是该活动(注意是栈顶),则认为可直接使用它,不会再创建活动的实例。但不是在栈顶时,则还会创建实例。
- singleTask
在整个应用程序的上下文中,只存在一个该活动的实例。当启动活动时,首先检查返回栈中是否已存在,若存在,则把该活动之上的活动统统移除出栈,如果没有发现就会创建一个新的实例。
- singleInstance
该模式下的活动会启用一个新的返回栈来管理,这样做的意义就是可以和其他程序之间共享这个活动的实例(用以上三种模式的话,每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈入栈时必然是创建了新的实例,做不到共享的效果)。
2.6 实践技巧
2.6.1 识别当前是在哪一个活动
新建一个BaseActivity继承Activity,然后重写onCreate()方法,让其他的Activity类继承BaseActivity类,在BaseActivity类的onCreate方法中打印:
- Log.d("BaseActivity", getClass().getSimpleName());
2.6.2 随时退出应用
(1)新建一个活动管理类:
- package com.jastar.activitylifecycletest;
- import android.app.Activity;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by admin on 2016/9/29.
- */
- public class ActivityCollector {
- //通过list来暂存活动
- public static List<Activity> activities = new ArrayList<Activity>();
- public static void addActivity(Activity activity) {
- activities.add(activity);
- }
- public static void removeActivity(Activity activity) {
- activities.remove(activity);
- }
- public static void finishAll() {
- for (Activity activity : activities) {
- if (!activity.isFinishing()) {
- activity.finish();
- }
- }
- }
- }
(2)在BaseActivity中重写onCreate()和onDestroy()方法实现向list中添加和移除activity
- ActivityCollector.addActivity(this);
- ActivityCollector.removeActivity(this);
(3)在想退出应用的地方调用ActivityCollector.finishAll()即可。
2.6.3 启动活动的最佳写法
(1)常规的思路:
在FirstActivity中创建意图,存放数据,然后启动SecondActivity——合理且完全没问题,但是不知道需要传递什么数据,需要哪些参数。
(2)更好的思路:
在SecondActivity中添加下面的方法,然后在FirstActivity中调用即可——传递哪些数据参数一目了然,一行代码即可启动活动。
- public static void actionStart(Context context, String param1, String param2) {
- Intent intent = new Intent(context, SecondActivity.class);
- intent.putExtra("param1", param1);
- intent.putExtra("param2", param2);
- context.startActivity(intent);
- }
2.活动(Activity)
2.1 概念
活动是Android的基本组成单位,每个Activity都被定义为一个单独的类,且都继承自基类:android.app.Activity;它是一种包含用户界面的组件,主要用来与用户进行交互(通俗点讲,可以先理解为一个单独的屏幕、一个交互的窗口,但不完全是这样)。
2.2 基本使用
2.2.1 手动创建活动
新建一个类FirstActivity,并继承自基类Activity,重写Activity的onCreate()方法(项目中的任何活动都要重写此方法)。
- public class FirstActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- }
2.2.2 创建加载布局
Android应用讲究逻辑和视图分离,所以最好一个Activity对应一个XML布局文件。
创建activity_first.xml文件(在res-->layout目录下),并添加一个按钮:
- <?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">
- <!--
- android:id==>>给当前的元素定义一个唯一标识符,可在代码中调用。
- @+id/btn_1==>>需要引用一个id,则使用@id/id_name这种语法;需要定义一个id,则使用@+id/id_name这种语法,其他资源一致。
- android:layout_width==>>指定当前元素宽度,同理height为高度
- android:text==>>指定元素显示的文字内容,其实文字应该放在字符串文件中并在这里引用。
- -->
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Button"
- android:id="@+id/btn_1" />
- </LinearLayout>
在代码中调用此视图显示到activity中:
- setContentView(R.layout.activity_first);
2.2.3 在Androidmanifest.xml中注册
所有的活动都要在AndroidManifest.xml中进行注册才能生效:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.jastar.activitytest">
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <!--
- 1.所有活动都需通过activity标签来注册,且放在application标签中
- 2.android:name:指定注册哪一个活动;.FirstActivity是缩写,因为包名在manifest标签中已经定义了
- 3.android:label:活动标题栏的内容,显示在最顶部
- 4.给主活动指定的label还会成为启动器(Launcher)中应用程序显示的名称
- -->
- <activity android:name=".FirstActivity" android:label="This is the firstActivity">
- <intent-filter>
- <!--让活动成为主活动(main入口)就要声明这两句话-->
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
2.2.4 隐藏标题栏
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏,一定要写在setContentView方法前面
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_first);
- }
注意:
使用AS创建的activity隐藏标题栏时无效,是因为AS默认继承的是AppCompatActivity类,换成Activity类即可。
2.2.5 使用Toast悬浮提示
Toast是Android系统提供的提示方式,可将信息展示给用户,并在一段时间后消失。
可给按钮添加点击事件,并提示:
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //隐藏标题栏
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_first);
- /**
- * 1.通过findViewById()来获得界面上的元素,返回View对象,并向下转型
- * 2.通过实现OnClicklistener接口的onClick()来给按钮添加点击事件
- */
- Button btn = (Button) findViewById(R.id.btn_1);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- /**
- * 别忘了调用.show()方法
- * param1:Context上下文,由于活动本身就是,所以传入活动对象即可
- * param2:提示内容
- * param3:提示显示时长,还有LENGTH_LONG
- */
- Toast.makeText(FirstActivity.this, "You click the button!", Toast.LENGTH_SHORT).show();
- }
- });
- }
2.2.6 使用menu菜单
(1)在res下新建menu文件夹
(2)在menu下新建一个名为main的菜单文件(在AS中直接new一个Menu resource file)
(3)AS创建之后默认是一个空的menu标签,需要添加菜单项代码:
- <?xml version="1.0" encoding="utf-8"?>
- <menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/item_add"
- android:title="Add" />
- <item
- android:id="@+id/item_remove"
- android:title="Remove" />
- </menu>
(4)在活动中重写onCreateOptionsMenu()使得菜单展示
- /**
- * 重写展示菜单的方法
- * @param menu
- * @return
- */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- /**
- * 通过此方式给当前活动创建菜单
- * param1:指定哪个资源文件创建菜单
- * param2:指定菜单项将添加到哪个菜单中,直接使用方法中传入的参数即可
- * return:true允许菜单展示,false则不显示
- */
- getMenuInflater().inflate(R.menu.main,menu);
- return true;
- }
(5)在活动中重写onOptionsItemSelected()来响应菜单点击事件
- /**
- * 重写响应菜单点击事件的方法
- *
- * @param item
- * @return
- */
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- //item.getItemId()用来获取选中菜单的id
- switch (item.getItemId()) {
- case R.id.item_add:
- Toast.makeText(FirstActivity.this, "You click add menu!", Toast.LENGTH_SHORT).show();
- break;
- case R.id.item_remove:
- Toast.makeText(FirstActivity.this, "You click remove menu!", Toast.LENGTH_SHORT).show();
- break;
- }
- return true;
- }
2.2.7 销毁活动
返回键可以销毁;当然代码也能:finish();即可
2.3 意图(Intent)
2.3.1 概念
Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务、以及发送广播等场景。
Intent的用法大概分为两种:显式意图和隐式意图。
2.3.2 显式意图
同样方法创建第二个Activity——SecondActivity,并在FirstActivity中按钮点击事件中编写如下代码:
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- /**
- * param1:为当前活动上下文
- * param2:要启动的活动
- */
- Intent intent =new Intent(FirstActivity.this,SecondActivity.class);
- startActivity(intent);
- }
- });
2.3.3 隐式意图
指定了一系列更为抽象的 action和 category等信息,然后交由系统去分析这个 Intent,并帮我们找出合适的活动去启动。
隐式意图需要在activity标签下的intent-filter标签中指定action和category,只有action和category同时匹配的情况下(除去当category配置为默认 android:name="android.intent.category.DEFAULT" 时),该活动才能响应。如:
- <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代码如下:
- Intent intent=newIntent("com.example.activitytest.ACTION_START");
- startActivity(intent);
每个 Intent 中只能指定一个 action,但却能指定多个 category。
- intent.addCategory("...");
2.3.4 隐式意图更多用法
隐式意图不但能打开自己应用的activity,还能打开系统的activity,如浏览器、拨号等等。
- @Override
- public void onClick(View v) {
- /**
- * 1.Intent.ACTION_VIEW 这是系统内置动作,其常量值为android.intent.action.VIEW
- * 2.通过Uri.parse()方法将网址解析为Uri对象
- * 3.调用setData将Uri对象传递。
- */
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse("http://www.baidu.com"));
- startActivity(intent);
- //打电话
- //Intent intent=new Intent(Intent.ACTION_DIAL);
- //intent.setData(Uri.parse("tel:10086"));
- //startActivity(intent);
- }
2.3.5 向下一个Activity传递数据
(1)第一个activity:
- Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
- //使用putExtra()方法传递数据
- intent.putExtra("data", "这是我传递的数据");
- startActivity(intent);
(2)第二个activity:
- //通过getIntent()方法获取启动当前activity的意图对象
- Intent intent = getIntent();
- //什么类型的数据就get类型Extra("");
- String data = intent.getStringExtra("data");
- Log.d("SecondActivity", data);
2.3.6 返回数据给上一个Activity
Activity中提供了一个startActivityForResult()方法,此方法期望在活动销毁后能够返还一个数据给上一个活动。
(1)在第一个activity中如下编写:
- Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
- intent.putExtra("data", "这是我传递的数据");
- //startActivity(intent);
- /**
- * param1:仍然是意图对象
- * param2:请求码,用于在之后的回调中判断数据来源,只要是唯一值就可以了,这里传入1
- */
- startActivityForResult(intent, 1);
(2)第二个activity中重写onBackPressed()方法,此方法表示用户点击了返回键:
- @Override
- public void onBackPressed() {
- //声明意图,但此处的意图仅仅是为了传递数据,并不是要启动Activity
- Intent intent=new Intent();
- intent.putExtra("data_back","这是返回的数据~~~");
- /**
- * 通过setResult方法来返回数据,非常重要
- * param1:返回处理结果,常用的是RESULT_OK,RESULT_CANCELED
- * param2:意图对象,传递数据
- */
- setResult(RESULT_OK,intent);
- //销毁活动
- finish();
- }
(3)在第一个activity中重写回调方法onActivityResult():
- /**
- * 第二个活动处理完成后返回第一个活动的回调函数
- * @param requestCode 启动第二个活动时传入的请求码,即1
- * @param resultCode 第二个活动返回的处理结果
- * @param intent 携带着返回数据的intent
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
- switch (requestCode){
- // 判断请求码是不是我们所传递的
- case 1:
- if (resultCode==RESULT_OK){
- String dataBack= intent.getStringExtra("data_back");
- Toast.makeText(FirstActivity.this, "返回:"+dataBack, Toast.LENGTH_SHORT).show();
- }
- break;
- default:
- }
- }
2.4 生命周期
2.4.1 返回栈
Android中的活动是层叠的,每启动一个活动,就会覆盖在原来的活动上面,然后点击Back键就会销毁最上面的。
Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的集合,这个栈被称作返回栈(Back Stack)
2.4.2 状态
- 运行:当活动处于返回栈的栈顶时,则这个活动是运行状态
- 暂停:当一个活动不处于栈顶、但仍然可见时,这个活动处于暂停状态,
- 停止:当一个活动不在处于栈顶时,而且完全不可见时,则进入了停止状态。当其他地方需要内存时,停止状态的活动极有可能被回收
- 销毁:当一个活动从返回栈中移除后就变成了销毁状态。
2.4.3 生存期
- onCreate():活动初次创建时调用,做初始化工作
- onStart():对用户即将可见的时候调用
- onResume():将要与用户交互的时候调用(此时活动一定处于栈顶,且运行状态)
- onPause():准备去启动或者恢复另一个活动时调用
- onStop():完全不可见时调用
- onDestroy():被销毁之前调用,调用后则变为销毁状态
- onRestart():活动由停止状态变为运行状态之前调用(重新启动)
三种生存期:
(1)完整生存期:onCreate()-->onDestroy()的过程
(2)可见生存期:onStart()-->onStop()的过程
(3)前台生存期:onResume()-->onPause()
2.4.4 活动被回收如何处理
活动在停止状态是容易被系统回收的(比如系统内存不足情况下),如何解决活动被回收时临时数据得不到保存的问题?
Activity 中提供了一个onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用。
- /**
- * Bundle类型的参数提供了一系列的方法用于保存数据
- * @param outState
- */
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- /**
- * put系列方法,依次类推,如putInt....
- * param1:数据的键值
- * param2:数据
- */
- outState.putString("data_key","something you want to save.");
- }
保存完成后可以在onCreate方法里面获取数据(因为活动被回收之后再运行此活动就会重新创建),onCreate方法也有一个Bundle类型的参数savedInstanceState:
- if(savedInstanceState!=null){
- String data=savedInstanceState.getString("data_key");
- //其他操作....
- }
还可以结合intent传递数据(把数据放在Bundle中,再把Bundle放到Intent中)。
2.5 启动模式
- standard
活动默认的启动模式,在此模式下,每当启动一个新的活动,他就会在返回栈中入栈,并处于顶部,系统不会在乎这个活动在返回栈中是否已存在,每次启动都会创建一个活动的实例。
- singleTop
启动活动时如果发现返回栈栈顶已经是该活动(注意是栈顶),则认为可直接使用它,不会再创建活动的实例。但不是在栈顶时,则还会创建实例。
- singleTask
在整个应用程序的上下文中,只存在一个该活动的实例。当启动活动时,首先检查返回栈中是否已存在,若存在,则把该活动之上的活动统统移除出栈,如果没有发现就会创建一个新的实例。
- singleInstance
该模式下的活动会启用一个新的返回栈来管理,这样做的意义就是可以和其他程序之间共享这个活动的实例(用以上三种模式的话,每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈入栈时必然是创建了新的实例,做不到共享的效果)。
2.6 实践技巧
2.6.1 识别当前是在哪一个活动
新建一个BaseActivity继承Activity,然后重写onCreate()方法,让其他的Activity类继承BaseActivity类,在BaseActivity类的onCreate方法中打印:
- Log.d("BaseActivity", getClass().getSimpleName());
2.6.2 随时退出应用
(1)新建一个活动管理类:
- package com.jastar.activitylifecycletest;
- import android.app.Activity;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by admin on 2016/9/29.
- */
- public class ActivityCollector {
- //通过list来暂存活动
- public static List<Activity> activities = new ArrayList<Activity>();
- public static void addActivity(Activity activity) {
- activities.add(activity);
- }
- public static void removeActivity(Activity activity) {
- activities.remove(activity);
- }
- public static void finishAll() {
- for (Activity activity : activities) {
- if (!activity.isFinishing()) {
- activity.finish();
- }
- }
- }
- }
(2)在BaseActivity中重写onCreate()和onDestroy()方法实现向list中添加和移除activity
- ActivityCollector.addActivity(this);
- ActivityCollector.removeActivity(this);
(3)在想退出应用的地方调用ActivityCollector.finishAll()即可。
2.6.3 启动活动的最佳写法
(1)常规的思路:
在FirstActivity中创建意图,存放数据,然后启动SecondActivity——合理且完全没问题,但是不知道需要传递什么数据,需要哪些参数。
(2)更好的思路:
在SecondActivity中添加下面的方法,然后在FirstActivity中调用即可——传递哪些数据参数一目了然,一行代码即可启动活动。
- public static void actionStart(Context context, String param1, String param2) {
- Intent intent = new Intent(context, SecondActivity.class);
- intent.putExtra("param1", param1);
- intent.putExtra("param2", param2);
- context.startActivity(intent);
- }