标签:exception persist 配置 active 定义 mis addclass layout 输入
本文参考\android\android\frameworks\base\core\java\android\app\Activity.java文件中的类注释,以及android/frameworks/base/docs/html/guide/components/activities.jd文件
Activity是一个单独的、可以和用户交互的东西。几乎所有的activities都要与用户交互,所以activity承担着创建window的重任,你可以通过setContentView的方法往window里填充view。通过一个主题属性android.R.attr#windowIsFloating来设置activities是全屏显示full-screen还是悬浮窗isfloat(比如dialog,或者是一个悬浮的view),当然这里所说的全屏显示不包括状态栏。
<!-- 全屏显示 -->
<item name="windowIsFloating">false</item>
在对应的主题中有dialog主题样式的
<!-- 悬浮窗显示 -->
<style name="Theme.Material.BaseDialog">
‘‘‘‘‘‘
<item name="windowIsFloating">true</item>
‘‘‘‘‘‘
</style>
在继承Activity时需要实现两个方法
为了能够使用 android.content.Context#startActivity Context.startActivity()打开一个activity,我们需要将activity在对应包下的androidmanifest文件中使用activity节点进行声明
<application android:icon="@drawable/icon"
‘‘‘‘‘‘
<!-- 声明activity -->
<activity android:name=".MainMenuActivity"
‘‘‘‘‘‘
</activity>
‘‘‘‘‘‘
</application>
Fragment开始于Android3.0,是应用程序组件碎片的意思,可以被放在activity内部。通过FragmentManager来管理与fragment的交互。fragmentmanager的对象可以通过两种方式获取到
fragment类可以用来获取各种各样的结果,在它内部,它代表一个普通的操作或者是交互接口。fragment与包含他的activity紧密相连,fragment依赖于activity存在。虽然fragment有它自己的生命周期,但fragment的生命周期与activity的生命周期息息相关。fragment生命周期图如下:
fragment依附于activity存在,当activity被stopped之后,activity中的fragment不能够started。当activity销毁后,位于activity中的fragment也随之销毁。
所有Fragment的子类必须包含一个无参的构造方法。当有需要时尤其是在状态恢复期,framework层会经常重新初始化fragment,framework会去找无参构造器去初始化fragment。如果fragment中无参构造器不可用的话就会在状态恢复时抛出 runtime exception 。
fragment 是在Android3.0才加入进来的,所以在Android3.0之前如果想要使用fragment可以使用android.support.v4.app.FragmentActivity具体可以参考
fragments for all
fragment可以作为应用程序布局的一部分,借助fragment,activity可以更好的 模块化,为更大的屏幕创建更复杂的用户交互,帮助应用实现小屏和大屏之间的尺寸的切换。例如,在一个activity上可以编写一个有item列表的fragment,然后再组合一个fragment去显示每个item的详细信息。
<fragment
class="com.example.android.wifidirect.DeviceListFragment"
android:id="@+id/frag_list"
android:layout_width="match_parent"
android:layout_height="@dimen/phone_list_height">
<!-- Preview: layout=@layout/row_devices -->
</fragment>
fragment相关可以参考:
fragment嵌套
fragment与activity
在系统中,activity被一个称为activity栈activity stack的东西在管理。当新创建一个activity时,就被被放在栈顶,并且成为正在运行的activity—-先前的activity会被保留在activity的下方,当位于栈的activity退出后,位于该activity下方的activity就会运行到前台,activity栈遵循栈的原则:后进先出。
一个activity基本上有四种状态
接下来看一张activity生命周期的流程图:(来自源码)
写的很是清楚啊
在这个流程图中可以看到有三个关键的循环
public class MyActivity extends Activity{
protected void onStart() {
//注册广播
mContext.registerReceiver(mReceiver, mIntentFilter);
}
protect void onStop(){
//注销广播
mContext.unregisterReceiver(mReceiver);
}
}
activity的完整生命时期包括以下所有activity的方法。你可以实现这些方法来完成工作。所有activity会实现onCreate方法来完成初始化操作;好多activity也会实现onPause方法来提交数据的改变并准备停止用户交互。在覆写方法时应该调用父类的方法
public class Activity extends ApplicationContext{
protected void onCreate(Bundle savedInstanceState)
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onDestroy();
}
activity生命周期方法之间的切换如下表所示
Method | Description | killable | Next |
---|---|---|---|
onCreate() | 当activity第一次创建时调用。在onCreate方法中需要做一些静态初始化的操作:创建views,绑定列表数据等等。如果onCreate传入的bundle参数不为null的话,可以从bundle中获取到activity先前的状态 | No | onStart |
onRestart() | 当activity已经被stopped,但又重新加载时调用 | No | onStart |
onStart() | 当activity对用户可见visible时调用 | No | 如果activity成为前台activity,则接下来会调用onResume方法。如果activity被隐藏hidden则接下来会调用onStop方法 |
onResume() | 当activity可以开始于用户交互即activity获取到焦点时会调用该方法。随着用户的输入,activity会处在栈顶。 | No | onPause |
onPause() | 当系统想要让一个先前的activity获取焦点时调用。该方法通常用来提交一些未保存的数据,停止动画以及其他一些消耗cpu内存的事情。方法的实现体必须快速,因为下一个activity只有在onPause方法执行返回之后才会resumed所以会一直处于阻塞状态 | 当activity重新返回到前台to the front时会调用onResume,当activity对用户不可见invisible时会调用onStop | |
onStop() | 当activity不再对用户可见时会调用该方法,因为其他activity已经resumed并且覆盖了该activity。当一个新的activity开始时会被放在该activity的前面时会调用onStop,或者该activity被销毁会调用onStop | yes | 如果activity重新加载出来与用户交互,则会调用onRestart方法。如果activity被销毁则会调用onDestroy方法 |
onDestroy() | 当activity被销毁时会调用该方法。Activity被销毁有两种情况,一种是用户调用了activity的finish方法结束了activity,一种是系统为节省空间销毁了activity。可以调用isFinishing方法来区分是哪一种情况 | yes | Nothing |
表格中killable这一列值得注意一下:
对于被标记成可以被killable的方法来说,当activity执行完这些方法返回时,持有该activity的进程《在任何时候》都可能被系统杀死,不再执行该activity中的任何一行代码。也因为如此,你应该在onPause方法中去保存数据(例如,用户的编辑)。另外,当将activity运行到后台状态时可以调用onSaveInstanceState(Bundle)方法来将activity的动态数据保存到一个bundle对象中,如果activity需要重新create的话,可以在onCreate中获取到Bundle数据。
注:在Android3.0以前保存数据应该在onPause中进行,因为onSaveInstanceState不是activity的生命周期的一部分,在进程生命周期相关中不会被调用。从Android3.0开始发生了改变。应用只有在onStop方法返回后才能被killable。这也就导致了在activity被杀死之前运行完onPause之后可能会调用onSaveInsatanceState(Bundle),并且可以让应用一直等待去保存数据直到运行了onStop方法。
对于那些没有标记为可以被killable的方法表示,在方法开始调用直至方法返回这一段时间系统都不会去杀死activity的进程。因而一个activity是在调用onPause之后调用onResume之前才处于可以被kill的状态。
如果一个设备的配置Resources.Configuration发生改变,显示给用户的交互界面也应该随之更新来配合格局发生的改变(横竖屏)。因为activity是与用户交互的主要机制,它包含用来处理设备配置改变的一些函数。
除非你有其他的指定,否则当设备的configuration发生改变时(例如,屏幕方向,语言,输入设备等等)会引起你当前activity的destroyed,经历activity的正常的生命周期过程onPause–>onStop–>onDestroy。如果activity已经加载到前台in the foreground或者对用户可见visible了,该activity实例一旦调用了onDestroy方法,就会去创建一个新的activity的实例,该activity实例可以获取到通过onSaveInstanceState所保存的先前的状态savedInstanceState.
应用中任何资源,包含layout文件都会基于configuration值的改变而发生变化。因而,处理configuration改变最安全的方法就是去检索所有资源文件,包括layouts,drawable,strings。因为activity必须知道如何如保存他们的状态以及如何根据保存的状态重新创建他们,所以,快捷的方法就是提供一个新的配置来restart一个activity。
在某些情况下,你可能想在configuration发生改变是不去重启activity,这需要借助配置文件中的属性android.R.attr#configChanges android:configChanges来完成。
<!-- 当屏幕方向或者键盘方向发生改变时不去调用activity的oncreate-->
android:configChanges="keyboardHidden|orientation"
当对该属性进行了配置后,就代表你可以进行监控,当所规定的配置发生变化时就会去调用onConfigurationChanged方法,而不是重启activity。
开启一个activity并且获取到结果
android.app.Activity#startActivity方法用来打开一个activity,打开之后activity会被放在栈顶。在调用startActivity方法时需要用intent指明要打开的activity。
有时你可能想在activity结束时获取到一个返回结果。比如,你可能开启一个activity来让用户从联系人列表中选择一个联系人,当activity结束时把选择的结果返回回来,那就可以用android.app.Activity#startActivityForResult(Intent, int)打开activity,结果可以在activity的onActivityResult方法中获取
在一个存在的activity中调用setResult(int)方法把结果返回给它的父activity。在返回结果时必须提供一个结果码,可以是RESULT_CANCELED、RESULT_OK或者是其他自定义的代号。另外,也可以选择返回一个带有额外数据的intent返回回去。借助结果码,所有的信息都可以在parent的onActivityResult获取到。如果子activity发生了崩溃,父activity接受到的结果码就是RESULT_CANCELED
public class MyActivity extends Activity {
...
static final int PICK_CONTACT_REQUEST = 0;
public 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通常会保存两种持久的状态
Activity也提供了一个API来管理与activity相关的内部状态。例如,可以用来记录用户的偏好设置,并对用户的日历接卖弄进行一个初始化,或者是在使用浏览器时为用户显示一个默认的主页。
Activity的持久的状态通过getPreferences方法管理,允许检索或者是修改与activity相关的一组name/value键值对。为了让preferences可以应用程序多个组件(activities,receivers,services,providers)之间共享,你可以使用已有的方法
Context#getSharedPreferences Context.getSharedPreferences()来检索对应某个特殊name的preferences对象。(跨进程时不能通过preferences分享数据—只能通过contentProvider)
。以下是日历中的一个代码片段
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();
}
}
在Androidmanifest中注册activity时可以给activity写明一个权限,这样其他应用在打开该activity时就需要拥有这个权限。
当打开一个activity时,你可以设置在intent上设置标志位Intent.FLAG_GRANT_READ_URI_PERMISSION或者 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。
这将授予activity对intent中特定uri的访问权限。访问权限会被保留到activity结束(他将保持到主机进程被杀死并且其他暂时性损坏)。Android2.0来说,如果activity已经被created并且一个新的intent也被发送给onNewIntent(intent),任何新授予的uri权限都会被添加到所现有的uri中。
Android系统试图将应用进程尽可能的保留更长时间,但是当内存较少时最终需要杀死旧的进程。正如在activity的生命周期ActivityLifecycle中所描述的那样,关于哪一个进程应该被移除由与用户交互状态决定。通常来说,根据运行在进程中的activity的状态可以看出进程有四种状态,按照重要性的顺序排列。系统在重新排序杀死重要进程之前会优先杀死最不重要的进程。
标签:exception persist 配置 active 定义 mis addclass layout 输入
原文地址:http://blog.csdn.net/zrf1335348191/article/details/68486409