【Android】详解Android Activity 1.创建Activity     2.Activity的跳转 3. Activity的生命周期 4.Activity的四种启动模式 5.横竖屏切换生命周期  6.硬件加速

目录结构:

contents structure [+]

1.1 如何创建Activity

需要在清单文件中为其配置一个activity标签  

1.2 如何创建快捷图标

可以利用下面的intent-filter创建快捷图标

         <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>

        一个应用程序还可以设置多个快捷图标,例如:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="applicationName"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:icon="@drawable/ic_launcher"
            android:label="mainActivityName" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SecondActivity"
            android:icon="@drawable/ic_launcher"
            android:label="SecondActivityName">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

1.3 如何设置应用程序的名称、图标与Activity的名称、图标不相同

  默认情况下,应用程序的名称和Activity的名称是相同的,图标也是。接下来介绍如何把应用程序的名称、图标与Activity的名称、图标不相同
    首先在AndroidManifest.xml文件中,配置应用程序和Activity的名称相同,然后在Activity中调动setTitle()设置标题和通过window对象来改变图标。

  例如,Application.xml代码:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="applicationName"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.test2.MainActivity"
            android:label="applicationName" 
            android:icon="@drawable/ic_launcher">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

  java代码:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Window win = getWindow();
        win.requestFeature(Window.FEATURE_LEFT_ICON);
        setContentView(R.layout.activity_main);
        
        setTitle("activityName");
        win.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
                R.drawable.activity_pic);
    }

这里必须要注意,setContentView方法必须在requestFeature方法之后调用。

如果调用:

win.requestFeature(Window.FEATURE_NO_TITLE);

那么将不会显示Activity的头部。

2.Activity的跳转

 Activity的跳转需要创建Intent对象,通过设置intent对象的参数指定要跳转Activity。

通过设置Activity的包名和类名实现跳转,称为显式意图。

通过指定动作实现跳转,称为隐式意图。

2.1 显示意图

跳转至同一项目下的另一个Activity,直接指定该Activity的字节码即可

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

跳转至其他应用中的Activity,需要指定该应用的包名和该Activity的类名

        Intent intent = new Intent();
        //启动系统自带的拨号器应用
        intent.setClassName("com.android.dialer", "com.android.dialer.DialtactsActivity");
        startActivity(intent);

2.2 隐示意图

在上面的栗子中,如果要实现跳转到系统的某些界面,使用上面的方法的可能并非是绝佳的选择,因为包名、类名可能随着android版本的变化可能不同,可以使用类似下面的隐式意图来实现

        Intent intent = new Intent(Intent.ACTION_DIAL);
        startActivity(intent);

上面介绍的隐式意图是系统自带的,如果想要一个自定义的activity可以被隐式启动,那么需要在清单文件中设置intent-filter子节点:

            <intent-filter>
                <action android:name="com.itheima.second" />
                <data 
                    android:scheme="asd" 
                    android:port="1235"
                    android:host="def"
                    android:path="/test"/>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

action 指定动作(可以自定义,可以使用系统自带的)

data 指定数据(用于筛选Activity)
category 类别 (默认类别,机顶盒,车载电脑)
隐式意图启动Activity,需要为intent设置以上属性,且值必须与该Activity在清单文件中对应属性的定义匹配

例如:

        Intent intent=new Intent();
        intent.setAction("com.itheima.second");
        intent.addCategory("android.intent.category.DEFAULT");
        intent.setData(Uri.parse("asd://def:1235/test"));

这样的intent就能够完全匹配上面的Activity,

data的匹配模板为:scheme://host:port/path      模式://主机:端口/路径

在目标Activity中,可以使用如下的代码来获取用户传递的data

        Intent intent= getIntent();
        Uri uri= intent.getData();

setData多用于过滤Activity的作用,也可以setData传递数据,例如:

       Intent intent=new Intent();
        //Intent.ACTION_VIEW 是系统的浏览器动作
        intent.setAction(Intent.ACTION_VIEW);
        //打开百度
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);

如果手机上有多个浏览器,那么就会弹出让用户选择的浏览器的界面,并且会打开百度页面。

2.3 显示意图和隐式意图的比较

(1).显式意图用于启动同一应用中的Activity

(2).隐式意图用于启动不同应用中的Activity

    如果系统中存在多个Activity的intent-filter同时与你的intent匹配,那么系统会显示一个对话框,列出所有匹配的Activity,由用户选择启动哪一个

2.4 Activity跳转时的数据传递

2.4.1 使用Intent的putExtra传递

第一个Activity中

//创建意图对象
Intent intent = new Intent(this,TwoActivity.class);
//设置传递键值对
intent.putExtra("data",str);
//激活意图
startActivity(intent);

第二个Activity中

// 获取意图对象
Intent intent = getIntent();
//获取传递的值
String str = intent.getStringExtra("data");
//设置值
tv.setText(str);

2.4.2 使用Intent的Bundle传递

第一个Activity中

 //创建意图对象
 Intent intent = new Intent(MainActivity.this,TwoActivity.class);
 //用数据捆传递数据
 Bundle bundle = new Bundle();
 bundle.putString("data", str);
 //把数据捆设置改意图
 intent.putExtra("bun", bundle);
 //激活意图
 startActivity(intent);

第二个Activity中

 //获取Bundle
 Intent intent = getIntent();
 Bundle bundle = intent.getBundleExtra("bun");
 String str = bundle.getString("data");
 tv.setText(str);

2.4.3 使用Activity销毁时传递数据

第一个Activity中

 Intent intent = new Intent(MainActivity.this,TwoActivity.class);
 //用一种特殊方式开启Activity
 startActivityForResult(intent, 11);
 //设置数据
 
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 String str = data.getStringExtra("data");
 tvOne.setText(str);
}

