Android入门笔记(活动 Activity)

活动(Activity)是一种可以包含用户界面的组件,主要用于和用户进行交互,一个应用程序中可以包含零个或多个活动。

Android 程序的设计讲究逻辑和视图分离,最好每一个活动能对应一个布局。一个Activity 的用法如下:

  • 新建一个 Activity
  • Activity 调用 setContentView() 方法来给当前活动加载一个布局,该方法需要一个布局文件 id
  • 新建一个 Activity后,AS 会默认自动创建和加载对应的布局资源文件。而项目中添加的任何资源都会在 R 文件中生成一个相应的资源 id,然后将该值传入 setContentView() 方法即可。(一般的 AS 都会代劳)
  • 最后所有的活动都要在 AndroidManifest.xml 中进行注册才能生效,活动的注册声明需要放在 <application> 标签中,并通过 <activity> 标签对活动进行注册,如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="top.seiei.aboutactivity">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!-- 设置活动 -->
        <activity
            android:name=".MainActivity"
            android:label="this is my first activity">
        	<!-- android:name 指定具体注册哪个活动 -->
        	<!--
 				而 .MainActivity 是 top.seiei.aboutactivity.MainActivity 的缩写,
        		在最外层的 mainfest 标签已经声明了 package 包名属性为 `top.seiei.aboutactivity`
        	-->
            <!-- 设置主程序入口 -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

1 销毁一个活动

手机上按 Back 键,即可销毁当前的活动,而在代码中,Activity 类提供了一个 finish() 方法用于销毁活动。

2 活动之间的跳转

活动之间如何跳转?此时就需要使用到 Intent(意图)。
Intent 是 Android 程序中各个组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务及发送广播等场景。
Intent 可以分为两种,显式 Intent 和 隐式 Intent

2.1 显式 Intent

Intent 的构造函数由很多,其中一个 Intent(Context packageContext, Class<?> cls) 接收两个参数,分别是:

  • Context,启动活动的上下文
  • 指定想要启动的目标 Activity

代码如下:

Button button1 = (Button) findViewById(R.id.goSecondActivity);
button1.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View v) {
		// 显式 Intent
		// 创建 Intent,第一个参数为启动活动的上下文,第二个则是指定想要启动的目标活动
		Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        startActivity(intent);
    }
});

使用 startActivity() 方法用于启动这个 Intent,使用这种方式启动活动,Intent 的 “意图” 十分明显,因此称为 显式 Intent

2.2 隐式 Intent

相比于显式 Intent 直接地传入指明想要启动的目标活动,隐式 Intent 则只是指定一系列更为抽象的 actioncategory 等信息,然后交由系统去分析这个 Intent,并找出合适的活动去启动。

  • action 标识用来说明这个 Activity 可以执行哪些动作
  • category 标识用来说明这个 Activity 在哪个环境中才能被激活,不属于这个环境的,不能被激活。
  • 每个 Intent 只能指定一个 action,但能指定多个 category

AndroidManifest.xml 文件中通过 <activity> 标签配置 <intent-filter> 可以设置到这些内容,代码如下:

<activity android:name=".SecondActivity">
	<intent-filter>
		<!-- 隐式 Intent -->
		<!-- category 标识用来说明这个activity在哪个环境中才能被激活,不属于这个环境的,不能被激活。 -->
		<!-- category android:name="android.intent.category.DEFAULT" 表示默认的category,不能删除 -->
		<category android:name="android.intent.category.DEFAULT"/>
		<!-- action 标识用来说明这个activity可以执行哪些动作 -->
		<action android:name="thisIsAction"/>
        <category android:name="thisIsCategory"/>
	</intent-filter>
</activity>

在代码中使用 Intent 的另一个构造函数,直接将 action 的字符串传进去,同时通过生产的 Intent 调用 addCategory() 传入 category 的字符串来筛选 category 属性,代码如下:

Intent intent = new Intent("thisIsAction");
intent.addCategory("thisIsCategory");
startActivity(intent);

2.3 更多隐式 Intent 的用法

通过使用隐式 Intent,不仅可以启动自己程序中的活动,还可以启动其它程序的活动,这可以达到 Android 多个程序之间的功能共享,所以,actioncategory 的命名应该使用包名的形式,做到规范。

说以下代码:

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

这是一个启动手机浏览器打开百度,其中:

  • Intent.ACTION_VIEW 这是一个 Android 系统内置的 action 动作,通过 Uri.parse() 方法将一个网址字符串解析为一个 Uri 对象,在调用 setData() 传入 Uri 对象。

setData() 方法主要指定当前 Intent 正在操作的数据,与之对应 的是 <intent-filter> 标签中配置的 <data> 标签,它用于规定指明当前设置的活动能够响应什么类型的数据,它主要可以配置一下内容:

  • android:sheme:指定数据的协议部分,如 http
  • android:host:指定数据的主机名,如 www.baidu.com
  • android:port:指定数据的端口
  • android:mimeTye:指定可以处理的数据类型

