《第一行代码》笔记之 Activity

Activity

本篇内容整理自郭霖的 《第一行代码》

文章目录

  • Activity
    • 认识活动
    • 活动的基本用法
      • 一. 创建活动的步骤
      • 二. 在活动中隐藏标题栏
      • 三. 活动中使用Toast(简易消息提示框)
      • 四. 在活动中使用Menu
      • 五. 销毁一个活动
    • 使用Intent在活动中穿梭
      • 一. 使用显式的Intent
      • 二. 使用隐式Intent
      • 三. 更多隐式Intent的用法
      • 四. 向下一个活动传递数据
      • 五. 返回数据给上一个活动
    • 活动的生命周期
      • 1. 返回栈
      • 2. 活动状态
      • 3. 活动的生存期
      • 4.活动被回收,数据丢失?
    • 活动的启动模式
      • standard
      • singleTop
      • singTask
      • singleInstance
    • 关于使用活动的一些技巧
      • 如何知晓当前是在哪一个活动?
      • 随时随地退出程序
      • 启动活动的最佳写法

认识活动

  • Activity(活动)是一种可以包含用户界面的组件,主要用于和用户进行交互

活动的基本用法


一. 创建活动的步骤

  1. 任何活动都要重写onCreate()方法
  2. 加载布局
    引入id: @id/id_xxx
    创建id: @+id/id_xxx
    match_parent 表示让当前元素和父元素一样
    match_content 表示当前元素刚好包含里面内容就好
    setContentView() 方法给活动加载一个布局
    AndroidSDK提供一个android包下面的R文件,不能引用
  3. AndroidManifest注册
  <application>
	  <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>

android:label 不仅仅会成为标题栏的内容,还会成为启动器(LAUNCHER)中应用程序显示的名称。
android.intent.action.MAIN 是主活动,点击图标首先打开的就是此活动


二. 在活动中隐藏标题栏

requestWindowFeature(Window.FEATURE_NO_TITLE);

此句代码必须在 setContentView() 之前执行,否则报错


三. 活动中使用Toast(简易消息提示框)

public void onClick(){
	Toast.makeText(FirstActivity.this,"point out",Toast.LENGTH_SHORT).show();
}

通过静态方法makeText()创建出Toast对象,然后调用show()将Toast显示出来就好了。

makeText() 三个参数:
第一个:Context :Toast要求的上下文本
第二个: Toast显示的文本内容
第三个: 显示的时长:Toast.LENGTH_SHORT 和 Toast.LENGTH_LONG


四. 在活动中使用Menu

  1. 在res目录下新建一个menu文件夹
  2. 创建xml文件:main.xml
  3. 必要代码

1、在main.xml文件中添加代码

<menu xmlns:android="http://schemas.android.com/apk/res/android">
		<item
			android:id="@+id/add_item"
			android:title="Add" />
		<item
			android:id="@+id/remove_item"
			android:title="Remove" />
	menu>

2、重写Activity中的 onCreateOptionsMenus() 方法

public boolean onCreateOptionsMenu(Menu menu){
	getMenuInflater().inflate(R.menu.main, menu);
	return true;
}

inflate()两个参数:
第一个: 来创建菜单的资源文件
第二个:onCreateOptionsMenus() 方法中传入的menu
4. 对xml文件里面的item设置点击事件


五. 销毁一个活动

  • 按一下Back键即可
  • finish() 方法

使用Intent在活动中穿梭


一. 使用显式的Intent

  • Intent有多个构造函数的重载

eg:跳转另一个活动

public void onClick(){
	Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
	startActivity(intent); //专门启动活动的方法
}

二. 使用隐式Intent

  • 指定抽象的 action 和 category 等信息,让系统去分析这个Intent
  1. 在AndroidManifest中的.SecondActivity写入 action 和 category 等信息
<activity android:name=".SecondActivity"
	>
		<action android:name="com.package.name.ACTION_START" />
		<category android:name="android.intent.category.DEFAULT" /> <--此为默认-->
		<category android:name="com.package.name.MY_CATEGORY" />
	intent-filter>
activity>
  1. 只有 同时匹配上 Intent 中指定的 action 和 category 时,这个活动才能响应 Intent
    eg:FirstActivity中按钮的点击事件
public void onClick(){
	Intent intent = new Intent("com.package.name.ACTION_START");
	intent.addCategory("com.package.name.MY_CATEGORY");
	startActivity(intent); //此方法会自动将默认的category添加进intent中
}
//每一个Intent中只能指定一个action,但能指定多个category

三. 更多隐式Intent的用法

  • 使用隐式Intent, 不但可以启动自己程序内的活动,还能启动其他应用程序的活动。因此 Android 多个应用之间的功能共享成为可能

    例1:
    自己的应用需要打开网页,可调用系统的浏览器。在 FirstActivity 中代码实现如下:

