Android Activity (一)

Class Overview

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:

 

Activity一般用于和用户的交互,所以Activity类管理创建窗口,用户可以通过setContentView(View)来放置需要的UI控件。当Activity全屏显示时,可以用于其它用户,例如浮动窗口(通过windwosIsFloating设置)或内置activity(通过ActivityGroup设置)。

有两个方法大部分Activity子类都会实现:

·         onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource defining your UI, and using findViewById(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 the ContentProvider holding the data).

OnCreate(Bundle)是用于初始化Activity,更为重要的是,在这里一般通过调用setContentView设置已经定义的layout资源和findViewById(int)初始化UI控件。

OnPause用于处理Avtivity将失去焦点动作,这时应该保存用户已经修改的数据。

 

To be of use with Context.startActivity(), all activity classes must have a corresponding <activity> declaration in their package's AndroidManifest.xml.

 

所有的Activity必须在AndroidManifest.xml里面声明,否则在startActivity调用后,会crash.

 

The Activity class is an important part of an application's overall lifecycle, and the way activities are launched and put together is a fundamental part of the platform's application model. For a detailed perspective on the structure of Android applications and lifecycles, please read the Dev Guide document on Application Fundamentals.

Topics covered here:

1.       Activity Lifecycle

2.       Configuration Changes

3.       Starting Activities and Getting Results

4.       Saving Persistent State

5.       Permissions

6.       Process Lifecycle

 

Activity是一个应用程序生命周期很重要的一部分,activity的加载和管理是android平台基本的应用程序模型。如果想整体上了解Android应用的结构和生命周期,可以阅读Application Fundamentals.

 

Activity Lifecycle

Activities in the system are managed as an activity stack. When a new activity is started, it is placed on the top of the stack and becomes the running activity -- the previous activity always remains below it in the stack, and will not come to the foreground again until the new activity exits.

 

Activity的生命周期

系统通过一个activity stack的方式来管理Activity. 当一个新的activity启动后,将被放置在这个栈的顶层并成为正在运行的一个activity. 原来的activity仍然保持在栈中,直到新的activity退出,否则将不会重新切换到前台。

An activity has essentially four states:

·         If an activity in the foreground of the screen (at the top of the stack), it is active or running.

·         If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations.

·         If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.

·         If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.

 

Activity用四个基本的状态

1 如果activity在前台(在栈的最顶部),那么他处于active running的状态

2.如果activity已经失去但仍保持可见(具有焦点的新activity不是全屏的或者透明),那这个activity处于paused状态。 一个pausedactivity仍然是alive(仍然保持所有的状态和成员信息,保持着和window managerattached关系),但在系统处于低内存状态可能被killed

3. 如果activity被另外一个activity完全屏蔽,那么他处于stopped状态。这样的Activity仍然保持所有的状态和成员信息,然而,对于用户而言将不在可见并且很容易被killed当系统需要额外的内存时。

4. 如果activity处于pausedstopped状态,系统可能从内存中销毁activity通过调用finish或者简单的杀掉他的进程。当再次显示时,将全部重新启动和加载原来的状态

The following diagram shows the important state paths of an Activity. The square rectangles represent callback methods you can implement to perform operations when the Activity moves between states. The colored ovals are major states the Activity can be in.

 

下面这张图描述了activity重要的状态转换。长方形表示当Activity在状态切换过程用户可以实现的用于控制操作的回调函数。

There are three key loops you may be interested in monitoring within your activity:

 

·         The entire lifetime of an activity happens between the first call to onCreate(Bundle) through to a single final call to onDestroy(). An activity will do all setup of "global" state in onCreate(), and release all remaining resources in onDestroy(). For example, if it has a thread running in the background to download data from the network, it may create that thread in onCreate() and then stop the thread in onDestroy().

·         The visible lifetime of an activity happens between a call to onStart() until a corresponding call to onStop(). During this time the user can see the activity on-screen, though it may not be in the foreground and interacting with the user. Between these two methods you can maintain resources that are needed to show the activity to the user. For example, you can register a BroadcastReceiver in onStart() to monitor for changes that impact your UI, and unregister it in onStop() when the user an no longer see what you are displaying. The onStart() and onStop() methods can be called multiple times, as the activity becomes visible and hidden to the user.