又如调用电话代码如下:

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

3 活动之间传递数据

3.1 向下一个活动传递数据

Intent 中提供一系列 putExtra() 方法的重载,可以将传递的数据存在 Intent 中,在启动活动后,只需将数据从 Intent 中获取出来就可以。
传递数据:

button1.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(MainActivity.this, SecondActivity.class);
		intent.putExtra("saveStr", "ThisIsStr");
		startActivity(intent);
	}
});

获取数据:

// 获取传递信息
Intent intent = getIntent();
String saveStr = intent.getStringExtra("saveStr");
Toast.makeText(SecondActivity.this, "这是传递过来的数据:" + saveStr, Toast.LENGTH_SHORT).show();

3.2 返回数据到上一个活动

返回数据到上一个活动就需要使用到 Activity 中的另一个启动活动的方法 startActivityForResult()。它也是用于启动活动,但同时它期待启动活动销毁时能返回一个结果。它接受一个 int 类型请求码,这个只要保证唯一性可以随意设置,作用是在触发活动销毁回调时辨识具体是哪个活动返回的数据。
所以总的具体步骤是:

1、父活动调用 startActivityForResult() 方法启动子活动:

Button button1 = (Button) findViewById(R.id.goSecondActivity);
button1.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View v) {
		// 显式 Intent
		// 构建函数参数为:
		Intent intent = new Intent("thisIsAction");
		// 返回结果給上层活动
		// 接受两个参数,一个是 intent,另一个是请求码,用于之后回调中判断数据的来源
		startActivityForResult(intent, 1);
	}
});

2、子活动在销毁时,创建 Intent 将要传递的数据设置在里面,调用 setResult() 方法设置返回结果状态及返回内容,其中状态码有:

  • RESULT_OK:成功
  • RESULT_CANCELD:失败
// 退出当前活动
Button button = (Button) findViewById(R.id.mySecondButton);
button.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		// 创建新的Intent,传递数据回上一个活动
		Intent intent = new Intent();
		intent.putExtra("returnStr", "thisIsReturnStr");
		// 专门返回数据给上活动
		// 第一个参数表示处理结果,有 RESULT_OK 和 RESULT.CANCELED
		// 第二个参数为 带有数据的 Intent
		setResult(RESULT_OK, intent);
		finish();
	}
});
  • 当活动被销毁之后会回调上一个活动的 onActivityResult() 方法,它接受三个参数,分别是:
    • requestCode:启动活动时设置请求码,用于识别消息来源,究竟是哪个子活动被销毁
    • resultCode:活动销毁时设置的处理结果状态码
    • intent:活动销毁时设置的 Intent 对象