public void onClick(){
	
	Intent intent = new Intent(Intent.ACTION_VIEW); // intent构造方法所传入的参数为Android 系统内置的动作,其常量为android.intent.action.VIEW
	
	intent.setData(Uri.parse("http://www.baidu.com")); // Uri.parse()将网址解析为一个Uri对象
	//setData()方法接收uri对象,用于指定当前Intent正在操作的数据
	
	startActivity(intent);
}
  • 可以在 AndroidManifest 对应活动中的 标签配置一个标签,用于更精准地指定当前活动能够响应什么类型的数据。
    标签可配置如下内容:
    1. android : scheme 用于指定数据的协议部分,如上例中 http 部分

    2. android : host 用于指定数据的主机部分,如上例中的 www.baidu.com 部分

    3. android : path 用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容

    4. android : mimeType 用于指定可以处理的数据类型,允许使用通配符的方式进行指定

只有当前 标签中指定的内容和 Intent 中携带的 Data 完全一致的时,当前活动才能响应该 Intent
eg:新建个 ThirdActivity ,在 AndroidManifest 中对它进行注册

<activity android:name=".ThirdActivity">
	<intent-filter>
		<action android:name="android.intent.action.VIEW" />
		<category android:name="android.intent.category.DEFAULT" />
		<data android:scheme="http" /> <--data标签中指定了数据协议必须是http协议,这样ThirdActivity应该就和浏览器一样能够响应一个打开网页的Intent-->
	intent-filter>
activity>

如此一来,执行 FirstActivity 的 onClick() 方法就不单单打开一个系统的浏览器去显示网页。而是跳出弹窗,让用户选择运用什么activity来执行这个intent:系统浏览器 or ThirdActivity ?因为系统浏览器和 ThirdActivity 都含有scheme=“http”,它们都可以响应这个打开网页的 Intent

简单理解:FirstActivity 中 intent 发出 http 协议,被含有scheme=“http”的活动响应

例2:
除了指定 http 协议外,我们还可以指定很多其他协议,比如 geo 表示显示地理位置、 tel 表示 拨打电话

public void onClick(){
	Intent intent = new Intent(Intent.ACTION_DIAL); // 指定了intent 为 Intent.ACTION_DIAL 这又是一个 Android 系统内置动作
	intent.setData(Uri.parse("tel:10086")); // 然后 data 部分指定了协议是 tel
	startActivity(intent);
}

执行这个onClick(),拨号页面这个 Activity 就响应了tel,因此打开拨号窗口


四. 向下一个活动传递数据

  • Intent 中提供了一系列的 putExtra() 方法重载,可以把数据暂存在 Intent 中,启动另一个活动后,只需把这个数据从 Intent 取出即可
  1. 存数据:intent.putExtra("key", data);
    putExtra() 接收的两个参数
    第一个:键
    第二个:传递的数据

  2. 取数据:

Intent intent = getIntent(); //获取用于启动本活动的 Intent
String data = intent.getStringExtra("key");
//通过键获取数据,除了 getStringExtra() 外,还有 getIntExtra()、getBooleanExtra();通过传入的数据决定使用哪个

五. 返回数据给上一个活动

  • Activity中还有一个 **startActivityForResult() **方法也是用于启动活动的,但它在启动的活动被销毁后会返回一个结果给上一个活动

例:
FirstActivity

public void onClick(){
	Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
	startActivityForResult(intent, 1); // 第二个参数为请求码 requestCode ,用于在之后的回调中判断数据的来源
}

SecondActivity

public void onClick(){
	Intent intent = new Intent();
	intent.putExtra("key", "你好!");
	setResult(RESULT_OK, intent); // 专门用于向上一个活动返回数据的,有两参数。第一个:向上一个活动返回处理结果;  第二个:把带参数的 intent 传过去
	finish();
}

或者使用 onBackPressed()方法,此方法在点击 Back 键后调用。因 Back 键也是销毁活动的,因此在最好也在此方法中添加活动被销毁前要返回的数据

FirstActivity
由于是用 startActivityForResult() 启动 SecondActivity 的,所以在 SecondActivity 被销毁后会回调上一个活动的 onActivityResult() 方法

protected void onActivityResult(int requestCode, int resultCoded, Intent data){
	switch(requestCode){
		case 1: // 请求码,判断数据是否从 SecondActivity 中来的
			if(resultCode == RESULT_OK){ // 判断处理结果是否成功
				String returnedData = data.getStringExtra("key");
			}
			break;
		default:
	}
}

活动的生命周期


1. 返回栈

  • 栈是一种后进先出的数据结构,在默认情况下,每当我们启动了一个新的活动,它会在返回栈中入栈,并处于栈顶的位置

