android.app.Activity---中文-程序员宅基地

技术标签: 网络应用  SQLite  配置管理  设计模式  Android  

Android.app.Activity

Activity是用户主要也是唯一打交道的途径。基本上所有的Activity都是和用户打交道的,你可以通过setContentView(View)来创建一个窗口。Activity常常是以全窗口的模式展示的,当然也有其他的展示方式:浮动窗口(windowIsFloating)或则嵌入到其他Activity(ActivityGroup)。基本上所有子类都会重写一下两个方法:

◆ onCreate(Bundle):初始化Activity。这里常会调用setContentView(int)来加载layout资源来定义你的UI,并且使用findViewById(int)来获取组件。

◆ onPause():指离开Activity时候触发的方法。用户在组件上所做的变更都要提交(通常保存到ContentProvider)

如果有调用Activity.startActivity(),必须在AndroidManifest.xml文件中的<activity>标签中声明该Activity。

Activity在整个应用的生命周期中起至关重要的作用。

Activity Lifecycle

系统中的Activity可以通过一个activity栈来进行管理。当一个新的activity启动的时候,它首先会被放置在activity栈顶部并成为running状态的activity —— 之前的activity也在activity栈中,但总是被保存在它的下边,只有当这个新的activity退出以后之前的activity才能重新回到前景界面

所有的activity有四中状态

◆ 如果activity在屏幕前端(在堆栈栈顶),那么这个activity是运行的

◆ 如果一个activity失去焦点时仍然可见(指新打开的activity不占用整屏),那么它的状态是paused。Paused 的Activity仍然可见(依然保存它的数据和状态信息,并且仍然由window manager ),但是会在系统处于低内存状态时候被清除。

◆ 如果一个Activity被其他activity覆盖时,它将处于stopped状态。它仍然保留数据和状态信息,但是它对于用户是不可见的。但是它会在系统其他地方需要内存的时候被杀掉

◆ 如果一个Activity处于paused或则stopped状态时,系统可以通过关闭或则杀掉进程的方式来释放它占用的内存。当再次需要它的时候,系统会重新启动并加载之前的状态。

下图是Activity的主要状态图:

对于你的activity,有三个点比较关键:

◆ Activity的整个生命周期从onCreate(Bundle)到onDestory().activity会在onCreate()时候创建所有的全局状态并且会在onDestory()时候释放这些资源。比如如果需要一个Thread在后台下载网络上的资源,那么需要在onCreate(Bundle)时候创建它并且在onDestory()时候释放它。

◆ Activity可见生命周期从onStart()到onStop().这个时间我们可以在屏幕上看到这些组件,尽管可能这个组件不在最前端。这两个方法之间可以调用一些展示给用户看的资源。比如可以在onStart()是创建一个BroadcastReceiver来接收对用户界面有影响的信息,在onStop()时候关闭它,那么在每次调用onStart()和onStop()时候都会穿件这个BroadcastReceiver。

◆ Activity的前景生命周期从onResume()到onPause()之间。这期间Activity处于和用户交互阶段。Activity会不断的在resume和pause状态之间切换:设备进入睡眠、activity需要的结果已传递过来了或则新的intent到达时。所以这两个方法应该是轻量级的。

Activity在整个生命周期中定义了以下方法,这些方法是以hook的形式定义的,你可以在子类中重写他们,一般来说子类都要覆盖onCreate(Bundle)来初始化一些数据而重写onPause()来提交用户的数据。一般会在最后调用父类的构造函数

Configuration changes

如果配置信息更改(在Resources.Configuration 类中定义),那么任何在用户界面定义的信息都会改变。由于activity是用来处理和用户交互的,所以它也提供了特别的机制来更新配置信息。除非你特别指定,否则配置的更改(比如屏幕的排序,语言,输入设备等)会导致当前的activity被destory,这里的destory是通过正常途径(通过生命周期的onPause(),onStop()以及onDestory()).如果activity正在展示给用户,那么当onDestory()调用时,会创建一个新的activity,并且前面那个示例中在onFreeze(Bundle)保存的内容传递给新的示例。因为任何资源都可能发生变化,所以最好的方法去处理配置的更改途径就是重新检索所有的资源(包括layouts、drawables、strings)。因为activity已经知道他们当前的状态,因而重新创建时一件很轻量的过程。在一些特殊的情况下,你可能希望当一种或则多种配置文件变化的时候不重启你的activity。你可以同坐在manifest文件中设置android:configchanges属性来是实现这一点。你可以在这里申明activity可以处理的任何配置变化,当这些变化发生时候不会重新启动activity而是调用activity的onConfigurationChanged(Resouces.configuration)方法。如果改变的配置中包含了你无法处理的配置(android.configChanges未申明),你的activity仍然会被重启而onConfigurationChanged(Resources.Configuration)将不会被调用。