/**
* 子活动被销毁后的回调方法
* @param requestCode 启动子活动时传入的请求码
* @param resultCode 返回数据时传入的处理结果
* @param data 携带返回信息的 Intent
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	// 请求码等于设置子活动时设置的
	if (requestCode == 1) {
		// 子活动返回数据的处理结果是成功
		if (resultCode == RESULT_OK) {
			String result = data.getStringExtra("returnStr");
			Toast.makeText(MainActivity.this, "这是子活动返回的数据:" + result, Toast.LENGTH_SHORT).show();
		}
	}
}

如果用户是点击 Back 键回到前一个活动,此时可重写 onBackPressed() 方法解决问题,该方法当用户按下 Back 键是会执行

4 活动的说明周期

Android 中的活动是可以重叠的,每启动一个活动就会覆盖在原活动之上,点击 Back 键或执行 finish() 方法会销毁最上面的活动,下面的活动就会重新显示出来。
Android 是使用任务 Task 来管理活动的,一个任务就是一组放在栈里的活动集合,这个栈就叫做 返回栈

4.1 活动状态

每个活动在生命周期中最多可能有四个状态:

  • 运行状态
    当一个活动位于返回栈的栈顶时,这时活动就位于运行状态。
  • 暂停状态
    当一个活动不再位于返回栈的栈顶时,但仍然可见,这时活动就进入了暂停状态。(不是每个活动就占满整个屏幕,比如说对话框),系统有可能回收这里的内容
  • 停止状态
    当一个活动不再位于返回栈的栈顶,并处于完全不可见的时候,就进入了停止状态(系统有可能回收这里的内容)
  • 销毁状态
    当一个活动从返回栈中消除后就会变成销毁状态。系统最倾向回收这种状态的活动,从而保证手机的内存充足

4.2 活动的生存期

在这里插入图片描述
上图是活动的生命周期,Activity 类定义了 7 个回调方法,覆盖了活动生命周期的每个环节:

  • onCreate():在 活动第一次创建 的时候调用,应该在这个方法中完成活动的初始化操作,如加载布局、绑定事件等
  • onStart():活动由 不可见变为可见 的时候调用
  • onResume():在活动准备好和用户进行交互的时候调用,此时活动一定处于 运行状态(与 onStart() 的区别看图)
  • onPause():在系统准备去启动或恢复 另一个活动 时调用(此时活动处于暂停状态)。通常会在这个方法中释放一些消耗 CPU 的资源,以及保存一些关键数据
  • onStop():在活动完全不可见的时候调用(此时活动处于停止状态),一般会完成释放资源的操作
  • onDestroy():在活动被销毁之前调动,一般会完成释放内存的操作
  • onRestart():在活动由 停止状态变为运行状态 之前调用

4.3 活动被回收

当一个活动进入停止状态,它就有可能被系统回收,比如应用中活动A启动了活动B,A处于停止状态,此时内存不足,系统把A回收了,而用户此时从B返回A,结果还是会正常地显示A,只不过此时活动A并不会执行 onRestart() 方法,而是执行 onCreate() 方法,即此时活动A重新创建了一次。
那么导致的问题可能是活动A中的临时数据和状态都会被回收掉。
解决方法就是 Activity 中的 onSaveInstanceState() 回调方法,这个方法可以保证在活动被回收之前一定被调用,它接收一个 Bundle 类型的参数,它用于存储数据,有诸如:putString()putInt() 等方法保存数据,接收两个值,第一个参数是键,第二个参数是值。
数据保存下来之后,在对应活动的 onCreate() 方法中的 Bundle 参数就会带有之前所保存的全部数据。

Intent 还可结合 Bundle 一起用于传递数据,将数据保存在 Bundle 对象中,并将 Bundle 对象存在 Intent 里。

4.4 活动的启动模式

活动的启动模式有四个,分别是:standardsingleTopsingleTasksingleInstance,这些模式可以在 AndroidMainFEST.xml 文件中通过 <activity> 标签 指定 android:launchMode 属性 来选择启动模式。

  • standard
    standard 是活动默认的启动模式,每当启动一个新的活动,新的活动就会自动添加到返回栈的栈顶位置,系统不会在乎该活动是否已经存在,每次启动都会创建该互动的一个新的实例
  • singleTop
    设置了 singleTop 模式,系统在启动活动时如果发现返回栈的栈顶是该活动,则会继续使用它
  • singleTask
    设置了 singleTask 模式,系统在启动活动时如果发现返回栈内有该活动,则会直接使用该实例,并把在活动之上的所有活动统统出栈,如果没发现就会创建一个新的活动实例
  • singleInstance
    设置了 singleInstance 模式,系统在启动活动时会创建一个新的返回栈来管理该活动,这通常用于允许其他程序的调用

Toast

Toast 是 Android 系统提供的一种提醒方式。下面为例子代码:

Button button1 = (Button) findViewById(R.id.goSecondActivity);
button1.setOnClickListener(new View.OnClickListener(){
	@Override
	public void onClick(View v) {
		Toast.makeText(MainActivity.this, "add", Toast.LENGTH_SHORT).show();
	}
});

Toast 的用法是:通过静态方法 makeText() 创建一个 Toast 对象,该方法接收三个参数:

  • Context,上下文
  • 显示文本
  • 显示时长,有两个内置常量 Toast.LENGTH_SHORTToast.LENGTH_LONG

该静态方法返回一个 Toast 对象直接调用 show() 就可以将 Toast 显示出来。

在活动中,可以通过 findViewById() 方法获取在布局文件中定义的元素,它返回的是 View 对象,所以通常需要强制转型。

Menu

Menu 的用法:首先在 res 目录新建 menu 文件夹,然后右键新增一个 Menu resource file 文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 其中 android:title 表示菜单项的名称 -->
    <item
        android:id="@+id/addItem"
        android:title="Add"></item>
    <item
        android:id="@+id/removeItem"
        android:title="Remove"></item>
</menu>

然后在 Activity 文件中 重写 onCreateOptionsMenu() 方法(AS 重写方法快捷键 Ctrl + O),代码如下:

/**
	* 添加菜单
    * @param menu
    * @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
	// getMenuInflater 方法获取 MenuInflater 对象
    // inflate 方法给当前活动创建菜单
   	// 第一个参数是资源文件,第二个指定菜单项添加到哪个 Menu 对象中,这里使用重写方法中传入的 menu 参数
	getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

定义菜单响应时间,需要在 Activity 重写 onOptionsItemSelected() 方法:

/**
	* 菜单项的点击事件
    * @param item
    * @return
*/
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
	// getItemId() 获取点击激活的 item 的 id
	switch (item.getItemId()) {
		case R.id.addItem:
			Toast.makeText(MainActivity.this, "add", Toast.LENGTH_SHORT).show();
            break;
		case R.id.removeItem:
			Toast.makeText(MainActivity.this, "remove", Toast.LENGTH_SHORT).show();
			break;
    }
	return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值