第二个Activity

 //设置返回的数据
 Intent intent = new Intent();
 intent.putExtra("data", edtOne.getText().toString().trim());
 setResult(3, intent);
 //关闭当前activity
 finish();

2.4.4 SharedPreferences传递数据

SharedPreferences进行传递的数据是利用本地存储进行传输的。

第一个Activity中

 SharedPreferences sp = this.getSharedPreferences("info", 1);
 //获取sp编辑器
 Editor edit = sp.edit();
 edit.putString("data", str);
 edit.commit();
 //创建意图对象
 Intent intent = new Intent(MainActivity.this,TwoActivity.class);
 //激活意图
 startActivity(intent);

第二个Activity中

 SharedPreferences sp = this.getSharedPreferences("info", 1);
 //设置数据
 tv.setText(sp.getString("data", ""));

2.4.5 使用序列化对象Seriazable

工具类

import java.io.Serializable;
class DataBean implements Serializable {
 private String name;
 private String sex;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getSex() {
 return sex;
 }
 public void setSex(String sex) {
 this.sex = sex;
 }
}

第一个Activity

//创建意图
 Intent intent = new Intent(MainActivity.this,TwoActivity.class);
 DataBean bean = new DataBean();
 //通过set方法把数据保存到DataBean对象中
 bean.setName("啦啦");
 bean.setSex("男");
 intent.putExtra("key", bean);
 startActivity(intent);

第二个Activity

Intent intent = getIntent();
 //反序列化数据对象
 Serializable se = intent.getSerializableExtra("key");
 if(se instanceof DataBean){
  //获取到携带数据的DataBean对象db
  DataBean db = (DataBean) se;
  tv.setText(db.getName()+"==="+db.getSex());
 }

2.4.6 使用静态变量传递数据

第一个Activity

Intent intent = new Intent(MainActivity.this,TwoActivity.class);
  TwoActivity.name="牛逼";
  TwoActivity.str="你说";
  startActivity(intent);

第二个Activity

//静态变量
protected static String name;
protected static String str;
tv.setText(str+name);

3. Activity的生命周期

附上一张Activity的生命周期图:

【Android】详解Android Activity
1.创建Activity    
2.Activity的跳转
3. Activity的生命周期
4.Activity的四种启动模式
5.横竖屏切换生命周期
 6.硬件加速

void onCreate()
    Activity已经被创建完毕

void onStart()
    Activity已经显示在屏幕,但没有得到焦点

void onResume()
    Activity得到焦点,可以与用户交互

void onPause()
    Activity失去焦点,无法再与用户交互,但依然可见

void onStop()
    Activity不可见,进入后台

void onDestroy()
    Activity被销毁

void onRestart()
    Activity从不可见变成可见时会执行此方法

使用场景
    Activity创建时需要初始化资源,销毁时需要释放资源;或者播放器应用,在界面进入后台时需要自动暂停

完整生命周期(entire lifetime)
onCreate–>onStart–>onResume–>onPause–>onStop–>onDestory


可视生命周期(visible lifetime)
onRestart->onStart–>onResume–>onPause–>onStop


前台生命周期(foreground lifetime)
onResume–>onPause

4.Activity的四种启动模式

每个应用会有一个Activity任务栈,存放已启动的Activity,Activity的启动模式,修改任务栈的排列情况
  standard

    每次启动一个Activity都会重新创建一个实例,即调用Activity创建时的生命周期方法onCreate,onStart,onResume;

  singleTop 单一顶部模式
          新启动的Activity已经位于任务栈的栈顶,那么此Activity将不会被重建,而是会回调其onNewIntent方法,如果新启动的Activity不是位于栈顶,此时将重新创建新的Activity实例并添加到栈顶.
          应用场景:浏览器的书签
  singleTask 单一任务栈,在当前任务栈里面只能有一个实例存在
    这是一种简单的单例模式,这种模式下只要被启动的Activity位于栈内,那么无论它是否位于栈顶都不会重新创建新的Activity实例,而是直接将其调回到栈顶并回调其onNewIntent方法,如果在其上有其他Activity的时候会将这些Activity进行出栈处理
    应用场景:浏览器的activity
    如果一个activity的创建需要占用大量的系统资源(cpu,内存)一般配置这个activity为singletask的启动模式。webkit内核 c代码
  singleInstance启动模式非常特殊, activity会运行在自己的任务栈里面,并且这个任务栈里面只有一个实例存在
          如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance
          应用场景: 电话拨打界面

可以在Activity标签中,指定启动模式:
android:launchMode="standard"
通过java代码实现:

          Intent intent = new Intent();  
            intent.setClass(this,TestActivity.class);  
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
            startActivity(intent);  

5.横竖屏切换生命周期

默认情况下 ,横竖屏切换, 销毁当前的activity,重新创建一个新的activity。

在一些特殊的应用程序常见下,比如游戏,不希望横竖屏切换activity被销毁重新创建
需求:禁用掉横竖屏切换的生命周期
1. 横、竖屏写死
android:screenOrientation=”landscape”
android:screenOrientation=”portrait”

2.让系统的环境 不再去敏感横竖屏的切换。
     android:configChanges="orientation|screenSize|keyboardHidden"

 6.硬件加速

游戏对硬件的要求比较高,经常需要要求对Activity进行硬件加速,在Activity中可以指定如下的命令来对当前的Activity进行硬件加速:

android:hardwareAccelerated="true"

该配置既可以配置到Activity中,也可以配置到application中。配置到application表示对整个应用加速,配置到activity中表示对某个activity加速。