学习笔记 4.3 Activity的生命周期与加载模式

4.3.1Activity的生命周期演示

Activity大致会经过如下4种状态:
    1.运行状态:当前Activity位于前台(返回栈的栈顶),用户可见,可以获得焦点。
    2.暂停状态:其他Activity位于前台 (返回栈的栈顶) ,但该Activity依然可见,只是不能获得焦点
    3.停止状态:该Activity不可见,失去焦点,该 Activity不在处于栈顶位置。

    4.销毁状态:该Activity结束,或Activity所在的进程被结束。(该Activity从返回栈中移除)


 开发Activity时经常复写onCreate(Bundle saveStatus)方法,该方法用于对该Activity进行初始化。
除此之外,覆盖onPause()也很常见,比如用户正在玩一个游戏,此时有电话进来,那么我们需要将当前游戏暂停,并保存该游戏的进行状态,这就可以通过覆盖onPause()方法来实现。接下来当用户切换到游戏状态时,onResume()方法已经被回调,因此可以通过复写onResume()方法来恢复游戏状态。
     
      onCreate(): 它会在活动第一次被创建的时候调用。应该在这个方法中完成活动的初始化操作,比如加载布局、绑定事件等。
      onStart():     这个方法在活动由不可见变为可见的时候调用
      onResume():这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
      onPause():这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动 的使用。
      onStop():这个方法在活动完全不可见的时候调用。它和onPause()的主要区别在于。如果启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,而onStop()方法不会执行
    onDestory():这个方法在活动被销毁之前调用,之后活动将变为销毁状态。
    onRestart():这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。    
以上7个方法中除了onRestart(),其他都是两两相对的,从而又可以将活动分为3种生存期。
       完整生存期:onCreate()----onDestroy()。一般情况下,一个活动会在onCreate()方法中完成各种初始化操作,而在onDestroy()中完成释放内存的操作。
      可见生存期:onStart()---onStop()。在可见生存期内,活动对于用户总是可见的,即使有可能无法和用户交互。我们也可以通过这两个方法,合理的管理那些对用户可见的资源。比如在onStart()中对资源进行加载,在onStop()中对资源进行释放,从而保证处于停止状态的活动不会占用过多内存。
     前台生存期:onResume()--onPause()。在前台生存区内,活动总是处于运行状态的,此时活动是可以和用户进行交互的。

例:MainActivity中有两个button,一个用于启动对话框风格的Activity,另一个用于退出该应用

package com.example.administrator.lifetest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
   final String MTAG = "MYTEST";
    Button startActivity,closeActivity;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e(MTAG,"----onCreate----");
        startActivity = (Button)findViewById(R.id.startActivity);
        closeActivity = (Button)findViewById(R.id.closeActivity);
        startActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivitry.class);
                startActivity(intent);
            }
        });
        closeActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.this.finish();
            }
        });
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.e(MTAG,"----onStart----");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.e(MTAG,"----onResume----");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.e(MTAG,"----onPause----");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.e(MTAG,"----onStop----");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(MTAG,"----onDestroy----");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e(MTAG,"----onRestart----");
    }
}

布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.lifetest.MainActivity">
  <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="startActivity"
      android:id="@+id/startActivity"
      />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/startActivity"
        android:text="closeActivity"
        android:id="@+id/closeActivity"
        />
</RelativeLayout>

SecondActivitry

public class SecondActivitry extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText("对话框风格的Activity");
        setContentView(textView);
    }
}
注意记得在AndroidManifest.xml中配置 主题为对话框风格
<activity android:name=".SecondActivitry"
           android:theme="@style/Base.V7.Theme.AppCompat.Dialog">
 </activity>

1.当程序启动时,会自动启动并执行MainActivity





2.当点击  “启动对话框风格的Activity” 按钮时
(对话框风格的Activity进入前台,虽然MainActivity不能获得焦点,但依然部分可见,所以进入暂停状态)


如果不是启动的对话框风格的Activity,会进入Stop状态,可以注释掉 AndroidManifest.xml中
android:theme="@style/Base.V7.Theme.AppCompat.Dialog"

结果如下



3.点击返回后(MainActivity再次进入运行状态)

4.按下HOME键, MainActivity失去焦点并且不可见,但它并未销毁,进入stop状态


5.再次启动该应用程序


6.点击 “CLOSEACTIVITY” 按钮后 ,MainActivity将会被销毁


4.3.3Activity的4种加载模式
   
       Android对Activity的管理:Android采用Task来管理多个Activity,当我们启动一个应用时,Android就会为之创建一个Task,然后启动这个应用的入口Activity(即<intent-filter.../ >中配置为MAIN和LUNCHER的Activity)。Task以栈的形式来管理Activity,这个栈也被称之为返回栈,先启动的Activity放在Task栈底,后启动的Activity放在Task栈顶。每当我们按下Back键或者调用finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈的活动会重新处于栈顶位置。系统总是会显示处于栈顶的活动给用户。
    由于Android没有为Task提供API,只能调用Activity的getTaskId()来获取它所在的Task的ID

   配置Activity时可指定android:launchMode属性,该属性用于配置该Activity的加载模式
