Activity是android应用程序中重要的组件之一,常听到的android四大组件是Activity、Service、BroadcastReceiver和ContentProvider。它间接继承自android.content.Context,因此,有些时候都直接把Activity实例当做Context的实例来使用。

如前面所提到的要在应用程序中使用Activity,必须在Android Manifest.xml中配置它。

新建一个Android工程,新建过程中勾选create activity,让系统自动帮我们创建一个Activity并在Android Manifest.xml中配置它。

AndroidManifest.xml代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  4.  
  5. package="cn.csc.activity"
  6.  
  7. android:versionCode="1"
  8.  
  9. android:versionName="1.0" >
  10.  
  11. <uses-sdk
  12.  
  13. android:minSdkVersion="8"
  14.  
  15. android:targetSdkVersion="14" />
  16.  
  17. <application
  18.  
  19. android:allowBackup="true"
  20.  
  21. android:icon="@drawable/ic_launcher"
  22.  
  23. android:label="@string/app_name"
  24.  
  25. android:theme="@style/AppTheme" >
  26.  
  27. <activity
  28.  
  29. android:name=".FirstActivity"
  30.  
  31. android:label="@string/app_name" >
  32.  
  33. <intent-filter>
  34.  
  35. <action android:name="android.intent.action.MAIN" />
  36.  
  37. <category android:name="android.intent.category.LAUNCHER" />
  38.  
  39. </intent-filter>
  40.  
  41. </activity>
  42.  
  43. </application>
  44.  
  45. </manifest>

配置中,Activity节点比较重要的属性有:

android:name属性:指明该Activity节点对应的Activity定义所在的类名,这里默认简写为.FisrtActivity,完整的类名需要与Manifest节点的package属性进行拼接,也可以直接写完整的类名,这里即为cn.csc.activity.FirstActivity。注意,name属性是必须配置的,否则报错,毕竟不配置name属性本身就没有任何意义了。

android:label属性:指明该Activity的标题栏显示的内容。

此外,比较重要的还有一个:

android:launchMode属性:指明该Activity的加载模式。取值可以是standard、singleTop、singleTask和singleInstance。这个属性在提到Activity生命周期时会用到。

回到FirstActivity.java的代码来看:

  1. public class FirstActivity extends Activity {
  2.  
  3. @Override
  4.  
  5. protected void onCreate(Bundle savedInstanceState) {
  6.  
  7. super.onCreate(savedInstanceState);
  8.  
  9. setContentView(R.layout.first_layout);
  10.  
  11. }
  12.  
  13. }

Activity中常用的方法:

void  onCreate(Bundle savedInstanceState)  :这个方法在该Activity被创建时回调,进行相关的初始化工作。如,我们最常做的setContentView();设置一个UI界面。

void  setContentView(int layoutResID)

void  setContentView(View view)  :这两个方法用于给Activity设置UI界面,只是传入的参数类型不同,一个是传入一个layout资源id,一个是直接在代码中编写UI界面。

View  findViewById(int id)  :根据控件的id找到该id,返回值是一个View实例,通常需要进行向下转型到具体类型,如Button、TextView等,以便对控件进行操作,如设置控件属性值,进行事件绑定等。

在first_layout.xml中添加一个按钮,需要设置按钮的id属性,在FirstActivity中的onCreate()方法中根据id获取该按钮,然后设置它的单击响应,弹出一个Toast信息。

代码如下:

first_layout.xml:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.  
  3. xmlns:tools="http://schemas.android.com/tools"
  4.  
  5. android:layout_width="match_parent"
  6.  
  7. android:layout_height="match_parent" >
  8.  
  9. <Button
  10.  
  11. android:id="@+id/btn"
  12.  
  13. android:layout_width="wrap_content"
  14.  
  15. android:layout_height="wrap_content"
  16.  
  17. android:text="@string/btnText"
  18.  
  19. />
  20.  
  21. </RelativeLayout>

FirstActivity.java:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. btn.setOnClickListener(new OnClickListener() {
  10.  
  11. @Override
  12.  
  13. public void onClick(View v) {
  14.  
  15. // TODO Auto-generated method stub
  16.  
  17. Toast.makeText(FirstActivity.this, "I'm clicked", Toast.LENGTH_SHORT).show();
  18.  
  19. }
  20.  
  21. });
  22.  
  23. }

void  startActivity(Intent intent)  :用于启动一个新的Activity,参数intent中指定了要启动Activity的相关信息。

