二、活动(Activity)的生命周期

来源:互联网 发布:java简单源码 编辑:程序博客网 时间:2024/05/22 08:11

  • 返回栈
  • 活动状态
  • 活动的生存期
  • 体验活动的生命周期
    • 活动被回收后
  • 活动的启动模式
    • standard
    • singleTop
    • singleTask
    • singleInstance
  • 相关实践
    • 获知当前活动
    • 随时随地退出程序
    • 启动活动的最佳写法

返回栈

安卓的活动会覆盖,实现的机制用的是栈

活动状态

四种:

运行状态;暂停状态;停止状态;销毁状态;

活动的生存期

七个

onCreate();onStart();onResume();onPause();onStop();onDestroy();onRestart();

这里写图片描述


体验活动的生命周期

三个Activity,一个NormalActivity, 一个DialogAcitvity, 一个MainActivity
NormalActivity:

protected void onCreate(Bundle savedInstanceState) {    // TODO Auto-generated method stub    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);    setContentView(R.layout.normal_layout); }

DialogAcitvity:

protected void onCreate(Bundle savedInstanceState) {    // TODO Auto-generated method stub    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);    setContentView(R.layout.dialog_layout);}

配置:

 <activity     android:name=".MainActivity"     android:label="@string/app_name" >     <intent-filter>         <action android:name="android.intent.action.MAIN" />         <category android:name="android.intent.category.LAUNCHER" />     </intent-filter> </activity> <activity android:name=".NormalActivity"> </activity> <activity      android:name=".DialogActivity"      android:theme="@android:style/Theme.Dialog"     > </activity>

MainActivity:

  protected void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      Log.d(TAG, "onCreate");      requestWindowFeature(Window.FEATURE_NO_TITLE);      setContentView(R.layout.activity_main);      Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);      Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);      startNormalActivity.setOnClickListener(new OnClickListener() {    @Override    public void onClick(View arg0) {        // TODO Auto-generated method stub        Intent intent = new Intent(MainActivity.this, NormalActivity.class);        startActivity(intent);    }});      startDialogActivity.setOnClickListener(new OnClickListener() {    @Override    public void onClick(View arg0) {        // TODO Auto-generated method stub        Intent intent = new Intent(MainActivity.this, DialogActivity.class);        startActivity(intent);    }});  }  @Override  protected void onStart() {    // TODO Auto-generated method stub    super.onStart();    Log.d(TAG, "onStart");  }  @Override  protected void onResume() {    // TODO Auto-generated method stub    super.onResume();    Log.d(TAG, "onResume");  }  @Override  protected void onPause() {    // TODO Auto-generated method stub    super.onPause();    Log.d(TAG, "onPause");  }  @Override  protected void onStop() {    // TODO Auto-generated method stub    super.onStop();    Log.d(TAG, "onStop");  }  @Override  protected void onDestroy() {    // TODO Auto-generated method stub    super.onDestroy();    Log.d(TAG, "Destory");  }  @Override  protected void onRestart() {    // TODO Auto-generated method stub    super.onRestart();    Log.d(TAG, "Restart");  }  @Override  public boolean onCreateOptionsMenu(Menu menu) {      // Inflate the menu; this adds items to the action bar if it is present.      getMenuInflater().inflate(R.menu.main, menu);      return true;  }

依次进入每个活动,MainActivity的状态:
onCeate()->onStart->onResume->

进入Normal:
onPause->onStop

返回:
onRestart->onStart->onResume

点击DialogAcitivity
onPause(没有onStop,因为这是对话框形式,所以MainActivity没有stop)

返回:
onResume

最后再返回:
onPause->onStop->onDestory


活动被回收后

如果内存不足,先开的活动被回收了,在返回那个活动时,会重新onCreate,同时活动的数据也没了。因此需要新的机制:onSaveInstanceState来解决保存回收前的已有数据问题。

@Override//这里面的Bundle就是onCreate的Bundle参数protected void onSaveInstanceState(Bundle outState) {    // TODO Auto-generated method stub    super.onSaveInstanceState(outState);    String tempDate = "要保存的内容";    outState.putString("data_key", tempDate);}

onCreate里面取数据:

if(savedInstanceState!=null){    String tempData = savedInstanceState.getString("data_key");    Log.d(TAG, tempData);}

Tip:Intent可以和Bundle一起用于传递数据,首先可以将Bundle放在Intent里面,然后传递Intent


活动的启动模式

standard

standard 是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用这种启动模式。因此,到目前为止我们写过的所有活动都是使用的 standard 式。在 standard 模式(即默认情况)下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于使用standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例
FirstActivity里的onClick:

Intent intent = new Intent(FirstActivity.this, FirstActivity.class);startActivity(intent);

onCreate里面:
加上:

Log.d("FirstAcitivity",this.toString());

点击按钮也就是自己调用自己,结果:需要自己按多次返回键

singleTop

配置文件中的Activity加上android:launchMode=”singleTop”属性,表示只有一个实例
但是如果活动不是在栈顶,还是会创建多个实例:
FirstActivity和SecondActivity互相循环调用,就不算是singleTop模式,仍然需要按多次返回

singleTask

在整个应用程序的上下文中只有一个实例,就不能循环调用(创建)了,2调用1,因为1已经在栈,所以2直接出栈调用1,2会被销毁。不像上面直接创建一个新的1。SingleTop会往上累加Activity,而singlTask,往下找Activity,找到后进入该Activity并会退出当前活动

singleInstance

指定为 singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果 singleTask 模式指定了不同的 taskAffinity,也会启动一个新的返回栈) 。那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,应该如何实现呢?使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。

案例:
1调用2,2调用3,2设置为singleInstance。
结果是1,3的taskid是相同的,与2不同,说明2放在了另一个栈中,返回时直接从3返回到1,再返回到2,再退出(因为1,3在同一个栈,所以2单独放在最后才退出)。


相关实践

获知当前活动

加上这句(可以知道哪个Activity继承了这个Activity,如果继承了,都会打出BaseActivity,因为这句话加载BaseActivity中的onCreate中)

Log.d("BaseActivity", getClass().getSimpleName());

随时随地退出程序

每次完全退出,都要按返回,知道主活动,如何才能快速的退出
设计一个Collector类,一旦有活动(继承同一个活动)创建,在加入list(基类Activity中的onCreate方法中加入),finishAll()方法可以直接退出(最后一层调用button的onclick里面调用),这样不用一次一次返回了

public static List<Activity> activities = new ArrayList<Activity>();public static void addActivity(Activity activity){    activities.add(activity);}public static void removeActivity(Activity activity){    activities.remove(activity);}public static void finishAll(){    for(Activity activity:activities){        if(!activity.isFinishing()){            activity.finish();        }    }}

启动活动的最佳写法

假设 SecondActivity 中需要用到两个非常重要的字符串参数,在启动 SecondActivity 的时候必须要传递过来,那么我们很容易会写出如下代码:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);intent.putExtra("param1", "data1");intent.putExtra("param2", "data2");startActivity(intent);

这样写是完全正确的,不管是从语法上还是规范上,只是在真正的项目开发中经常会有对接的问题出现。比如 SecondActivity 并不是由你开发的,但现在你负责的部分需要有启动SecondActivity 这个功能,而你却不清楚启动这个活动需要传递哪些数据。这时无非就有两种办法,一个是你自己去阅读 SecondActivity 中的代码,二是询问负责编写 SecondActivity的同事。你会不会觉得很麻烦呢?其实只需要换一种写法,就可以轻松解决掉上面的窘境.
我们在 SecondActivity 中添加了一个 actionStart()方法,在这个方法中完成了 Intent 的构建,另外所有 SecondActivity 中需要的数据都是通过 actionStart()方法的参数传递过来的,然后把它们存储到 Intent 中,最后调用 startActivity()方法启动 SecondActivity(原因在于函数一般都会注明参数,可以自己看)

public static void actionStart(Context context, String data1, String data2){    Intent intent = new Intent(context, SecondActivity.class);    intent.putExtra("param1", data1);    intent.putExtra("param2", data2);    context.startActivity(intent);}

在FirstActivity里面的onClick中加入:

SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
0 1