Android四大组件之Activity

1、Activity概述

1.1、Activity简介

Activity:活动,是Android四大组件之一。在Android中,Activity代表手机屏幕的一屏,或是平板电脑中的一个窗口,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。

Activity是一个负责与用户交互的组件,Android程序的设计讲究逻辑和视图分离,可以通过setContentView(View)来显示指定视图。

2、Activity的基本用法

2.1、布局

如果是在 XML中引用一个 id,就使用@id/id_name这种语法,如果是在 XML中 定义一个 id,则要使用@+id/id_name 这种语法。

2.2、清单文件说明

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.helloworld"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="19" />

 

    <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>

               <action android:name="android.intent.action.MAIN" />

 

              <category android:name="android.intent.category.LAUNCHER" />

           </intent-filter>

        </activity>

    </application>

</manifest>

通过清单文件中的以上代码可知:

1最外层的<manifest>标签中通过 package 属性指定了程序的包名com.example.helloworld,因此在注册活动时可以省略包名,直接使用.MainActivity.

2android:label指定活动中标题栏的内容,标题栏是显示在活动最顶部的,注意的是,给主活动指定的 label不仅会成为标题栏中的内容,还会成为启动器(Launcher)中应用程序显示的名称。

3) intent-filter里的两行代码

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER"

表示 MainActivity是这个项目的主活动,在手机上点击应用图标,首先启动的就是这个活动

2.3、android去掉标题栏

方法一:在 onCreate()方法中添加如下代码: 

requestWindowFeature(Window.FEATURE_NO_TITLE); 

注意这句代码一定要在 setContentView()之前执行,不然会报错。

方法二:可以将整个应用设置成无标题栏

<application

    android:allowBackup="true"

    android:icon="@drawable/ic_launcher"

    android:label="@string/app_name"

android:theme="@android:style/Theme.NoTitleBar" >

2.4、在Activity中使用 Menu

主要通过两个步骤完成: 

1onCreateOptionsMenu()在活动 中创建菜单

@Override

public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.main, menu);

    return true;//表示允许显示创建的菜单

}

2onOptionsItemSelected():定义菜单响应事件

3、Intent在Activity中的使用

Intent表示意图的意思,是Android各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent可被用于启动活动、启动服务、以及发送广播。Intent的用法大致可以分为两种,显式 Intent和隐式 Intent。 

3.1、使用显式 Intent

显示intent通过组件的ComponentName来指定目标组件。应用程序在自己内部跳转的时候,一般用显式意图。效率高。

Intent(ContextpackageContext,Class<?>cls)

这个构造函数接收两个参数,第一个参数 Context要求提供一个启动活动的上下文,第二个参数 Class则是指定想要启动的目标活动,通过这个构造函数就可以构建出 Intent的“意图”。 

Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent);

3.2、隐士Intent

隐式intent不指定组件的名称。一般应用在跳转到其他应用中的某个界面,或者自己的应用界面想被其他应用打开。 效率低。

隐式 Intent它并不明确指出我们想要启动哪一个活动,而是指定了一系列更为抽象的actioncategory等信息,然后交由系统去分析这个Intent, 并帮我们找出合适的活动去启动。

通过在<activity>标签下配置<intent-filter>的内容,可以指定当前活动能够响应的 action 和 category,打开 AndroidManifest.xml,添加如下代码: 

<activity android:name=".SecondActivity" >

    <intent-filter>

        <action android:name="com.example.activitytest.ACTION_START" />

 

        <category android:name="android.intent.category.DEFAULT" />

    </intent-filter>

</activity>

<action>标签

指明当前活动可以响应 com.example.activitytest.ACTION_ START这个 action<category>标签

包含了一些附加信息,更精确地指明了当前的活动能够响应的 Intent中还可能带有的 category

只有<action><category>中的内容同时能够匹配上 Intent中指定的 action和 category时,这个活动才能响应该 Intent。 

如下,在FirstActivity定义button1按钮的点击事件,代码如下所示: 

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(
				"com.example.activitytest.ACTION_START");
		startActivity(intent);
	}
});

可以看到,我们使用了 Intent的另一个构造函数,直接将 action的字符串传了进去,表明要启动能够响应 com.example.activitytest.ACTION_START这个 action的活动。至于这里有指定 category是因为 android.intent.category.DEFAULT 是一种默认的 category,在调用 startActivity()方法的时候会自动将这个 category添加到 Intent中。  

每个Intent中只能指定一个 action,但却能指定多个category。修改 FirstActivity中按钮的点击事件,代码如下所示: 

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		Intentintent = newIntent("com.example.activitytest.ACTION_START");
		// 默认的category 可以省略,所以这里实际指定了连个category
		// intent.addCategory("com.example.activitytest.MY_CATEGORY");
		startActivity(intent);
	}
});