void  finish()  :用于结束,并销毁当前Activity。

新建一个Activity,名为SecondActivity;新建一个layout文件,名为second_layout.xml

修改first_layout中按钮的点击事件,使它启动SecondActivity。

代码如下:

second_layout.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.  
  5. android:layout_width="match_parent"
  6.  
  7. android:layout_height="match_parent"
  8.  
  9. android:orientation="vertical" >
  10.  
  11. <Button android:id="@+id/btn2"
  12.  
  13. android:layout_width="wrap_content"
  14.  
  15. android:layout_height="wrap_content"
  16.  
  17. android:text="@string/close"/>
  18.  
  19. </LinearLayout>

SecondActivity.java:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. // TODO Auto-generated method stub
  4.  
  5. super.onCreate(savedInstanceState);
  6.  
  7. setContentView(R.layout.second_layout);
  8.  
  9. Button btn2 = (Button) findViewById(R.id.btn2);
  10.  
  11. btn2.setOnClickListener(new OnClickListener() {
  12.  
  13. @Override
  14.  
  15. public void onClick(View v) {
  16.  
  17. // TODO Auto-generated method stub
  18.  
  19. finish();
  20.  
  21. }
  22.  
  23. });
  24.  
  25. }

FirstActivity.java:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. btn.setOnClickListener(new OnClickListener() {
  10.  
  11. @Override
  12.  
  13. public void onClick(View v) {
  14.  
  15. // TODO Auto-generated method stub
  16.  
  17. // Toast.makeText(FirstActivity.this, "I'm clicked", Toast.LENGTH_SHORT).show();
  18.  
  19. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
  20.  
  21. startActivity(intent);
  22.  
  23. }
  24.  
  25. });
  26.  
  27. }

注意:使用SecondActivity一定要在Manifest.xml中配置

<activity android:name=".SecondActivity" android:label="@string/second">

</activity>

否则会出现如下错误:

点击FirstActivity中的按钮,会启动SecondActivity,点击SecondActivity中的按钮会销毁SecondActivity,然后又回到FirstActivity中。跟点击模拟器上的返回键效果一样。

点击I am a button

点击Close或者返回键:

关于Intent的使用,将在之后详细说明。

void  startActivityForResult(Intent intent, int requestCode)  :用于启动一个新的Activity,并期望在这个新的Activity结束时返回数据。

void  onActivityResult(int requestCode, int resultCode, Intent data)  :用于接收处理启动的新的Activity结束时返回的数据。

这两个函数在Intent在Android之间传递数据时会用到。

Intent  getIntent()  :获取启动该Activity的意图实例,该方法可以实现获取该Activity的启动者所要传递给自己的存放在Intent中的数据。

关于管理Activity的任务栈:

Activity中有一个int  getTaskId()方法 :用于获取当前Activity所处的栈的id。

修改FirstActivity中的onCreate():

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. Log.i("TaskId","First:"+getTaskId());

  10. btn.setOnClickListener(new OnClickListener() {
  11.  
  12. @Override
  13.  
  14. public void onClick(View v) {
  15.  
  16. // TODO Auto-generated method stub
  17.  
  18. // Toast.makeText(FirstActivity.this, "I'm clicked", Toast.LENGTH_SHORT).show();
  19.  
  20. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
  21.  
  22. startActivity(intent);
  23.  
  24. }
  25.  
  26. });
  27.  
  28. }

及SecondActivity中的onCreate():

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. // TODO Auto-generated method stub
  4.  
  5. super.onCreate(savedInstanceState);
  6.  
  7. setContentView(R.layout.second_layout);
  8.  
  9. Button btn2 = (Button) findViewById(R.id.btn2);
  10.  
  11. Log.i("TaskId","Second:"+getTaskId());

  12. btn2.setOnClickListener(new OnClickListener() {
  13.  
  14. @Override
  15.  
  16. public void onClick(View v) {
  17.  
  18. // TODO Auto-generated method stub
  19.  
  20. finish();
  21.  
  22. }
  23.  
  24. });
  25.  
  26. }

注意:Log.i("TaskId","First:"+getTaskId());用于在LogCat中输出程序运行信息,第一个为Tag参数,第二个要输出的字符串信息。

打开LogCat界面:window ----> show view ----> other ---->即可找到LogCat。

由于显示的运行信息比较多,可以添加一个信息过滤器,只显示我们所关心的信息。

点击绿色的加号

由于我们在之前的Log.i()中设定了Tag参数为TaskId,这时选择by Log Tag,然后填入我们所设置的TaskId即可,随便给过滤器取个名字,然后OK。

启动应用程序,若发现仍有很多运行信息:

此时,单击下TaskId会发现只剩下一条了

此时运行的是FirstActivity,显示的是FirstActivity所在的任务栈的id为15。然后点击程序中的按钮,启动SecondActivity,发现又多出一条信息:

发现SecondActivity所在的任务栈id同样为15。

一个android应用中,不可能只有一个Activity,如上面启动了两个Activity。Android中使用任务栈来管理多个Activity。

当一个Activity被创建启动时,就会把它放入一个任务栈的栈顶。当该Activity结束被销毁时,就会从所在任务栈弹出,其下的Activity变为栈顶,切换到活动状态。当有新的Activity被启动时,它会入栈称为新的栈顶,之前活动的Activity被强制切换到暂停或者停止状态。

任意时刻,只有栈顶的Activity处于活动状态,可以与用户进行交互。栈中其他Activity若是仍然可见或部分可见,即没有被当前活动Activity完全遮盖时,则处于暂停状态。若完全不可见,则处于停止状态。

一般来说,一个android应用中所有的Activity都会被放到同一个任务栈中进行统一管理,但是也有例外,如上面提到的在Manifest.xml中配置launchMode时,配置不同的值就会有所差别。

关于Activity的状态

任意时刻,一个Activity都处于下面四个状态之一:

运行状态:位于任务栈的栈顶,此时能够与用户进行交互。

暂停状态:不再处于任务栈的栈顶,不能与用户交互,但是仍然有部分可见。

停止状态:不再处于任务栈的栈顶,不能与用户交互,而且完全不可见。

销毁状态:已从任务栈中弹出。

当系统内存不足时,会优先回收处于销毁状态的Activity所占用的资源;仍然不足时,会回收处于停止状态的Activity所占用的资源;仍然不足时,会回收处于暂停状态的Activity的资源;最不愿意回收的是运行状态的Activity资源。

关于Activity的加载模式与任务栈的关联

前面提到android:launchMode属性:指明该Activity的启动模式。取值可以是standard、singleTop、singleTask和singleInstance。

standard模式:是默认的启动模式,若没有明确指定启动模式,则为standard模式。如上面的FirstActivity和SecondActivity都没有设置launchMode属性,即为standard模式。

在该模式下,每当新启动一个Activity时,都会为之创建一个新的实例,然后放入栈顶,而不在乎任务栈中是否已然存在该Activity的实例。

修改FirstActivity代码:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. Log.i("TaskId","First:"+this+" "+getTaskId());
  10.  
  11. btn.setOnClickListener(new OnClickListener() {
  12.  
  13. @Override
  14.  
  15. public void onClick(View v) {
  16.  
  17. // TODO Auto-generated method stub
  18.  
  19. // Toast.makeText(FirstActivity.this, "I'm clicked", Toast.LENGTH_SHORT).show();
  20.  
  21. Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
  22.  
  23. startActivity(intent);
  24.  
  25. }
  26.  
  27. });
  28.  
  29. }

Log.i("TaskId","First:"+this+" "+getTaskId());此处,加上this,打印出当前实例引用this的值。

按钮的点击响应改为启动FirstActivity自身。

运行信息:

发现每次this的值都不同,可见每次都新建了一个FirstActivity实例,即便当前FirstActivity实例已然位于任务栈中,且位于任务栈的栈顶。

singleTop模式:standard模式很多时候明显不太合理,当前Activity已然有实例位于任务栈的栈顶,直接使用不就得了,干嘛非要再创建一个实例浪费资源呢。singleTop模式就是当要启动的Activity已然有实例位于任务栈的栈顶就直接使用当前栈顶,而不重新创建实例。

修改Manifest.xml:

<activity

android:name=".FirstActivity"

android:label="@string/first"

android:launchMode="singleTop" >

修改FirstActivity代码:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. Log.i("TaskId","Create:"+this+" "+getTaskId());
  10.  
  11. btn.setOnClickListener(new OnClickListener() {
  12.  
  13. @Override
  14.  
  15. public void onClick(View v) {
  16.  
  17. Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
  18.  
  19. Log.i("TaskId","Click:"+FirstActivity.this+" "+getTaskId());
  20.  
  21. startActivity(intent);
  22.  
  23. }
  24.  
  25. });
  26.  
  27. }

