一个activity是一个单例,用户能够在上面处理一些事情。几乎所有的activites都与用户进行互动,因此Activity类使用方法setContentView(int)放置UI组件到创建的窗口上。与此同时,activies通常以全屏的形式展现在windows上,也可以使用其他的方法,例如漂浮在window上(通过theme使用andorid.R.attr#windowIsFloating 设置)或者嵌入到其他的acticity(使用ActivityGroup)
- 如果activity在屏幕的前端,他处于被激活或者运行状态。
- 如果activity失去焦点,但是仍然可见(就是一个新的非全屏尺寸或者转场的activity在你的activity之上获取焦点),他会暂停。一个暂停的activity是完全活着的(他保持所有的状态和成员信息且依然接近window管理者),但是可能被紫铜在低内存状态下杀死。
- 如果activity被另一个activity完全遮蔽,他就会停止。他依然会保持所有的状态和成员信息,然而他对用户不在可见,因此他的窗口时隐藏的而且当任何地方需要内存的时候,系统会将其杀死。
- 如果activity暂停或者停止,系统会从内存中抛弃activiy通过要求他结束,或者仅仅杀死这个进程。当他再次展示的时候,他必须是完全重启且存储他之前的状态。
生命周期
锁定 Activity 运行时的屏幕方向
<activity android:name=".EX01"
android:label="@string/app_name"
android:screenOrientation="portrait">// 竖屏 , 值为 landscape 时为横屏
…………
</activity>
或者
//添加setRequestedOrientation方法实现锁定横屏(portrait为保持竖屏,landscape为保持横屏)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Activity全屏
在其 onCreate()方法中添加如下代码实现:
// 设置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 去除标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
在 Activity 的 Title 中加入进度条
为了更友好的用户体验,在处理一些需要花费较长时间的任务时可以使用一个进度条来提示用户“不要着急,我们正在努力的完成你交给的任务”。
在 Activity 的标题栏中显示进度条不失为一个好办法,下面是实现代码:
// 不明确进度条
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
setProgressBarIndeterminateVisibility(true);
// 明确进度条
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main);
setProgress(5000);
onSaveInstanceState的作用
onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。
当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
- 当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则 - 长按HOME键,选择运行其他的程序时。
- 按下电源按键(关闭屏幕显示)时。
- 从activity A中启动一个新的activity时。
- 屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。
onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原
在播放视频过程中,横竖屏切换要保持当前播放时间进度,在默认情况下播放时间是不被自动保存的。我们还要保存一些其他数据的时候, 我们就需要覆盖onSaveInstanceState()方法来保存Activity的附件信息
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("currentposition", videoView.getCurrentPosition());
Log.v("tag", "onSaveInstanceState");
super.onSaveInstanceState(outState);
}
onCreate中:
if (savedInstanceState != null
&& savedInstanceState.getInt("currentposition") != 0) {
videoView.seekTo(savedInstanceState.getInt("currentposition"));
}
android:configChanges
APP运行时,一些设备的配置可能会改变,如:横竖屏的切换、键盘的可用性等会导致Activity重启,即oncreate会被再次调用, 如果oncreate方法中有向服务器请求的方法,那么悲剧就会发生,相当于多次请求。这也是项目测试中通过抓包发现的问题,因此查了下,了解了android:configChanges属性,可以设置多个,中间用“|”号隔开。最常用的两个属性:
“orientation” (屏幕方向改变了)和”keyboardHidden” ( 键盘的可用性发生了改变)。
详细使用 在manifest中:
<activity
android:name=".ui.FeedBack"
android:configChanges="keyboardHidden|orientation"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/Theme.HalfTranslucent"
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
在Android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置。在activity加上android:configChanges=”keyboardHidden|orientation”属性,就不会重启activity.而只是调用onConfigurationChanged(Configuration newConfig).这样就可以在这个方法里调整显示方式.
VALUE | DESCRIPTION |
“mcc” | 国际移动用户识别码所属国家代号是改变了—– sim被侦测到了,去更新mcc mcc是移动用户所属国家代号 |
“mnc” | 国际移动用户识别码的移动网号码是改变了—— sim被侦测到了,去更新mnc MNC是移动网号码,最多由两位数字组成,用于识别移动用户所归属的移动通信网 |
“locale” | 地址改变了—–用户选择了一个新的语言会显示出来”touchscreen”触摸屏是改变了——通常是不会发生的 |
“keyboard” | 键盘发生了改变—-例如用户用了外部的键盘 |
“keyboardHidden” | 键盘的可用性发生了改变 |
“navigation” | 导航发生了变化—–通常也不会发生 |
“screenLayout” | 屏幕的显示发生了变化——不同的显示被激活 |
“fontScale” | 字体比例发生了变化—-选择了不同的全局字体 |
“uiMode” | 用户的模式发生了变化 |
“orientation” | 屏幕方向改变了 |
“screenSize” | 屏幕大小改变了 |
“smallestScreenSize” | 屏幕的物理大小改变了,如:连接到一个外部的屏幕上 |
public void onConfigurationChanged(Configuration newConfig) {
try {
super.onConfigurationChanged(newConfig);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.v("Himi", "onConfigurationChanged_ORIENTATION_LANDSCAPE");
} else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
Log.v("Himi", "onConfigurationChanged_ORIENTATION_PORTRAIT");
}
} catch (Exception ex) {
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.himi" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
总结:一般加上
android:configChanges="keyboard|keyboardHidden|orientation|locale"
android:screenOrientation="portrait"
Android中的onActivityResult和setResult方法的使用
相关函数:
startActivityForResult(Intent intent, Int requestCode)
setResut(int resultCode, Intent intent)
onActivityResult(int requestCode, int resultCode, Intent intent)
1、onActivityResult()方法中的第二个参数就是SecondActivity传回来的键,第三个参数就是SecondActivity传回来的键对应的值。
final int RESULT_CODE = 101;
final int REQUEST_CODE = 1;
public void enterSecond(View view) {
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "onActivityResult" + "requestCode" + requestCode + "\n resultCode=" + resultCode);
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_CODE) {
String result = data.getStringExtra("second");
textView.setText(result);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
2、SecondActivity 类中的代码:
这个里面的RESULT_CODE、intent分别跟上段代码中onActivityResult()方法中的第二个、第三个参数相对应。
final int RESULT_CODE = 101;
public void closeButton(View view) {
Intent intent = new Intent();
intent.putExtra("second", "I am second!");
setResult(RESULT_CODE, intent);
finish();
}
3、除此之外,onActivityResult()方法中的第二个参数resultCode还有系统自带的一些参数,也就是说,如果我们启动的intent是隐式意图,那么可以用Activity类中RESULT_OK来表示操作已经顺利结束。
例如,调用系统图库的返回,请看代码:
final int CROP_PIC_REQUESTCODE = 23;
final int SELECT_PICTURE = 21;
if(resultCode ==RESULT_OK &&requestCode ==SELECT_PICTURE)
{
System.out.println("调用图库返回,关闭activity");
Intent intent1 = new Intent("com.android.camera.action.CROP");
intent1.setDataAndType(data.getData(), "image/*");
intent1.putExtra("crop", "true");
intent1.putExtra("aspectX", 1);
intent1.putExtra("aspectY", 1);
intent1.putExtra("outputX", 80);
intent1.putExtra("outputY", 80);
intent1.putExtra("return-data", true);
startActivityForResult(intent1, CROP_PIC_REQUESTCODE);
}
当然,我们还可以看下源码中还有哪些类似RESULT_OK的
/**
* Standard activity result: operation canceled.
*/
public static final int RESULT_CANCELED = 0;
/**
* Standard activity result: operation succeeded.
*/
public static final int RESULT_OK = -1;
/**
* Start of user-defined activity results.
*/
public static final int RESULT_FIRST_USER = 1;
@Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed");
setResult(Const.LIVE_OK);
super.onBackPressed();
}