如上,调用Intent中的 addCategory()方法来添加一个 category,这里指定了一个自定义的 category,值为com.example.activitytest.MY_CATEGORY。 

接着在<intent-filter>中再添加一个 category的声明,如下所示:

<activity android:name=".SecondActivity" >

    <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>

3.3、隐式 Intent的更多用法

使用隐式 Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动

1)启动系统的浏览器

Intent intent = new Intent(Intent.ACTION_VIEW); 

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

这里首先指定了 Intent的 action是 Intent.ACTION_VIEW,这是一个 Android系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse()方法,将一个网址字符串解析成一个 Uri对象,再调用 Intent的 setData()方法将这个 Uri对象传递进去。 

2)启动系统打电话的功能:

Intent intent = new Intent(Intent.ACTION_DIAL); 

intent.setData(Uri.parse("tel:10086")); 

方法介绍:

setData(data):

data: Uri对象,主要用于指定当前 Intent操作的数据,这些数据通常都是以字符串的形式传入到 Uri.parse()方法中解析产生的.

与此对应,我们还可以在<intent-filter>标签中再配置一个<data>标签,用于更精确地指 定当前活动能够响应什么类型的数据。

<data>标签中主要可以配置以下内容。 

1. android:scheme 用于指定数据的协议部分,如上例中的 http部分。 

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

3. android:port 用于指定数据的端口部分,一般紧随在主机名之后。 

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

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

只有<data>标签中指定的内容和 Intent中携带的 Data完全一致时,当前活动才能够响应 该 Intent.

3.4、Activity之间数据的传递

1)数据的正向传递向下一个活动传递数据)

Intent中提供了一系列putExtra()方法的重载,可以把我们想要传递的数据暂存在Intent中,启动了另一个活动后,只需要把这些数据再从Intent中取出就可以了。

如下,把 FirstActivity 中的一个字符串传递到SecondActivity中: 

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		String data = "Hello SecondActivity";
		Intent intent = new Intent(FirstActivity.this,
				SecondActivity.class);
		intent.putExtra("extra_data", data);
		startActivity(intent);
	}
});

putExtra(key,value)

第一个参数是键,用于后面从 Intent 中取值

第二个参数才是真正要传递的数据。 

然后我们在 SecondActivity中将传递的数据取出,代码如下所示:

public class SecondActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.second_layout);
		Intent intent = getIntent();
		String data = intent.getStringExtra("extra_data");

	}
}

 首先通过 getIntent()方法获取到用于启动SecondActivity Intent,然后调用getStringExtra()方法,传入相应的键值,就可以得到传递的数据了。如果传递的是字符串数据,则使用getStringExtra()方法来获取传递的数据,如果传递的是整型数据,则使用getIntExtra()方法,传递的是布尔型数据,则使用getBooleanExtra()方法,以此类推。

2)数据的反向传递(返回数据给上一个活动)

①使用Activity中的startActivityForResult() 方法,这个方法期望在活动销毁的时候能够返回一个结果给上一个活动。

startActivityForResult(intent, requestCode):

第一个参数还是 Intent,表示要启动的activity

第二个参数是请求码,用于在之后的回调中判断数据的来源。

修改 FirstActivity中按钮的点击事件,代码如下所示: 

button1.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(FirstActivity.this,
				SecondActivity.class);
		startActivityForResult(intent, 1);
	}
});

这里我们使用了 startActivityForResult()方法来启动SecondActivity,请求码只要是一个唯一值就可以了,这里传入了1

②设置返回结果

要返回信息给FirstActivity,需要通过setResult(resultCode, data)方法,

setResult(resultCode, data):

resultCode用于向上一个活动返回处理结果,一般只使用RESULT_OKRESULT_CANCELED这两个值。

data:把带有数据的 Intent传递回去。

接下来我们在 SecondActivity中给按钮注册点击事件,并在点击事件中添加返回数据的逻辑,代码如下所示: 

class SecondActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second_layout);
		Button button2 = (Button) findViewById(R.id.button_2);
		button2.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent();
				intent.putExtra("data_return", "Hello FirstActivity");
				setResult(RESULT_OK, intent);
				finish();
			}
		});
	}
}

通过代码可知了,构建一个 Intent把要传递的数据存放在 Intent中,然后调用了setResult() 方法,用于向上一个活动返回数据。

③处理返回结果—onActivityResult()

当在Activity中调用startActivityForResult()启动另一个Activity后,当从另一个Activity返回到当前Activity时,便会回调onActivityResult()方法来处理返回结果。

onActivityResult(int requestCode, int resultCode, Intent data)

requestCode,在启动活动时传入的请求码。

resultCode,在返回数据时传入的处理结果。

data,即携带着返回数据的Intent

如下:使用startActivityForResult来启动SecondActivity,在SecondActivity被销毁之后会回调上一个活动的onActivityResult()方法,因此我们需要FirstActivity中重写这个方法来得到返回的数据,如下所示:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	switch (requestCode) {
	case 1:
		if (resultCode == RESULT_OK) {
			String returnedData = data.getStringExtra("data_return");
		}
		break;
	default:
	}
}