·         The foreground lifetime of an activity happens between a call to onResume() until a corresponding call to onPause(). During this time the activity is in front of all other activities and interacting with the user. An activity can frequently go between the resumed and paused states -- for example when the device goes to sleep, when an activity result is delivered, when a new intent is delivered -- so the code in these methods should be fairly lightweight.

 

Activity生命周期三个关键的循环

1.  Activityoncreate ondestory的整个生命周期。在onCreateActivity会初始化全局的状态,并在onDestory中将释放所有的资源。比如需要后台线程用网络下载数据,那么将在oncreate中启动线程并在onDestory中停止这个线程。

2.  Activity的可见生命周期是从调用onStartonStop的调用。在这段时间用户可以从屏幕上看到activity,尽管可能不是处于前台和用户交互。在这两个方法中可以维持需要的资源。例如可以注册一个BroadcastReceiveronStart中去监测对UI影响的变化,并在onStop中反注册当当前activity不在对用户可见时。

3.  前台生命周期保持在onResumeonPause的函数调用之间。这段时间中,activity在其他的activity的前面并和用户进行交互。

The entire lifecycle of an activity is defined by the following Activity methods. All of these are hooks that you can override to do appropriate work when the activity changes state. All activities will implement onCreate(Bundle) to do their initial setup; many will also implement onPause() to commit changes to data and otherwise prepare to stop interacting with the user. You should always call up to your superclass when implementing these methods.

 public class Activity extends ApplicationContext {

     protected void onCreate(Bundle savedInstanceState);

 

     protected void onStart();

    

     protected void onRestart();

 

     protected void onResume();

 

     protected void onPause();

 

     protected void onStop();

 

     protected void onDestroy();

 }

 

 

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 onStart().

No

onStart()

    

onRestart()

Called after your activity has been stopped, prior to it being started again.

Always followed by onStart()

No

onStart()

onStart()

Called when the activity is becoming visible to the user.

Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.

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 onPause().

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 onResume() if the activity returns back to the front, or onStop() if it becomes invisible to the user.

Yes

onResume() or
onStop()

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 onRestart() if this activity is coming back to interact with the user, or onDestroy() if this activity is going away.

Yes

onRestart() or
onDestroy()

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

Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed. Because of this, you should use the onPause() method to write any persistent data (such as user edits) to storage. In addition, the method onSaveInstanceState(Bundle) is called before placing the activity in such a background state, allowing you to save away any dynamic instance state in your activity into the given Bundle, to be later received in onCreate(Bundle) if the activity needs to be re-created. See the Process Lifecycle section for more information on how the lifecycle of a process is tied to the activities it is hosting. Note that it is important to save persistent data in onPause() instead of onSaveInstanceState(Bundle) because the later is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.

For those methods that are not marked as being killable, the activity's process will not be killed by the system starting from the time the method is called and continuing after it returns. Thus an activity is in the killable state, for example, between after onPause() to the start of onResume().

 

上面表格中的killable列表示在这些方法中被标记为可以被killed掉。当这些方法调用后 这个activity的进程随时都可能被系统kiiled  At any time.!!所以需要在onPause中保存数据。

另外onSaveInstanceStateActivity被切换到后台时将被调用,这里允许用户保存任何动态数据到给定的bundle,这个参数将在onCreateBundle)中调用如果activity需要重新创建。

onPause中保存数据代替onSAveInstanceState因为后者不是Activity生命周期回调的一部分,有可能在任何情况下不被调用。

 

 

Configuration Changes

If the configuration of the device (as defined by the Resources.Configuration class) changes, then anything displaying a user interface will need to update to match that configuration. Because Activity is the primary mechanism for interacting with the user, it includes special support for handling configuration changes.

当前设备的配置有所变化时,呈现给用户的任何接口需要更新以便适配变化后的配置。

Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate. If the activity had been in the foreground or visible to the user, once onDestroy() is called in that instance then a new instance of the activity will be created, with whatever savedInstanceState the previous instance had generated from onSaveInstanceState(Bundle).

 

在这里非常非常需要注意的是:如果没有特殊处理,那么配置的变化(比如屏幕方向,语言,输入设备等等)将会引起当前的activity destoryed通过onPause onStop onDestory这个流程。如果这个activity是当前的可见的activity,一旦onDestory调用后新的实例将会被创建,通过传递onSaveInstanceStatus(Bundle)保存的savedInstaceState的实例。

 

This is done because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources, including layouts, drawables, and strings. Because activities must already know how to save their state and re-create themselves from that state, this is a convenient way to have an activity restart itself with a new configuration.

 

之所以这样,是因为应用的资源包括layout文件需要改变以便适应新的配置。最安全的方法是重新生成所有的资源,包括layout,drawables,strings.

In some special cases, you may want to bypass restarting of your activity based on one or more types of configuration changes. This is done with the android:configChanges attribute in its manifest. For any types of configuration changes you say that you handle there, you will receive a call to your current activity's onConfigurationChanged(Configuration) method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and onConfigurationChanged(Configuration) will not be called.

 

在某些情况下,可能需要避免因为某一项或者多项类型配置的变化引起的重新创建activity

这个可以通过在manifest设置android:configChange属性实现。

任何配置的变化都因为当前acitivity的成员函数onConfigurationChanged(Configuration)的调用。可以通过重载这个函数避免当前activity的重新创建。

Starting Activities and Getting Results

The startActivity(Intent) method is used to start a new activity, which will be placed at the top of the activity stack. It takes a single argument, an Intent, which describes the activity to be executed.

启动一个新的activity可以通过startActivity,通过简单的传递一个Inteng参数,而他描述了当前需要执行的activity的信息。

Sometimes you want to get a result back from an activity when it ends. For example, you may start an activity that lets the user pick a person in a list of contacts; when it ends, it returns the person that was selected. To do this, you call the startActivityForResult(Intent, int) version with a second integer parameter identifying the call. The result will come back through your onActivityResult(int, int, Intent) method.

 

如果需要从新加载的activity获取某些结果,那么可以通过startActivityForResult函数来实现通过一个integer来标示那种操作,结果会在onActivityResult中返回。

When an activity exits, it can call setResult(int) to return data back to its parent. It must always supply a result code, which can be the standard results RESULT_CANCELED, RESULT_OK, or any custom values starting at RESULT_FIRST_USER. In addition, it can optionally return back an Intent containing any additional data it wants. All of this information appears back on the parent's Activity.onActivityResult(), along with the integer identifier it originally supplied.

 

当一个activity退出时,通过调用setResult以便返回数据到他的父容器。这里必须实现一个result code,可以简单通过标准的RESULT_CANCELED, RESULT_OK或者其他的定义的valueRESULT_FIRST_USER开始的值。 另外还可以返回一个Intent用于返回任何想返回的数据。

If a child activity fails for any reason (such as crashing), the parent activity will receive a result with the code 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));

             }

         }

     }

 }

 

Saving Persistent State

There are generally two kinds of persistent state than an activity will deal with: shared document-like data (typically stored in a SQLite database using a content provider) and internal state such as user preferences.

有两种方式用于保存activity的状态

 一种是通过共享文档SQLite数据库,另外一种是通过设置user preference.

 

For content provider data, we suggest that activities use a "edit in place" user model. That is, any edits a user makes are effectively made immediately without requiring an additional confirmation step. Supporting this model is generally a simple matter of following two rules:

对于content provider数据,建议用“edit in place”(个人理解立马生效)的模式。用于做的任何更改不需要其他额外的任何步骤立即进行保存。

·         When creating a new document, the backing database entry or file for it is created immediately. For example, if the user chooses to write a new e-mail, a new entry for that e-mail is created as soon as they start entering data, so that if they go to any other activity after that point this e-mail will now appear in the list of drafts.

·         When an activity's onPause() method is called, it should commit to the backing content provider or file any changes the user has made. This ensures that those changes will be seen by any other activity that is about to run. You will probably want to commit your data even more aggressively at key times during your activity's lifecycle: for example before starting a new activity, before finishing your own activity, when the user switches between input fields, etc.

 

 

This model is designed to prevent data loss when a user is navigating between activities, and allows the system to safely kill an activity (because system resources are needed somewhere else) at any time after it has been paused. Note this implies that the user pressing BACK from your activity does not mean "cancel" -- it means to leave the activity with its current contents saved away. Cancelling edits in an activity must be provided through some other mechanism, such as an explicit "revert" or "undo" option.

 

