您的位置:首页 > 其它

安卓开发笔记——重识Activity

2015-08-28 17:06 501 查看
  Activity并不是什么新鲜的东西,老生常谈,这里只是随笔记录一些笔记。

  每当说起Activity,感觉最关注的还是它的生命周期,因为要使我们的应用程序更加健壮,客户体验更加良好,如果对生命周期不熟悉,那是不可能完成的任务。好了,言归正传,开始笔记,尽可能用最精简的言语来阐述最实用的东西。

  准备写几篇文章,这是第一篇只谈生命周期的普通用法,不涉及到复杂点的知识,比如任何栈回退栈等操作。

1、一张来自谷歌官方文档的Activity的生命周期图:

package com.lcw.rabbit.activitydemo;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

private static final String TAG = "Rabbit";

private Button mbButton;
private MediaPlayer mMediaPlayer;
private int mCurrentPosition;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//点击按钮跳转第二个Activity
mbButton = (Button) findViewById(R.id.bt_button);
mbButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
});

//播放音乐
mMediaPlayer=MediaPlayer.create(this,R.raw.music);
mMediaPlayer.start();

Log.i(TAG, "1----------onCreate");
}

@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "1----------onStart");
}

@Override
protected void onResume() {
super.onResume();
if(mCurrentPosition!=0){
//如果当前有记录进度,继续播放
mMediaPlayer.seekTo(mCurrentPosition);
mMediaPlayer.start();
}
Log.i(TAG, "1----------onResume");
}

@Override
protected void onPause() {
super.onPause();
//记录当前进度
mCurrentPosition=mMediaPlayer.getCurrentPosition();
mMediaPlayer.pause();
Log.i(TAG, "1----------onPause");
}

@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "1----------onStop");
}

@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "1----------onRestart");
}

@Override
protected void onDestroy() {
super.onDestroy();
//释放资源
mMediaPlayer.release();
mMediaPlayer=null;
Log.i(TAG, "1----------onDestroy");
}
}


MainActivity.java

5、关于Activity数据状态的保存

  由于手机是便捷式移动设备,掌握在用户的手中,它的展示方向我们是无法预知的,具有不确定性。平时我们拿着手机多数为竖屏,但有时候我们感觉累了也会躺着去使用手机,那么这时手机屏幕的展示方向可能已经被用户切换成横屏,由于竖屏和横屏的界面宽高比例不同,那么我们的布局界面就会发生改变,所以是件很麻烦的事情,我们需要去准备两套UI布局,当然很多时候我们为了节省设计成本,只准备一套UI布局(竖屏或者横屏),使程序固定在一个方向,让其不跟随着屏幕的旋转而旋转。在这里我们先不去管这些东西,我们来看看当屏幕旋转的时候,Activity的生命周期是怎么走的:

实验五:

  启动一个Activity,对屏幕进行翻转,观看生命周期的变化

结论:

  在我们翻转屏幕的时候,会销毁当前的Activity,然后重建Activity。



  对Activity进行重建的时候,我们的数据就会丢失,很多时候,当我们切换到别的Activity的时候,需要保存当前Activity的状态或者是临时数据,那么我们该怎么办呢?

  我们在Activity里再覆写这两个方法:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, "1----------onSaveInstanceState");
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i(TAG, "1----------onRestoreInstanceState");
}


  然后我们再来看下这两个方法是什么时候被调用的:

1、当正常进入退出的时候,生命周期依旧正常,这两个方法没有被调用:



2、当我们正常进入一个Activity点击按钮跳转到别的Activity的时候,我们会发现onSaveInstanceState在第二个Activity获取屏幕焦点(onResume)之后,在第一个Activity执行onPause之后,onStop之前调用了此方法,当从第二个Activity切换回来的时候就重复执行着实验四。



  细心的朋友可能已经发现,onSaveInstanceState方法里有个Bundle类型的回调参数,在onCreate里面也有个Bundle类型的参数,没错,答案就在这里,如果我们要对Activity的数据或者状态进行临时性的保存时,我们可以在onSaveInstaceState存入参数,类似这样的:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("name","Rabbit");
Log.i(TAG, "1----------onSaveInstanceState");
}


  在onCreate里获取:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取保存数据
if (savedInstanceState!=null){
Log.i(TAG, "I am "+savedInstanceState.get("name") );
}

//点击按钮跳转第二个Activity
mbButton = (Button) findViewById(R.id.bt_button);
mbButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
});

Log.i(TAG, "1----------onCreate");
}


  在onRestoreInstanceState里取:

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//获取保存数据
if (savedInstanceState!=null){
Log.i(TAG, "I am "+savedInstanceState.get("name") );
}
Log.i(TAG, "1----------onRestoreInstanceState");
}


  无图无真相,来看下实验结果图,我进入了Activity对屏幕翻转,触发Activity重建,可以看到数据已经被保存了。



  但这里有个疑问,当我们不翻转屏幕,也就是不触发Activity重建的时候,我们是没有执行onCreate,onRestoreInstanceState方法的,所以这个Bundle对象我们不一定是可以拿到的,那数据保存不就变得很不可靠了吗?

  没错,由于Activity重建的不确定,所以saveInstanceState保存的数据一般都是临时性的,真正持久化操作我们应该在onPause方法里操作。

这里额外的要提到一点,onRestoreInstanceState方法在两种状态下会被调用:

1、在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity,此方法会被调用;

2、在用户改变屏幕方向时,重建的过程中,此方法会被调用。

[b]6、关于屏幕方向改变Activity会重建的应对策略:[/b]

1、

  指定为竖屏:在AndroidManifest.xml中对指定的Activity设置:

android:screenOrientation="portrait"


  或者在onCreate方法中指定:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  //竖屏


  指定为横屏:在AndroidManifest.xml中对指定的Activity设置:

android:screenOrientation="landscape"


  或者在onCreate方法中指定:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //横屏


2、

  锁定屏幕虽然可以实现我们想要的效果,但并不是很好的一种做法,为了避免这样销毁重建的过程,我们可以在AndroidMainfest.xml中对对应的<activity>配置:

android:configChanges="orientation"


  如果是Android4.0,则是:

android:configChanges="orientation|keyboardHidden|screenSize"


  然后我们在Activity里重写onConfigurationChanged方法:

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(TAG, "1----------onConfigurationChanged");
}


  这样Activity在翻转屏幕的时候就不会被销毁重建了,只是调用了onConfigurationChanged方法。

总结:

做工作中,你可能感兴趣的三个关键环① 完整生命周期② 可见生命周期③ 可交互生命周期
如图所示,图中的周期都是大的包括小的:



在实际工作中的使用
①onResume可见, 可交互.。把动态刷新的操作启动。
②onPause部分可见, 不可交互. 把动态刷新的一些操作, 给暂停了。
③onCreate 初始化一些大量的数据
④onDestroy 把数据给释放掉, 节省内存。

  好了,今天先写到这里,关于Activity单单了解这些是远远不够的,下篇文章讲关于Activity的任务栈已经回退栈等操作。

作者:李晨玮
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: