Android入门系列001----Android HelloWorld 分析(Activity类基础)
一、项目文件系统分析
安装环境配置就不在说了,网上有很多,直接来HelloWorld开始变成。
建立一个新的Android程序后,会直接生成一系列文件和文件夹。先来介绍文件系统各自功能.
- src文件夹:
MainActivity.java——主程序;
还可以存放其他程序类(class)
都直接归属于创建程序时的默认包中
- gen文件夹:系统自动生成的
BuildConfig.java—— 一看就是项目配置文件;
R.java——打开看,里面放的都是系统的一些静态类,项目公共数据放在里面
- Android 4.2:项目使用的Android系统类库
android.jar—— Android系统类库文件
- Android Dependencies: 环境支持库
android-support-v4.jar—— Android环境支持库文件
- bin: 最终生成的应用程序文件夹
在这里可以看到本项目最终生成的应用程序"Helloworld.apk"
附带还会由编译器生成一系列文件
- libs: 库文件夹
android-support-v4.jar—— Android环境支持库文件
- res: 项目资源文件夹
先说根目录地下的4个文件,包括ico,项目配置等
AndroidMainfest.xml—— 项目设置文件,里面包含应用程序中有那些Activity、Service或者Receiver等;
在"drawable-*"中放的也是ico,从文件夹名称上看,是绘图相关资源
- res/layout: 最重要的布局配置
activity_main.xml—— 激活时程序主布局配置文件
- res/menu: 菜单布局文件
main.xml—— 菜单布局
- res/values :常数文件
dimens.xml—— 对齐方式?配置
strings.xml—— 字符串
styles.xml—— 外观样式
1.MainActivity.java—— 项目主程序,激活后先运行他:
1 package com.example.helloworld; 2 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.view.Menu; 6 7 public class MainActivity extends Activity { 8 @Override 9 protected void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.activity_main); 12 } 13 14 @Override 15 public boolean onCreateOptionsMenu(Menu menu) { 16 // Inflate the menu; this adds items to the action bar if it is present. 17 getMenuInflater().inflate(R.menu.main, menu); 18 return true; 19 } 20 }
主程序类 MainActivity (主活动程序类),派生自 Activity类。主要用来设置当前程序的活动界面
重写了两个方法:
- onCreate(Bundle savedInstanceState):初始化Activity,其中通过调用setContentView方法来读取资源文件夹中设置好的UI布局;
- onCreateOptionsMenu(Menu menu):初始化标准option menu
Activity类介绍:
类树:
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View)
. While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows (via a theme with windowIsFloating
set) or embedded inside of another activity (using ActivityGroup
). There are two methods almost all subclasses of Activity will implement:
onCreate(Bundle)
is where you initialize your activity. Most importantly, here you will usually callsetContentView(int)
with a layout resource defining your UI, and usingfindViewById(int)
to retrieve the widgets in that UI that you need to interact with programmatically.onPause()
is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to theContentProvider
holding the data).
To be of use with Context.startActivity()
, all activity classes must have a corresponding <activity>
declaration in their package's AndroidManifest.xml
.
*注:关于Android SDK的类库文档,在SDK包中就很完整(安装路径\android_sdk\doc\index.html),比任何一本书都好,强烈建议使用!
不要费力气去找中文文档,现在没有完整的,工作量太大。学编程读英文书和文档是基本功,实在困难可以用google浏览器Chrome打开文档,整页直接机译,鼠标悬停还可以看原文,非常方便,可以作为过渡手段。
2.AndroidMainfest.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.helloworld" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 7 <uses-sdk 8 android:minSdkVersion="8" 9 android:targetSdkVersion="17" /> 10 11 <application 12 android:allowBackup="true" 13 android:icon="@drawable/ic_launcher" 14 android:label="@string/app_name" 15 android:theme="@style/AppTheme" > 16 <activity 17 android:name="com.example.helloworld.MainActivity" 18 android:label="@string/app_name" > 19 <intent-filter> 20 <action android:name="android.intent.action.MAIN" /> 21 22 <category android:name="android.intent.category.LAUNCHER" /> 23 </intent-filter> 24 </activity> 25 </application> 26 27 </manifest>
项目配置文件,在application节中,指定当前程序包含哪些Activity、Service或Receiver。
android.intent.category.LAUNCHER 指定了项目的启动Activity
3.其他的XML
如string.xml、activity_main.xml 等,这些XML都可以算作是资源,以后再细说
三、 Android程序运行分析:
Android中,一个程序(application)对应一个独立进程(process),其中可以包含多个activities,activity可以可见,也可以不可见,但可见的程序界面必为activity.
//下面摘自百度百科,介绍了Android应用程序(application)、进程(process)、和活动(activity)间关系
Android系统的手机的每一个你能看到的画面都是一个activity,它像是一个画布,随你在上面怎么涂画,画个按钮,画个图片,画个列表,都随你!
专业点其实activity就是一个view类的派生类(比如Button, listview,imageview)的container。
Android平台的四大天王:Activity, Service, ContentProvider, BroadcastReceiver, 这四种组件通过Intent进行沟通,Intent就是桥梁了!
Android是跑在Linux kernel上的,每一个APP都有自己的进程,Google的工程师为了简化APP开发人员的开发难度,把进程相关的东西都在底层做掉了,暴漏给APP开发人员的就是这四大天王和一个桥梁
Activity你不能把它看成是页面,因为如果你不指定页面,它就没有页面。
其实你最好是拿金山词霸翻译一下就得到答案,对, Activity 是指 一次活动的意思,
活动在这里是一场演播剧。 一出演出活动。 而演出可以是有画面的舞台,也可以是没有画面的单口相声通过声音演出给你。
如果需要有页面,那很简单你的oncreate方法里面必须要有一句代码:
this.setContentView(R.layout.main);
其中setContentView是指,我要设定我这次演出活动的演出舞台为 R.layout.main
而R.layout.main是在你的res/layout文件夹由main.xml 文件定义的,
所以你可以像网页设计一样在你的某个xml文件中定义你的界面,定义你的舞台,然后通过setContentView表现出来。
如果你像设计html一样在xml可定义了某个按钮并给按钮取了一个名字,
那么你就可以在你的activity中使用,这是你的演员,演员都有名字,你用findviewbyid(xxx) 找到这个演员,然后让他表现个动作看看。
所以用户按下这个按钮的时候就会有动作。
如果你的电视有好几集,那么你可以把每集看成一个activity.
每集有片头,片尾,中间需要的话可以插广告,广告播完要回来接着播。
所以你的ACTIVITY就有以下方法:
oncreate, onrestart onpause, onresume,onDestroy
这些方法都是导演己经为你安排好了,每个activity肯定都会有这些内容,所以如果你想特别点,那你就在这些方法里面写都你的东西。
activity 会在合适的时候自动执行你的代码。
1. Android Activity类型:
- 前端Activity(Foreground Activities):比如我们这个HelloWorld
- 后台服务(Background Service):如看不见的System Service、BroadCast、Receiver等
- 间隔执行Activity (Intermittent Activities) :类似线程Threading、Notification Manager等
2. Activity生命周期:
一个Activity的生命周期,如图
当Activity执行过 onCreate() (这个只在程序初次打开时执行,一般静态操作处理应该放在这个事件中、还有创建外观、绑定数据等等)之后,执行onStart(),
执行过onStart()后,执行onResume(),直到另一个Activity占据前端焦点,会使这个程序的Activity进入onPause()状态,这时会走到一个三叉路口,可能出现三种情况:
- 当这个Activity不再可见,直接进入onStop();
- 更高优先级的应用程序需要内存,直接关闭此应用进程;
- 用户切换回这个Activity,会重新使Activity进入onResume()
在进入onStop()状态后,也会有三个分支:
- 第一种,用户切换回这个Activity,会执行onRestart(),而后在开始onStart()。。。;
- 第二种,更高优先级的应用程序需要内存,直接关闭此应用进程;
- 第三中,这个Activity执行完毕,或者系统将其销毁,会导致onDestroy(),Activity直接关闭。
四、Activity生命周期说明:
1.整个生命周期(entire lifetime):
开始于onCreate(),结束于onDestroy(),直到执行过onDestroy()之后,才会真正关闭,释放所有资源;
2.可视生命周期(visible lifetime):
这个过程虽然叫“visible lifetime”,并不代表一直能被看到。从onStart()开始,到onStop()结束。尽管在这个过程中可能并未获取前端焦点(in the foreground)和用户交互(interacting with the user);但在这两方法间,你可以使用Activity显示所需资源。这个过程可以重复多次。
3.前端生命周期(foreground lifetime)
这个过程会被用户看到,并和用户交互,在所有其他activities之前。从onResume()开始,到onPause()结束。这个过程也是可以重复多次,相互转换(参看上面的图)
五 、Activity的基本应用:
1.基本使用方法:
参看本例,直接将自己的Activity派生自系统Activity,需要操作哪个事件,直接重写即可。
所有Activities都应该实现onCreate()来初始化,当有数据更新或停止用户互动时应该实现onPause()。
2.关于Killable
在程序执行过程中,在一些状态下(即Activity运行到某些事件时,如onStop()等),系统会因为一些如内存不足之类的原因,自动将这个activity给杀了。
//下表摘自Android SDK DOC
In general the movement through an activity's lifecycle looks like this:
Method | Description | Killable? | Next | ||
---|---|---|---|---|---|
onCreate() |
Called when the activity is first created. This is where you should do all of your normal static set up: create views, bind data to lists, etc. This method also provides you with a Bundle containing the activity's previously frozen state, if there was one.
Always followed by |
No | onStart() |
||
onRestart() |
Called after your activity has been stopped, prior to it being started again.
Always followed by |
No | onStart() |
||
onStart() |
Called when the activity is becoming visible to the user.
Followed by |
No | onResume() or onStop() |
||
onResume() |
Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.
Always followed by |
No | onPause() |
||
onPause() |
Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
Followed by either |
Pre-HONEYCOMB |
onResume() oronStop() |
||
onStop() |
Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.
Followed by either |
Yes | onRestart() oronDestroy() |
||
onDestroy() |
The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method. |
Yes | nothing |
所以需要一个状态存储过程: 在自己的onPause()事件方法中将现存的数据给保存住;对应的,使用onSaveInstanceState()方法将数据准备好,以备重新加载到再次被激活的activity中,之后通过调用onCreate(),就可以在其中完成重新加载的操作。
*注意:在不同的SDK版本中,可能会有微小的调整,上面的过程是最新的SDK 17的
六、启动Activities、获取执行结果
1.startActivity(Intent)方法启动Activities:
使用startActivity(Intent)方法来启动新的activity。
新的activity会位于activity栈的最上面(at top of the activity stack).该方法只有一个参数,Intent类对象。
2.startActivityForResult(Intent,int)启动activity,并获取执行结果:
如果需要activity执行后返回一些信息的话,就是用startActivityForResult(Intent,int)来启动activity,第二个整型参数用来定位之前调用该方法的activity。
接着,在新启动的activity中,通过setResult(int)来将数据返回给父activity,在父activity的onActivityResult(int,int, Intent)方法中,会接受到刚才子activity返回的结果。
1 //下面代码摘自Android SDK DOC 2 public class MyActivity extends Activity { 3 ... 4 5 static final int PICK_CONTACT_REQUEST = 0; 6 7 protected boolean onKeyDown(int keyCode, KeyEvent event) { 8 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 9 // When the user center presses, let them pick a contact. 10 startActivityForResult( 11 new Intent(Intent.ACTION_PICK, 12 new Uri("content://contacts")), 13 PICK_CONTACT_REQUEST); 14 return true; 15 } 16 return false; 17 } 18 19 protected void onActivityResult(int requestCode, int resultCode, 20 Intent data) { 21 if (requestCode == PICK_CONTACT_REQUEST) { 22 if (resultCode == RESULT_OK) { 23 // A contact was picked. Here we will just display it 24 // to the user. 25 startActivity(new Intent(Intent.ACTION_VIEW, data)); 26 } 27 } 28 } 29 }
可以参考这篇文章:https://www.ibm.com/developerworks/cn/opensource/os-cn-android-actvt/
七、进程声明周期(Process Lifecycle)
1、Android Process简介:
//关于进程的简介摘自:http://su1216.iteye.com/blog/1591699
默认的,同一个应用中所有的组件运行在同一个进程中,并且大多数应用不应该改变这种行为。
然而,如果你发现你需要控制某个组件所在的进程,你可以在manifest文件中设置。
每一个组件元素<activity>, <service>, <receiver>,和<provider>在manifest的入口,支持android:process属性可以指定组件应该运行在哪一个进程
你可以设置这个属性,这样每一个组件就能运行在它自己的进程或者同一些组件共享同一个进程而其他组件则不会。
你也可以设置android:process来让不同应用中的组件运行在同一个进程中 - 由共享同一个Linux user ID并且具有相同的签名的应用提供。
2.进程生命周期:
Android系统尝试尽可能长的保持一个应用进程,但是最终需要为更重要的进程移除旧的进程来回收内存。
决定哪一个进程保留哪个杀死,系统把每一个进程放到一个"重要层级"中,基于进程中运行的组件和这些组件的状态。
重要性级别最低的最先被清除,然后是与其级别相邻的