这个方法用于当用户在activity之间进行切换时防止数据丢失,以便系统可以安全的kill掉任何一个activity.

See the content package for more information about content providers. These are a key aspect of how different activities invoke and propagate data between themselves.

The Activity class also provides an API for managing internal persistent state associated with an activity. This can be used, for example, to remember the user's preferred initial display in a calendar (day view or week view) or the user's default home page in a web browser.

Activity persistent state is managed with the method getPreferences(int), allowing you to retrieve and modify a set of name/value pairs associated with the activity. To use preferences that are shared across multiple application components (activities, receivers, services, providers), you can use the underlying Context.getSharedPreferences() method to retrieve a preferences object stored under a specific name. (Note that it is not possible to share settings data across application packages -- for that you will need a content provider.)

Activity提供了API用于管理内部的状态数据。 通过getPreference 允许回复和更改设置的名值对。

Here is an excerpt from a calendar activity that stores the user's preferred view mode in its persistent settings:

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

     }

 }

 

Permissions

The ability to start a particular Activity can be enforced when it is declared in its manifest's <activity> tag. By doing so, other applications will need to declare a corresponding <uses-permission> element in their own manifest to be able to start that activity.

See the Security and Permissions document for more information on permissions and security in general.

需要调用某些Activity需要在manifest里声明activity tag。有时需要增加权限以便可以启动activity.

 

Process Lifecycle

The Android system attempts to keep application process around for as long as possible, but eventually will need to remove old processes when memory runs low. As described in Activity Lifecycle, the decision about which process to remove is intimately tied to the state of the user's interaction with it. In general, there are four states a process can be in based on the activities running in it, listed here in order of importance. The system will kill less important processes (the last ones) before it resorts to killing more important processes (the first ones).

 

Android系统试图尽量的延长应用进程的的周期。但是在内存状态比较差时最终是需要移除旧的进程。简而言之,基于运行其中的activityprocess有四个状态。按照重要程度列表如下:

1.       The foreground activity (the activity at the top of the screen that the user is currently interacting with) is considered the most important. Its process will only be killed as a last resort, if it uses more memory than is available on the device. Generally at this point the device has reached a memory paging state, so this is required in order to keep the user interface responsive.

2.       A visible activity (an activity that is visible to the user but not in the foreground, such as one sitting behind a foreground dialog) is considered extremely important and will not be killed unless that is required to keep the foreground activity running.

3.       A background activity (an activity that is not visible to the user and has been paused) is no longer critical, so the system may safely kill its process to reclaim memory for other foreground or visible processes. If its process needs to be killed, when the user navigates back to the activity (making it visible on the screen again), its onCreate(Bundle) method will be called with the savedInstanceState it had previously supplied in onSaveInstanceState(Bundle) so that it can restart itself in the same state as the user last left it.

4.       An empty process is one hosting no activities or other application components (such as Service or BroadcastReceiver classes). These are killed very quickly by the system as memory becomes low. For this reason, any background operation you do outside of an activity must be executed in the context of an activity BroadcastReceiver or Service to ensure that the system knows it needs to keep your process around.

 

1.       foreground process

系统总是将其列为最后一个killed的进程,只有当他需要的内存超过当前设备的可能的允许程度时,需要killed这个process以便可以相应用户的操作。

2.       visiable process process拥有的activity保持可见但并不处于前台时,只有在为了保持前台process正常运行的情况下才会killed掉这个process

3.       background process   当前的activity处于后台对于用户不可见时,系统可以安全的killed当前的process回收内存以便处于前台的process可以正常运行。

4.       empty process 不在保留activity或者其他的应用组件(serviceBroadcastReceiver等),会很快的被killed当系统处于低内存状态时。所以任何脱离activity的操作比如serviceBroadcastReceiver确保系统知道其运行在一个activitycontext中。

 

 

Sometimes an Activity may need to do a long-running operation that exists independently of the activity lifecycle itself. An example may be a camera application that allows you to upload a picture to a web site. The upload may take a long time, and the application should allow the user to leave the application will it is executing. To accomplish this, your Activity should start a Service in which the upload takes place. This allows the system to properly prioritize your process (considering it to be more important than other non-visible applications) for the duration of the upload, independent of whether the original activity is paused, stopped, or finished

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值