展会信息港展会大全

官方解读Activity之二
来源:互联网   发布日期:2016-01-14 10:58:27   浏览:1847次  

导读:本文接着上一篇写:配置改变如果设备的配置(被定义为Resources.Configuration类)被改变了,那么所有显示用户界面的都需要被更新以适应新的配置。因为Acitivi...

本文接着上一篇写:

配置改变

如果设备的配置(被定义为Resources.Configuration类)被改变了,那么所有显示用户界面的都需要被更新以适应新的配置。因为Acitivity是和用户交互的首要机制,它包含了对配置文件改变的特殊支持。

除非你特殊指定,否则,配置文件的改变将会导致你当前的activity被销毁,经历了一个正常的activity的生命周期:onPause()、onStop(0和onDestroy()。如果此activity目前处在屏幕的最前端,或者是对用户可见,一旦那个activity实例的onDestroy()被调用,那么一个新的activity实例将会被创建,并且新创建的实例将会从 onSaveInstanceState(Bundle)中获得之前那个activity的状态。为什么要这么做呢?是因为任何应用程序的资源,包括布局文件,都能够因为任何配置文件中的配置值而发生改变。因此,对待配置文件的改变最保险的方式就是重新获得所有的资源,包括布局文件,图片资源以及字符资源。由于activity一定知道如何保存他们自己的状态并且利用这些状态重新创建自己,这就是一个简便的方法,让activity利用新的配置文件重启自己!

在一些特殊的情况下,你可能想基于一种或者多种配置文件的改变而避开重启你的activity,这可以通过manifest文件中的 android:configChanges属性来实现。对你声明在此的任何类型的配置文件的改变,你都将再你的activity中调用onConfigurationChanged(Configuration)方法,而不是通常的重启行为。如果出现了一些你并未在此声明的配置文件改变类型,那么,此activity将会重启并且onConfigurationChanged(Configuration)将不会被调用!

启动Activities并获取结果

startActivity(Intent)方法被用来启动一个新的activity,新启动的activity将会位于栈顶,该方法仅有一个参数,一个 Intent,该Intent被用来描述即将被启动的那个activity。

有的时候你也许希望当一个activity结束的时候可以从期中获得一个结果。例如:你可能会启动一个activity使得用户可以从联系人列表中选取一个记录,当选取结束后,该activity可以返回你选中的记录。为了达到这样的目的,你可以调用startActivityForResult(Intent, int)这个方法来启动activity,该方法包含第二个参数,用于标识本次调用的一个整数,该方法的返回值会通过 onActivityResult(int, int, Intent)方法返回。

当一个activity已经存在,那么他就可以调用setResult(int)返回数据给它的持有者,他必须总是提供一个返回码,可以使标准的结果RESULT_CANCELED, RESULT_OK或者是任何从RESULT_FIRST_USER开始自定义的代码。另外,它可以返回一个可选的intent,这个intent可以包含任何你想要的数据。所有的这些信息都会返回给它的持有者的Activity.onActivityResult(),伴随着前面提到的整型参数。

如果一个子activity由于任何原因失败了(例如:崩溃),那么父activity将会收到RESULT_CANCELED的返回码。

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

}

}

}

}

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

}

}

}

}

保存连续的状态

activity一般需要处理两种持续的状态:一种是共享的文档类型的数据(典型的是利用content_provider存储再SQLite中);另一种是内部状态例如:用户的偏好。

对于content provider数据,建议activities利用本地编辑的模型。那就是,用户做出的任何编辑都会立即产生作用,而不需要额外的确认的步骤,支持这种模型需要遵守如下两条规则:

1、当创建一个新的文档,那么备份的数据库条目和文件就会立即被创建。例如:当用户要写一个新的邮件时,那么一条新的记录就会随着开始输入数据而被创建,以至于如果用户浏览其他的activity,这个邮件将会出现在草稿箱中。

2、当activity的onPause()方法被调用,那么他就会把用户做出的任何改变提交到后端的content provider或者是文件。这将会确保那些改变对于那些即将运行的activity是可见的,你可能会想在activity的生命周期中更加积极主动的保存数据,例如:在启动一个新的activity之前,在结束一个activity之前,当用户改变输入框时。

这个模型被设计用来在用户浏览多个activity防址数据的丢失,并且允许系统在activity被暂停之后安全的杀死它。这意味着用户按下BACK键并不意味着“取消”,而是意味着保存当前的activity的内容并且离开当前的activity,在一个activity中取消编辑需要通过其他的一些机制,例如一个明确的“恢复”或者“撤销”选项。

关于content providers的详细内容可以查阅 content package,这些都是关于在activities之间调用和传播数据的不同之处重要方面。

Activity同样提供了API来管理与activity有关联的持续的状态。这都是可以被拿来使用的,例如:要记住用户的日历显示(日视图还是周视图)或者浏览器的默认主页。

Activity持久的状态是通过getPreference(int)来管理的,允许你去获取并修改一系列和activity有关的键值对。对于多个应用程序组件(activities,receivers,services,provides)共享的偏好设置,你可以通过隐含的Context.getSharedPreferences()方法来通过特殊的名字获取偏好设置的一些对象。(注意:再多个应用程序包中共享设置的数据是不可能的,对于这种情况,你需要使用content provider).

下面有一个从存有用户设定的显示模式的calendar activity中摘抄的一些内容:

public class CalendarActivity extends Activity {

...

static final int DAY_VIEW_MODE = 0;

static final int WEEK_VIEW_MODE = 1;

private SharedPreferences mPrefs;

private int mCurViewMode;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

SharedPreferences mPrefs = getSharedPreferences();

mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);

}

protected void onPause() {

super.onPause();

SharedPreferences.Editor ed = mPrefs.edit();

ed.putInt("view_mode", mCurViewMode);

ed.commit();

}

}

public class CalendarActivity extends Activity {

...

static final int DAY_VIEW_MODE = 0;

static final int WEEK_VIEW_MODE = 1;

private SharedPreferences mPrefs;

private int mCurViewMode;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

SharedPreferences mPrefs = getSharedPreferences();

mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);

}

protected void onPause() {

super.onPause();

SharedPreferences.Editor ed = mPrefs.edit();

ed.putInt("view_mode", mCurViewMode);

ed.commit();

}

}

权限

启动特殊activity的权利是在manifest文件中的<activity>标签中声明后被强制执行的。通过这种做法,其他的应用程序需要再他们自己的manifest文件中声明相应的<uses-permission>元素才能启动上面所说的特殊的activity。

要想查看详细的关于权限和安全的内容,可以查阅Security and Permissions文档。

进程的生命周期Android系统试图尽可能的保持进程,但是不幸的是,当系统内存过低时,系统不得不杀死一些老的进程来释放内存空间。进程也有四种状态,这四种状态都是基于运行再进程中的activity的状态,系统会优先杀死一些不太重要的进程而不是杀死重要的进程。

1、前台的activity

2、可见的activity

3、后台的activity

4、空的进程

有的时候,一个Activity也许需要长时间的运行,即要独立的存在于它自己的activity生命周期,一个例子就是:也许照相的应用程序允许你上传照片到网上,而上传可能会需要比较长的时间,那么这个应用程序应当允许用户离开上传照片的activity,但是上传照片的进程还是要处于运行状态。为了达到这样的目的,你的应用程序需要再你上传照片的地方开启一个service。这就允许系统给你的应用赋于恰当的优先级,独立于你原来的activity,不管原来的activity处于paused、stopped或者是finished。

摘自 chenlong12580的专栏

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港