2. 活动状态

  1. 运行状态:活动处于栈顶,系统最不愿回收

  2. 暂停状态:活动不处于栈顶,仍然可见(不占满屏幕的活动,比如对话框的形式出现)

  3. 停止状态:活动不处于栈顶,完全不可见(活动保留相应状态和成员变量,其他地方需要内存即刻回收)

  4. 销毁状态:活动从栈中移走


3. 活动的生存期

  • onCreate():活动第一次创建的时候被调用
  • onStart():活动由不可见变为可见
    • onResume():准备好与用户进行交互的时候调用(处于运行状态)

    • onPause():系统准备去启动或者恢复另一个活动的时候调用

  • onStop():在活动完全不可见的时候调用
  • onDestory():活动被销毁之前调用
  • onRestart():活动重新启动(停止状态变运行状态)
    《第一行代码》笔记之 Activity_第1张图片

4.活动被回收,数据丢失?

  • onSaveInstanceState() 回调方法在活动被回收之前调用,可解决活动被回收,数据得不到保存的问题。
    onSaveInstanceState()方法携带一个 Bundle 参数,此参数提供一系列的方法来保存数据:puString()、putInt() 等。每一个方法含有两个参数,类似 Intent 传递数据所采用的存放数据的方法。第一个:键;第二个:data
    Activity的onCreate() 方法一直都有 Bundle 类型的参数,默认为 null ,如果 onSaveInstanceState() 中保存了数据,那么 Bundle 中就存在活动被销毁前的数据

简单理解:Bundle 类型的参数在 onSaveInstanceState()onCreate() 中是共享的,前一个在活动销毁前存数据,后一个在活动开始前取数据

活动的启动模式

  • 活动的启动模式一共有4种,standard、singleTop、singTask、singleInstance,在AndroidManifest.xml中通过 标签指定 android:launchMode 属性来选择启动模式。

standard

默认的启动模式。使用此模式,系统不会在乎这个活动是否已经在返回栈中,每次启动都会创建该活动的一个新的实例
《第一行代码》笔记之 Activity_第2张图片


singleTop

使用此模式。在启动活动时如果发现返回栈的栈顶已经是该活动前提),则认为可以直接使用它,不会再创建新的活动实例
《第一行代码》笔记之 Activity_第3张图片


singTask

使用此模式。每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的活动统统出栈,如果没有发现就会创建一个新的活动实例。
《第一行代码》笔记之 Activity_第4张图片


singleInstance

使用此模式启动的活动,会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,(这个活动)都共用的同一个返回栈。可以解决共享活动实例的问题(即允许其他程序来调用这个活动
《第一行代码》笔记之 Activity_第5张图片

关于使用活动的一些技巧


如何知晓当前是在哪一个活动?

1、 新建一个 BaseActivity 继承 Activity
2、 在 BaseActivity 中重写 onCreate() 方法:

protected void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	log.d("BaseActivity", getClass().getSimpleName()); // getClass().getSimpleName() 方法就是获取当前活动的类名
}

3、让所有活动都继承BaseActivity


随时随地退出程序

  • 只需要一个专门的集合类,对所有活动进行管理即可

1、新建一个 ActivityCollector 类作为活动管理器

public class ActivitykCollector{
	
	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){
			activity.finish();
		}
	}
}

2、修改 BaseActivity(如何知晓当前是哪一个活动中的)代码

public class BaseActivity extends Activity{
	
	protected void onCreated(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		
		ActivityCollector.addActivity(this);	
	}
	
	protected void onDestroy(){
		super.onDestroy();
		ActivityCollector.removeActivity(this);
	}
}

3、只要所有活动在继承 BaseActivity 基础上,不管什么地方退出程序只需要调用 ActivityCollector.finishAll()


启动活动的最佳写法

  • 如何简化启动代码,且一下子就让其他人明白他将要启动的活动需要哪一些参数(假设 SecondActivity 是你开发的,而 FirstActivity 是由你同事开发,他需要启动 SecondActivity 但是他不知道 SecondActivity 需要哪些必要参数

SecondActivity

public class SecondActivity extends BaseActivity{
	
	public static void actionStart(Context context, String data_1, String data_2){
		Intent intent = new Intent(context, SecondActivity.class);
		intent.putExtra("param_1", data_1);
		intent.putExtra("param_2", data_2);
		context.startActivity(intent);
	} // 启动本活动的函数。这样处理,其他活动启动本活动的时候就可以把必要的参数也带进来
}

FirstActivity

public void onClick(){
	SecondActivity.actionStart(FirstActivity.this, "data_1", "data_2");
} // 启动 SecondActivity 活动

你可能感兴趣的:(Android基础)