Starting Activities and Getting Results

startActivity(Intent)是用来启动一个Activity的,也就是把这个Activity推到栈顶。它有一个唯一的参数,这个参数是用于描述要执行的Activity的。有时候你希望当一个Activity结束时可以返回一些信息。比如,你提供了一个Activity给用户选择电话薄,并希望在用户选择完后会返回选择的电话信息。你可以调用startActivityForResult(Integer,int)来启动Activity,第二个参数int就用来标示你想要返回的结果,通过调用onActivityResut(int,int,Intent)来获取返回的信息,第一个int就是你标识的。当activity退出时,可以调用setResult(int)来把数据返回给她的父进程。返回的结果码可以使标准结果RESULT_CANCELED,RESULT_OK,也可以是从RESULT_FIRST_USER定义的值,当然还可以是一个URL地址(通常是activity所希望的Bundle)。这些信息以及一些最初定义的值都会在父activity的Activity.onActivityResult()中出现。如果子Activity失败了(例如crashing),父Activity就会受到一个RESULT_CANCELED的结果。

这里有一个启动并处理结果的Activity:

public class MyActivity extends Activity {
...
static final int PICK_CONTACT_REQUEST = 0;
protected boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}

Saving Persistent Sate

Activity会处理两类的持久状态:共享文档类数据(通过contesnt provide共享的保存在SQLite数据)以及内部状态(例如用户自定义数据)

对于content provider的数据,我们建议activity使用“编辑即发生”用户模型。就是说,用户所做的任何编辑都将立即生效而不要求任何进一步的确认。下面两条规则可以使支持这种模型成为一件简单的事情。

◆创建一个新文档的时候,立即为它创建文件或者后台数据库条目。举例来说,如果用户要写一封新邮件,当他们开始输入的时候马上创建一个新的数据库条目,所以即使他们输入以后进入别的activity,这封邮件也会在草稿箱中出现。

◆当activity的onPause()方法被调用时,它应该将任何用户所做修改向后台的content provider 或者文件提交。这可以确保即将运行的其他activity可以看到这些修改。你可能会使用更激进的方式来在你的activity生命周期中关键的时间点上提交数据:例如在启动一个新的activity之前、终止你的activity之前、当用户在输入域之间切换时,等等。

这个模型是为了避免用户在activity之间切换时数据丢失而设计的,同时允许系统在activity处于paused状态后任何时间都可以安全的kill这个activity(因为其它地方可能需要系统资源)。注意这隐含着一个含义,即用户点击你activity的BACK键并不意味着“取消”——它意味着保存他当前的内容并离开你的activity。Activity中取消编辑必须通过其他机制来提供,例如显式的提供"revert" 或 "undo"选项。

Activity同时提供了API来管理与activity相关联的内部持久状态。这可以用来记忆用户日历的首选初始显示(日期视图或者周视图)或者用户web浏览器的缺省主页这类信息。

Activity持久状态使用getPreferences(int)方法来管理,允许你取得和修改一系列与activity相关联的名称/取值对。如果要在应用的多个组件(activities,recivers,services,providers)之间共享参数,你可以使用底层方法Context.getSharedPreferences()来获得存储在一个特定名称下的参数对象。(注意:在application packages之间不能共享设置数据 —— 如果要这么做的话你需要使用content provider)。

这里摘录了一段日历activity中的代码,用来在永久设定中保存用户首选的视图模式。

1: public class CalendarActivity extends Activity { 2: ... 3: static final int DAY_VIEW_MODE = 0; 4: static final int WEEK_VIEW_MODE = 1; 5: private SharedPreferences mPrefs; 6: private int mCurViewMode; 7: 8: protected void onCreate(Bundle icicle) { 9: super.onCreate(icicle); 10: SharedPreferences mPrefs = getSharedPreferences(); 11: mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE); 12: } 13: 14: protected void onPause() { 15: super.onPause(); 16: SharedPreferences.Editor ed = mPrefs.edit(); 17: ed.putInt("view_mode", mCurViewMode); 18: ed.commit(); 19: } 20: }Permissions
你可以通过在Activity所属应用的manifest文件中对应的<activity>标签中进行声明来限制哪些应用可以启动此Activity。如果你进行了声明,其它应用需要在他们自己的manifest文件中声明对应的<uses-permission>元素(而且需要在安装时被授予许可:译者注)才可以启动这个activity。

