Activity的生命周期
- onCreate():创建时调用
- onStart():在屏幕上可见,但是还没有获取焦点
- onResume():可见并且获取焦点
- onRestart():
- onPause():可见,但是失去焦点
- onStop():不可见,但是仍然存在内存当中
- onDestory():销毁了
Activity的重新创建过程
- Activity非正常结束(如:内存不足、用户直接按Home键),系统会回收activity。此时系统为了补偿你,会将Activity状态通过[onSaveInstanceState()]方法保存到Bundle对象中(可以自己增加额外的键值对保存到Bundle),当需要重新创建此activity时,保存的bundle对象会传递到activity的[onRestoreInstanceState()]方法和onCreate()方法中。这也就是onCreate()方法中参数 -- Bundle savedInstanceState的来源。
- 主动销毁一个activity时,不调用onSaveInstanceState()
- 在onPause()方法中持久化数据,在onSaveInstanceState保存瞬态数据,并在onPause()之后调用
AndroidMainifest启动模式
standard
- 默认的启动模式,栈模式
- 创建ABB界面:(A)- (AB)-(ABB)
singleTop
- 当Activity的实例不在栈顶,那么就会创建该Activity的实例,如果已经在栈顶就不会再创建了
- 创建ABB界面:(A)- (AB)- (AB)
singleTask
- 如果Activity没有被创建任何实例,那么启动时会创建,如果已经创建了一个实例,那么启动时是返回至该Activity而不会再创建该Activity,并且把该Activity上的实例全部清除。始终保证该栈中永远只有一个该Activity的实例。
- 创建ABCB界面:(A)-(AB)- (ABC)- (AB)
singleInstance
- 在单独一个任务栈中创建该Activity的实例,然后再也不会创建第二个实例,以后每次启动该Activity,都是把该Activity所在的栈显示在前台。保证整个系统的内存都只有一个该Activity的实例。来电界面就是该模式。
- 如果该Activity在前台,按返回键会销毁改Activity,并把该任务栈放置后台,然后会切换到原来的任务栈;如果该Activity的任务栈在后台,不论什么时候启动的,都是在原来的任务栈实例都销毁之后,才会将该任务栈放置前台。
- 类似浏览器工作原理。多个程序中访问浏览器时,如果浏览器没打开,则打开浏览器,否则会在当前打开浏览器中访问。
Intent设置Flag来设置Activity的启动模式:
- Intent.FLAG_ACTIVITY_NEW_TASK:使用一个新的Task来启动一个Activity,但启动的每个Activity都将在一个新的Task中,通常该Flag使用在Service中启动activity的场景,由于在service中并不存在Activity栈,所以使用该Flag来创建一个新的activity栈,并创建新的Activity实例
- Intent.FLAG_ACTIVITY_SINGLE_TOP(singleTop)
- Intent.FLAG_ACTIVITY_CLEAR_TOP(singleTask)
- Intent.FLAG_ACTIVITY_NO_HISTORY:使用这种模式启动activity,当该Activity启动其他activity后,该activity就消失了,不会保留在activity栈中。例如A-B,B中以这种模式启动C,C在启动D,则当前activity栈为ABD
清空任务栈
- 系统提供了清空任务栈的方法来让我们将一个Task全部清除。在AndroidMainifest文件中的<activity>标签中使用以下几种属性来清理任务栈。
- clearTaskOnLaunch:每次返回该Activity时,都将该Activity之上的所有Activity都清除。通过这个属性,可以让这个Task每次在初始化的时候,都只有一个Activity。
- finishOnTaskLaunch:当离开这个Activity所处的Task,那么用户再返回时, 该Activity就会被finish掉。
- alwaysRetainTaskState:如果将Activity的这个属性设置为true,那么该Activity所在的Task将不接受任何清理命令,一直保持当前的Task状态。
Activity的启动方式
直接启动
A:
Intent intent = new Intent(this,xxx.class);
startActivity(intent);
B:
Intent intent = new Intent();
ComponentName conmonent = new ComponentName(this,xxx.class);
intent.setComponent(component);
startActivity(intent);
匿名启动 -- 启动系统的Activity
- 在跳转前的Activity的xml中添加
<intent-filter>
<action android:name="www.imooc.com">
<!-- Category属性用于指定当前动作(Action)被执行的环境 -->
<actegory android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Intent intent = new Intent();
intent.setAction("www.imooc.com");
startActivity(intent);
启动系统的Activity
启动系统浏览器
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.parse("http:www.imooc.com");
intent.setData(uri);
startActivity(intent);
启动系统图库
intent.setAction(Intent.ACTION_GET_CONTENT)
intent.setType("image/*")
发送短信
intent.setAction(Intent.ACTION_SEND)
intent.setType("text/plain")
intent.putExtra(Intent.EXTRA_TEXT,"I now")
启动电话界面
intent.setAction(Intent.ACTION_CALL)
Uri uri = Uri.parse("tel:123456");
intent.setData(url)
Activity的数据交换
传递基本的数据类型
实现Serializable传递对象
- Serializable的作用是将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
javabean实现Serializable(序列化)接口
Bundle.putSerializable(Key,Object)
getIntent.getSerializableExtra("user");
实现Parcelable传递对象
- 本质上可以当成一个Serializable,只是Parcelable的对象是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此更加高效。
### 自定义实体类,实现Parcelable接口,重写其两个方法
@Override
public int describeContents() {
return 0;
}
// 将对象中的属性保存至目标对象dest中
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
### 创建带有参数的构造方法,本构造方法仅供类的方法createFromParcel调用
public User(Parcel source){
name = source.readString();
age = source.readInt();
}
# 该实体类必须添加一个常量CERATOR(名字和大小写都不能是其他的),该常量必须实现Parcelable的内部接口:
Parcelable.Creator,并实现该接口中的两个方法.
// 必须要创建一个名叫CREATOR的常量。
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<User>(){
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
//重写createFromParcel方法,创建并返回一个获得了数据的user对象
@Override
public User[] newArray(int size) {
return new User[size];
}
};
为什么要将对象序列化?
- 永久性保存对象,保存对象的字节序列到本地文件中。
- 通过序列化对象在网络中传递对象。
- 通过序列化对象在进程间传递对象。
为什么使用Parcelable接口来实现在Intent中传递对象?
- 在使用内存的时候,Parcelable比Serializable性能高,推荐用Parcelable类。
- Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
- 注意:Parcelable不能使用在将数据存储在磁盘上的情况。因为Parcelable不能很好的保存数据的持续性在外界有变化的情况下。这种情况要使用Serializable。
Activity传递大数据时遇到的问题?
- bundler传递数据一般不能超过0.5M的内容。
- 当数据超出后,提示“!!! FAILED BINDER TRANSACTION !!!”红色异常,且Activity界面不再跳转。
- TransactionToolLargeException传递数据过大异常。
onActivityResult
- 使用startActivityForResult()方法,参数1为intent,参数2为自己定义的请求码
public void onSelect(View view){
Intent intent = new Intent(this, ListViewActivity.class);
startActivityForResult(intent, FLAG_0);
}
- 第2步:在下个Activity使用setResult()+finish()返回,参数一固定为:RESULT_OK
String number = list.get(position);
Intent intent = new Intent();
intent.putExtra("number",number);
setResult(RESULT_OK,intent);
finish();
- 第3步:在第一个Activity中处理
* requestCode 自定的请求码
* resultCode setResult()中的结果码:RESULT_OK
* data intent
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FLAG_0 && resultCode == RESULT_OK) {
String number = data.getStringExtra("number");
text.setText(number);
}
}
设置Activity运行时屏幕的方向
- 通过xml设置横竖屏
<activity
android:name=".MainActivity"
<-- protrait为竖屏,landscape为横屏 -->
android:screenOrientation="portrait(肖像/竖屏) | landscape(风景/横屏) | sensor(传感器/通过重力感应来判断横竖屏)"
<-- 横竖屏、屏幕大小、弹出软键盘不销毁重建Activity -->
android:configChanges="orientation|screenSize|keyboardHidden"h
android:label="@string/app_name" >
- 通过代码设置横竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);~~~
# Activity全屏
##### 不显示系统的标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);~~~
不显示程序的标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);~~~
##### 透明系统的标题栏(沉浸菜单栏)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
<-- AndroidManifest.xml中填写,通过theme设置 -->
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"~~~
再按一次退出程序
// 监听返回键
long time = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()==0) {
if (System.currentTimeMillis() - time > 2000) {
Toast.makeText(this, "再按一次退出系统",0).show();
time = System.currentTimeMillis();
} else {
System.exit(0);
}
//此处一定要反回true,否则监听失败
return true ;
}
return super.onKeyDown(keyCode, event);
}
启动Activity的最佳写法
/**
* 第一个Activity
*/
SecondActivity.actionStart(FirstActivity.this,"data1","data2");
/**
* 第二个Activity
*/
public static actionStart(Context context,"data1","data2"){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1","data1");
intent.putExtra("param2","data2");
context.startActivity(intent);
}~~~
# 获取当前是哪个Activity
public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ getClass:是Object中的方法,表示获取当前对象的类
@ getSimpleName:是Class中的方法,表示获取当前类的名称
Log.d("BaseActivity", getClass().getSimpleName());
}
}~~~
一键销毁所有Activity
- 首先创建一个管理Activity的管理器
public class ActivityCollector {
//存储Activity的List
public static List<Activity> activities = new ArrayList<Activity>();
//添加Activity -- 静态
public static void addActivity(Activity activity) {
activities.add(activity);
}
//移出Activity -- 静态
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
// 销毁其他Activity -- 静态
public static void finishOther(Activity currentActivity){
for (Activity activity : activities) {
if (currentActivity != activity && activity.isFinishing()) {
activity.finish();
}
}
}
//销毁所有Activity -- 静态
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
- 在任何地方调用ActivityCollector.finishAll()就可以销毁所有的activity
public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//添加该活动
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//删除该活动
ActivityCollector.removeActivity(this);
}
}~~~
# Activity的意外回收,处理临时数据
public class MyActivity extends Activity {
//在创建活动时调用,恢复临时数据
@Override
protected void onCreate(Bundle savedInstanceState) { -- 此Bundle就是onSaveInstanceState()保存的数据
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
if (savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
}
}
//在活动意外销毁前一定会被调用,保存临时数据
@Override
protected void onSaveInstanceState(Bundle outState) { -- 进行数据保存
String tempData = "Something you just typed";
outState.putString("data_key", tempData);
}
}~~~
网友评论