在一个活动中有可能调用startActivityForResult()方法去启动很多不同的活动,每一个活动返回的数据都会回调到onActivityResult()这个方法中,因此我们首先要做的就是通过检查requestCode的值来判断数据来源。确定数据来源后,再通过resultCode 的值来判断处理结果是否成功。最后从data中取值出来,这样就完成了向上一个活动返回数据的工作。 

4)通过按下 Back将数据回传到 上一个Activity

如果直接按下back键,这样数据是无法返回到FirstActivity的。在这种情况下我们可以通过重写 onBackPressed()方法来解决这个问题,代码如下所示: 

@Override
public void onBackPressed() {
	Intent intent = new Intent();
	intent.putExtra("data_return", "Hello FirstActivity");
	setResult(RESULT_OK, intent);
	finish();
}

当用户按下 Back键,就会去执行 onBackPressed()方法中的代码,我们在这里添加返回数据的逻辑就行了。

4、Activity的生命周期

4.1、任务栈

Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(BackStack)。栈是一种后进先出的数据结构(——队列是先进先出的数据结构),在默认情况 下,每当我们启动了一个新的activity,它会在返回栈中入栈,并处于栈顶的位置。而每当我们按下 Back键或调用 finish()方法去销毁一个activity时,处于栈顶的activity会出栈,这时前一个入 栈的activity就会重新处于栈顶的位置。系统总是会显示处于栈顶的activity给用户。 

4.2、Activity的生命周期中的4个状态

①活动状态:当前Activity位于返回栈的栈顶,在屏幕最前端,处于可见并可和用户交互的激活状态。

②暂停状态:当Activity被另一个透明或者Dialog 样式的Activity覆盖,但仍然可见。处于暂停状态的activity仍然是完全存活着的,只有在系统内存不足才时会杀死这个Activity。 

③停止状态:该Activity被其他Activity完全覆盖,且完全不可见。但是它仍然保存所有的状态和信息。当内存低的情况下,它将要被系统killed(杀死)

④销毁状态:该Activity从返回栈中移除,或Activity所在的Dalvik进程被结束

4.3、Activity生命周期的7个方法

1.onCreate()activity在第一次被创建的时候调用,完成初始化操作,比如加载布局、绑定事件等。 

2.onStart() 这个方法在活动由不可见变为可见的时候调用。 (可见不可交互)

3.onResume() 这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。

4.onPause() 这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方 法中将一些消耗 CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度 一定要快,不然会影响到新的栈顶活动的使用。(可见不可交互)

5.onStop()这个方法在活动完全不可见的时候调用。(最小化或者按了home键)

它和 onPause()方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop() 方法并不会执行。

6.onDestroy() 这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。

7.onRestart() 这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。 

4.4、常见的生命周期

1)完整的生命周期:

onCreate--onStart--- onResume---onPause--onStop---onDestory

如,如果Activity有一个线程在后台运行从网络下载数据,它会在onCreate()创建线程,而在 onDestroy()销毁线程

2可视生命周期

onStart--onResume--onPause--onStop

3前台生命周期

onResume--onPause  

为了更直观理解生命周期,提供生命周期图如下:

 

注意:将一个activity设置成dialog形式只需在清单文件做如下配置:

 <activity
      android:name=".DialogActivity"
      android:theme="@android:style/Theme.Dialog" >
 </activity>

5、Activity的启动模式

Activity的启动模式一共有四种,分别是standardsingleTopsingleTask singleInstanc,可以在AndroidManifest.xml 中通过给<activity>标签指定android:launchMode属性来选择启动模式。

5.1、Standard

standard模式是系统默认的启动模式,不需为<activity>配置android:launchMode属性

特点是不管栈中是否存该activity,都生成新的实例,存放于栈结构的顶部。 

FirstActivity中,每点击一次按钮就会创建出一个新的FirstActivity实例。此时返回栈中也会存在三个FirstActivity的实例,因此你需要连按三Back键才能退出程序。 

standard模式的原理示意图,如图:

 

5.2、SingleTop

单一顶部模式,如果发现有对于对应的activity存在于栈顶,则不创建新的实例,而是复用;如果发现有对应的activity但不是位于栈顶,则创建新的新的实例存放于栈顶顶。

应用场景:避免重复的打开和重复的激活。

singleTop模式的原理示意图,如图 

 

5.3、SingleTask

单一任务模式。如果发现有对应的activity在任务栈里,那么它将清空它上面所有的activity,也会调用onNewIntent()。

应用场景:浏览器这样的耗内存资源的应用。

5.4、SingleInstance

单例模式,全局唯一模式。系统为之分配一个新的task,且里面只能有其一个Activity,也会调用onNewIntent

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值