Process Lifecycle
Android系统会尽量久的保留应用进程。但是当内存降低时最终还是要移除旧的进程。就像Activity 生命周期 中描述的一样,移除哪个进程还是要取决于关联的用户与之交互的程度。一般来说,进程可以基于其中运行的activity所处的生命周期而分成四种状态,下面将这些状态根据重要程度排列。系统会在kill更重要的进程(第一个)之前首先kill那些不那么重要的进程(最后一个)。

◆前景activity(处于屏幕最上方,用户与之交互的activity)被认为是最重要的。如果设备上的内存无法满足它的使用,Kill此进程只能作为最后的手段。一般来说这个时候设备处于内存paging状态,为了使用户界面保持响应才会发出这个kill请求。

◆可见activity(一个对用户可见,但是不在前景的activity,比如处在浮动对话框后)被认为是非常重要的,除非为了保证前景activity运行,否则不会被kill。

◆后台activity(一个对用户不可见,并处于paused状态的activity)就不再重要了,所以◆空进程是一个没有运行activity或者其他应用组件(比如Service或者IntentReceiver类)的进程。当内存开始降低时系统很快就会kill掉这些进程。因此当你要在activity外运行任何的后台操作时,必须在IntentReceiver或Service的上下文环境中运行,这样系统才知道需要将你的进程保留而不是kill。

有些时候Activity可能需要长时间运行一个操作,且它并不依赖于activity的生命周期而存在。例如一个照相机应用可能允许你将照片上传到web站点。上传可能需要很长时间,在上传过程中应该允许用户离开这个应用。为了做到这一点,你的activity应该在上传时启动一个Service来执行此工作。这将使系统在你的进程上传数据的过程中能够恰当的区分它的优先级(认为此进程比其他不可见应用更重要),不管原来的activity的状态是paused、stopped还是finished。

本文来自程序员宅基地,转载请标明出处:http://blog.csdn.net/timchen6824/archive/2011/03/08/6231470.aspx

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_15968/article/details/82045822

智能推荐

Pythonic风格_pythonic 三目判断-程序员宅基地

1、变量交换&gt;&gt;&gt; a = 1&gt;&gt;&gt; b = 2&gt;&gt;&gt; tmp = a&gt;&gt;&gt; a = b&gt;&gt;&gt; b = tmppythonic&gt;&gt;&gt; a, b = b, a2、循环遍历区间元素for i in [0, 1, 2, 3, 4, 5]: _pythonic 三目判断

flink学习之sql-client之踩坑记录_flink sql-client_cclovezbf的博客-程序员宅基地

注意当你使用这个模式运行一个流式查询的时候,Flink 会将结果持续的打印在当前的屏幕之上。如果这个流式查询的输入是有限的数据集, 那么Flink在处理完所有的数据之后,会自动的停止作业,同时屏幕上的打印也会相应的停止。--也可以不用hadoop 其实这里的时候就该反应过来,如果写过flink table api就知道连接hive的时候也是这两个参数。记住我们是搞flink遇到的这个问题,那么这个类和flink肯定相关,找到一个我们引入flinkjar最多的工程。网上的千篇一律是抄袭的。_flink sql-client

大数据时代时代舍恩伯格书资源_产品经理书单:《大数据时代:生活、工作与思维的大变革》...-程序员宅基地

一、书籍基本介绍书籍名称中文:《大数据时代:生活、工作与思维的大变革》书籍名称原文:《Big Data:A Revolution That Will Transform How We Live, Work, and Think》作者:[英] 维克托•迈尔•舍恩伯格(Viktor Mayer-Schönberger)中文译者:周涛发行:浙江人民出版社页数:261页出版:2012-12;内容摘要:《..._大数据时代书籍的结构

Pandas报错AttributeError: Cannot access callable attribute 'sort_values' of 'DataFrameGroupBy' objects-程序员宅基地