standard:  标准模式,这是默认的加载模式
singleTop:Task栈顶单例模式
singleTask:Task内单例模式
singleInstance:全局单例模式
1.standard模式
      每次通过这种模式来启动目标Activity时,Android总会为目标Activity创建一个新的实例,并将该Activity添加到当前Task栈中----这种模式不会启动新的Task,新Activity将被添加到原有的Task中。
  
例:每次点击button都会再次启动MainActivity。

public class MainActivity extends AppCompatActivity {
    Button startActivity;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        startActivity = (Button)findViewById(R.id.startActivity);
         textView.setText("Activity为:"+this.toString()+"\n"+"Task的ID为"+this.getTaskId());
        startActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}
   

不同Activity实例的hashCode值有差异,但它们所在的Task ID总是相同的----表明这种加载模式不会使用全新的Task

2.singleTop模式
     与standrad模式基本相同,但有一点不同:当将要启动的Activity已经位于Task栈顶时,系统不会重新创建目标Activity的实例。
    不再用默认加载模式,在AndroidManifest.xml中把加载模式改为singleTop

<activity android:name=".MainActivity"                                                     
         android:launchMode="singleTop">
无论再点击多少次button,界面上的程序都不会有任何变化。

3.singleTask模式
    采用这种加载模式的Activity在同一个Task内只有一个实例,当系统采用singleTask模式时。
        (1)如果要加载的目标Activity不存在,系统将会创建目标Activity的实例,并将它加入Task栈顶。
        (2)如果将要启动的Acitvity已经在栈顶,此时与singleTop的行为相同
        (3)如果将要启动的目标Activity已经存在,但没有位于Actvity栈顶,系统将会把位于该Activity上的所有Activity都移出Task栈,从而使得目标Activity转入栈顶。
    
例:MainActivity的加载模式为standrad,SecondActicity的加载模式为singleTask
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.lifetest">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivitry"
            android:launchMode="singleTask"
            ></activity>
    </application>
</manifest>
MainActivity的button点击事件是启动SecondActicity,textview显示当前Acticvity 和 所在的Task ID
public class MainActivity extends AppCompatActivity {
//   final String MTAG = "MYTEST";
    Button startActivity;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        startActivity = (Button)findViewById(R.id.startActivity);
         textView.setText("Activity为:"+this.toString()+"\n"+"Task的ID为"+this.getTaskId());
        startActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivitry.class);
                startActivity(intent);
            }
        });
    }
}
  SecondActicity 的button点击事件是启动 MainActivity ,textview显示当前Acticvity 和 所在的Task ID
public class SecondActivitry extends AppCompatActivity {
     Button but;
     TextView tex;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_second);
        but = (Button) findViewById(R.id.startMain);
        tex = (TextView) findViewById(R.id.stx);
        tex.setText("Activity为:"+this.toString()+"\n"+"Task的ID为"+this.getTaskId());
        but.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent mintent = new Intent(SecondActivitry.this,MainActivity.class);
                startActivity(mintent);
            }
        });
    }
}
应用程序LifeTest
 1.进入MainActivity                     2.点击button进入SecondActivity          3.点击button进入MainActivity

  

4.点击button进入SecondActivity


会发现这两次进入SecondActivity的实例都一样都一样 
而此时Task栈中 只剩两个Activty实例: 第一个MainActivity----SecondActivity
点返回键之后退回到第一个MainActivity,再返回一次会退出应用程序
4.singleInstance模式
     在singleInstance模式下,系统保证无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会用一个全新的Task栈来加载该Activity实例
    (1)如果将要启动的目标Actvity不存在,系统会先创建一个全新的Task栈,再创建目标Activity的实例,并将它加入新的Task栈顶
     (2)如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中,位于哪个Task中系统都会把该Activity所在的Task转到前台,从而使该Activity显示出来
     采用singleInstance模式加载的Activity总是位于Task栈顶,且采用singleInstance模式加载的Activity所在的Task将只包含该Activity

   把singleTask例子中SecondActivity的加载模式改为singleInstance,并且将exported属性配置成true--表明该Activity能被其他应用程序启动。并且配置<intent-filter.../>子元素,表明该Activity可通过隐式Intent启动

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.lifetest">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivitry"
            android:launchMode="singleInstance"
            android:exported="true">
            <intent-filter>
                <!--指定该Activity能响应Action为指定字符串"xufelony"的Intent-->
              <action   android:name ="xufelony"/>
              <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
    </application>
</manifest>
重新新建一个Project
SingleActivity 使用隐式Intent启动该SecondActivity,就算他们不在同一个应用程序

public class SingleActivity extends AppCompatActivity {
    Button button;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single);
        button = (Button) findViewById(R.id.startSecond);
        textView = (TextView) findViewById(R.id.testlauchSecond);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //使用隐式Intent启动SecondActivity
                Intent intent = new Intent();
                intent.setAction("xufelony");
                startActivity(intent);
            }
        });
    }
}
在应用程序SingleInstanceTest的SingleActivity
当点击button时,会把SecondActivity所在的Task(应用程序LifeTest)转入前台(注意此时 LifeTest的Task栈中只有 SecondActivity而没有 MainActivity。 因为采用singleInstance模式加载的Activity所在的Task将只包含该Activity ),从而将 SecondActivity显示出来





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值