Log.i("TaskId","Create:"+this+" "+getTaskId());表示是onCreate()中调用

在button的onclick中Log.i("TaskId","Click:"+FirstActivity.this+" "+getTaskId());表明是点击按钮调用。

运行信息:

发现只有一个Create,即onCreate()方法只调用了一次,只创建了一个FirstActivity实例。

若FirstActivity实例在任务栈中,但是不是在栈顶,又会如何呢?

修改代码,FirstActivity中启动SecondActivity,而SecondActivity又启动FirstActivity,两者均配置为singleTop。

修改FirstActivity代码:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. super.onCreate(savedInstanceState);
  4.  
  5. setContentView(R.layout.first_layout);
  6.  
  7. Button btn = (Button) findViewById(R.id.btn);
  8.  
  9. Log.i("TaskId","Create First:"+this+" "+getTaskId());
  10.  
  11. btn.setOnClickListener(new OnClickListener() {
  12.  
  13. @Override
  14.  
  15. public void onClick(View v) {
  16.  
  17. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
  18.  
  19. startActivity(intent);
  20.  
  21. }
  22.  
  23. });
  24.  
  25. }

修改SecondActivity代码:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.  
  3. // TODO Auto-generated method stub
  4.  
  5. super.onCreate(savedInstanceState);
  6.  
  7. setContentView(R.layout.second_layout);
  8.  
  9. Button btn2 = (Button) findViewById(R.id.btn2);
  10.  
  11. Log.i("TaskId","Create Second:"+this + " "+getTaskId());
  12.  
  13. btn2.setOnClickListener(new OnClickListener() {
  14.  
  15. @Override
  16.  
  17. public void onClick(View v) {
  18.  
  19. // TODO Auto-generated method stub
  20.  
  21. Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
  22.  
  23. startActivity(intent);
  24.  
  25. }
  26.  
  27. });
  28.  
  29. }

运行信息:

发现每次都新建了一个实例,即使当前Activity在任务栈中已然存在,但由于并没与处于栈顶,就要再次创建新的实例。

singleTask模式:可能会觉得singleTop模式还是浪费资源,明明栈中已然存在实例,只因为它不在栈顶便要重新创建。若是想重用不在栈顶的Activity实例,则需要使用singleTask模式,该模式下,新启动一个Activity时,检查当前任务栈中是否存在实例,若存在,但是不在栈顶也没关系,系统会把所有在这个实例之上的Activity实例统统出栈,这样这个实例就处于栈顶,然后就可以直接重用了。

修改Manifest.xml将两个Activity的launchMode都改为singleTask,源代码不需要改动,此时观察运行信息:

启动FirstActivity时,输出一条信息,点击FirstActivity中的按钮,由于SecondActivity在栈中不存在,创建了一个实例,然后点击SecondActivity中的按钮,发现FirstActivity实例已然存在,但是栈顶是SecondActiviy,则会将SecondActivity实例出栈,直接重用已存在的FirstActivity实例,所以,此时没有回调onCreate(),故而没有输出信息。

singleInstance模式:用于共享Activity时使用。设置为该模式的Activity不会与当前应用中的其他Activity公用一个任务栈,而是出于自己单独的任务栈中。而几个公用这个Actiivty的应用,共享这个单独的任务栈,就实现了该Activity实例的共享。不然的话,每个应用都有自己的任务栈,启动的Activity肯定在自己的任务栈中管理,根本做不到Activity实例的共享。

修改程序,添加一个ThirdActivity,程序运行的效果FirstActivity为入口,在其中点击按钮可以启动SecondActivity,SecondActivity的launchMode设置为singleInstance,点击SecondActivity中的按钮,可以启动ThirdActivity。ThirdActivity中的按钮可以启动SecondActivity。

FirstActivity和ThirdActivity的launchMode均设置为singleTask。

运行信息:

FirstActivity和ThirdActivity都在同一个栈中,id为28

而SecondActivity在id为29的栈中。

注意,此时,点击ThirdActivity中的按钮启动SecondActivity时,不会输出任何信息,因为直接重用了id为29的任务栈中的SecondActivity实例。若在ThirdActivity时,按下模拟器的返回按钮,销毁ThirdActivity,则会直接回到FirstActivity中,因为它俩是处在同一个栈中的。

android菜鸟学习笔记8----Activity(一)的更多相关文章

  1. android菜鸟学习笔记11----Intent的两点补充

    关于Intent的两点补充: 1.隐式Intent启动组件,会有一个Intent解析的过程,若找不到能够处理该Intent的组件,程序就会异常终止.一个合理的做法是,在使用Intent实例启动组件如: ...

  2. android菜鸟学习笔记5----第一个android程序

    程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...

  3. android菜鸟学习笔记3----关于AndroidMainfest.xml

    每个android项目都包含一个AndroidMainfest.xml文件,它包含了组成应用程序的每一个Acitivity.Service.Content Provider和Broadcast Rec ...

  4. android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图

    1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 ...

  5. android菜鸟学习笔记29----Android应用向用户发送提示信息的方式总结

    常见的向用户发送提示信息的方式有3种,分别为: 1)发送Toast信息 2)弹出对话框 3)发送通知 总结如下: 方式1:发送Toast信息: 这种方式最简单,在之前的学习中多次使用过.Toast是在 ...

  6. android菜鸟学习笔记27----Fragment的简单使用

    1.Fragment的生命周期: 简单在新建一个MyFragment继承自Fragment,重写各个生命周期回调方法,各个方法中直接输出标识相关函数被调用的信息. 重写MainActivity的各个生 ...

  7. android菜鸟学习笔记31----Android使用百度地图API(二)获取地理位置及地图控制器的简单使用

    1.获取当前地理位置: Android中提供了一个LocationManager的类,用于管理地理位置.不能通过构造函数获取该类的实例,而是通过Context的getSystemService(): ...

  8. android菜鸟学习笔记28----Android中的Service生命周期及本地和远程服务绑定的实现

    Service是Android中长期在后台运行的没有界面的组件,使用服务的优势在于:能够提高进程的优先级,系统不容易回收掉进程,即便回收了,内存充足的时候,会把进程重新创建. 1.服务的简单使用示例: ...

  9. android菜鸟学习笔记26----Android广播消息及BroadcastReceiver

    1.广播类型: Android中的广播有两种类型:标准广播和有序广播.其中,标准广播是完全异步发送的广播,发出之后,几乎所有的广播接收者都会在同一时刻收到这条广播消息,因而,这种类型的广播消息是不可拦 ...

随机推荐

  1. 洛谷 P1865 A % B Problem[筛素数/前缀和思想/区间质数个数]

    题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格式: 对于每次询问输出个数 t,如l或r∉[1,m]输出 Cros ...

  2. CodeForces - 316E3 Summer Homework

    Discription By the age of three Smart Beaver mastered all arithmetic operations and got this summer ...

  3. 如何使用Ext.create() 调用一个窗体

    Ext.define("Scripts.Code.QM.OutgoingQuality.OQC.ReinspRequest.view.DefectContentsDetailInfoWind ...

  4. iOS7自定义back按钮和pop交互手势

    Clambake for iPhone有一个回退按钮在所有的导航条上.这是一个简单的没有文字箭头. 实现一个自定义按钮是简单的.类似这个设置controller 的navigationItem一个le ...

  5. IOS开发~灵活使用 dismissViewControllerAnimated / dismissModalViewControllerAnimated

    当遇到: A presentViewController B ,  B presentViewController C,  C presentViewController D,问如何从D一下子回到A, ...

  6. weblogic多池与oracle集群RAC

    http://www.techpaste.com/2013/04/soa-infra-start-fails-weblogic-common-resourceexception-good-connec ...

  7. RHEL CentOS Fedora各种源介绍和安装

    CentOS默认自带CentOS-Base.repo源,但官方源中去除了很多有版权争议的软件,而且安装的软件也不是最新的稳定版.   下面介绍各种第三方软件库,以下软件库适用于与RHEL完全兼容的li ...

  8. wxWidgets 安装方法(Windows 8.1 + Visual Studio 2013)

    在windows 8.1上面,搭建基于visual studio 2013的wxWidgets的开发环境,方法如下: 下载  目前最新版本为3.0.0,下载地址: http://sourceforge ...

  9. 两段用来启动/重启Linux下Tomcat的Perl脚本

    两段代码,第二段比较好些. 下面是Split输出结果方式的代码: #!/usr/local/bin/perl #Date:2015-07-07 print "Begin to restart ...

  10. mysql 导入sql文件时编码报错

    1.命令行导入 mysql -uroot -pnewpwd --default-character-set=utf8 databasename < xxx.sql 2.使用source导入 进入 ...