完整报错如下:AttributeError: Cannot access callable attribute 'sort_values' of 'DataFrameGroupBy' objects, try using the 'apply' method报错代码如下:import pandas as pddata = pf.read_csv('test.csv',header..._attributeerror: cannot access callable attribute 'to_excel' of 'dataframegro

【愚公系列】2022年01月 Mysql数据库-表结构和关系的设计_愚公搬代码的博客-程序员宅基地

文章目录一、多表设计1.一对一2.一对多3.多对多二、其他表1.中间表2.临时表一、多表设计1.一对一分析人和身份证。一个人只有一个身份证,一个身份证只能对应一个人!实现原则在任意一个表建立外键,去关联另外一个表的主键SQL演示-- 创建db5数据库CREATE DATABASE db5;-- 使用db5数据库USE db5;-- 创建person表CREATE TABLE person( id INT PRIMARY KEY AUTO_INCREMENT,

ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'appq.user', but app_valueerror: the field app_part_1.wxusermodel.user_-程序员宅基地

今天创建一个新的Django项目,然后执行 python manage.pymakemigrations 命令时,出现下面问题很奇怪,我明明没有appq这个app,百度了一下发现问题出在 Python37\Lib\site-packages\django\contrib\admin\migrations\下面,找到对应的文件,然后删除掉再次执行命令就可以了。..._valueerror: the field app_part_1.wxusermodel.user_id was declared with a laz

随便推点

python狗狗年龄换算程序_狗狗与人年龄换算表,终于知道狗狗多大了!-程序员宅基地

狗狗的寿命只有短短的十几年,很多人都很好奇狗狗的年龄到底是人类年龄的几岁呢?那么狗狗的年龄与人类的年龄是怎么换算的呢?今天小编带你一起了解一下吧。那么怎么判断狗狗的年龄?1、牙齿由牙齿耗损的程度可以判断狗狗是否已经进入老犬阶段,如果门牙已经掉落,且牙齿磨得很深或已经松动,可以判断应该已经7岁以上了,饮食上要做出调整,适当的补充营养。2、被毛上了年纪的狗狗脸颊与耳朵周围的被毛会变成灰白色,嘴边的白毛...

NumPy Essentials 带注释源码 四、NumPy 核心和模块_numpy 源代码分析-程序员宅基地

NumPy 核心和模块# 来源:NumPy Essentials ch4步长# 步长是每个维度相邻两个元素的偏移差值import numpy as npx = np.arange(8, dtype = np.int8)x# array([0, 1, 2, 3, 4, 5, 6, 7])# x 是一维数组,步长为 1,因为 int8 占一个字节x.strides# (1,)# data_numpy 源代码分析

matlab中fill函数的使用方法_matlab fill-程序员宅基地

填充的二维多边形fill 函数创建彩色多边形。语法①fill(X,Y,C)fill(X,Y,C) 根据 X 和 Y 中的数据创建填充的多边形(顶点颜色由 C 指定)。C 是一个用作颜色图索引的矢量或矩阵。如果 C 为行矢量,length 必须等于 size(X,2) 和 size(Y,2);如果 C 为列矢量,length 必须等于 size(X,1) 和 size(Y,1)。必要时,fill 可将最后一个顶点与第一个顶点相连以闭合多边形。X 和 Y 的值可以是数字、日期时间、持续时间或类别值_matlab fill

数据对接-ETL之StreamSet学习之旅七微服务-程序员宅基地

StreamSet作为大数据ETL工具的选择,当然需要处理数据的合并与转存,其大部分功能集中于此。有些场景可能需要其对外提供个接口,可以被调用,StreamSets能做到吗?答案是能!并且能做当今流行的微服务,啊!好高大上~,今天就来看看吧。目录学习系列1、Restful风格的Api2、建立Api3、测试一下3.1 大名鼎鼎的Postman,后端程序员必备3.2 测试专业级Jmeter3.3..._streamset

深入浅出matplotlib(26):使用模块patches的Wedge实现饼图_patches.wedge()-程序员宅基地

前面学习了patches模块,也知道了一些简单使用,但是知识要在应用中才发现它的好处。本文就来演示Wedge的使用,使用它来实现饼图。饼图最合适用来表示百分比了,因为一个圆就表示百分之百,某一部分就可以使用扇形来表示,这样看起来就比较明了,占得多的面积的就是百分比大的。当然,也可以直接使用matplotlib里的饼图来实现,但是这里主要是演示Wedge模块。当你需自定义一些数据图时,就可以采用类似的方法来实现,也就是实现自定义图表,这样灵活性更大。如果你掌握了这种方法,应付各种实验的论文,各种课堂演示的稿件_patches.wedge()