Android四大组件:ActivityServiceBroadcast ReceiverContent Provider

  Activity是Context的子类,同时实现了Window.CallbackKeyEvent.Callback接口,可以处理用户与窗体交互的事件。

创建Activity

  1. 定义一个XxxActivity类继承Activity,并重写onCreate()

  2. 在onCreate()中通过setContentView()加载该Activity的布局文件

  3. 在清单文件中配置activity标签,注册这个Activity

    • activity标签下如果带有下面这部分代码,则会在系统中多创建一个快捷图标

      <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:icon="@drawable/ic_launcher"
      android:label="@string/app_name"

Activity的跳转

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

  明确指定要启动或者触发的目标组件(可以是Activity,Service,BroadcastReceiver)的类名或包名的Intent,称为显式Intent。通过显式Intent实现Activity的跳转称为显式跳转

  隐式Intent没有明确指定要启动或者触发的目标组件的类名和包名,而只是指定了一系列更为抽象的Intent Filter的属性(包括action,category,data等)值,然后交由系统去分析这个Intent,并帮我们找出预启动或触发的目标组件。通过隐式Intent实现Activity的跳转称为隐式跳转

显式跳转

  跳转至同一应用中的Activity

Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);// 指定当前的上下文和目标Activity的字节码
startActivity(intent);

  跳转至不同应用中的Activity

Intent intent = new Intent();
// 指定目标Activity所在的应用的包名和目标Activity的包名加类名,这里启动系统自带的拨号器应用(针对Android 4.3)
intent.setClassName("com.android.dialer", "com.android.dialer.DialtactsActivity");
startActivity(intent);

隐式跳转

  隐式意图跳转至打电话Activity

Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
  • 要让一个Activity可以被隐式启动,需要在该应用清单文件下的activity标签下配置intent-filter子标签

  • 系统会在所有应用的清单文件中寻找与我们创建的隐式Intent匹配的intent-filter,找到则启动,找不到则抛异常

  • 匹配就是intent-filter中定义了什么属性,我们创建的intent中也必须设置什么属性,并且对应的属性值也一样

  • 在清单文件的activity标签下,配置intent-filter子标签,其中再配置dataactioncategory子标签。其中data标签下可以配置scheme、host、port、path等子标签,它们构成一个android.net.Uri对象  scheme://host:port/path ,也叫URL Scheme,其应用场景大体分为以下几种:

    • 服务器下发跳转路径,app端根据服务器下发跳转路径跳转相应的页面
    • H5页面点击锚点,根据锚点具体跳转路径app端跳转到相应的页面
    • app端收到服务器下发的Push通知栏消息,根据消息的点击跳转路径跳转相关页面
    • app端根据URL跳转到另外一个app的指定页面

应用场景

  • 启动同一应用中的Activity,用显式Intent。显式启动效率明显高于隐式,因为显示直接指定了目标Activity,隐式需要遍历所有应用的清单文件寻找匹配的Intent Filter

  • 启动不同应用中的Activity,用隐式Intent。当使用隐式Intent跳转到其他应用中的Activity时,如果系统找到了多个intent-filter与我们创建的Intent匹配,就会弹出对话框,列举所有匹配的Activity,让用户选择。比如我们的手机里如果安装了多款浏览器App,当我们点击一个URL时,会弹出一个对话框让我们选择使用哪个浏览器来打开这个网页,这就是因为跳转到浏览器Activity用的是隐式Intent;有些应用的Activity启动时需要接收数据,比如打电话Activity需要接收电话号码,也只能用隐式Intent

Activity跳转时的数据传递

  • Activity跳转时,可以把数据封装在Intent中

    Intent intent = new Intent(this, SecondActivity.class);
    intent.putExtra("name", name); // 字符串类型
    intent.putExtra("age", age); // 整型
    startActivity(intent);
  • 在跳转到的目标Activity中取出数据

    Intent intent = getIntent();    // 获取启动该Activity的Intent
    String name = intent.getStringExtra("name");
    int age = intent.getIntExtra("age");
  • Intent中可以封装的数据类型:八大基本数据类型及其数组、String及其数组、实现了序列化接口Serializable和Parcelable的对象、Parcelable数组、Bundle对象(数据可以先封装至Bundle,再把Bundle封装至Intent)。

Activity的生命周期

  • onCreate():创建Activity时被回调

  • onStart():在屏幕上可见,但是还没有获得焦点,用户还不能与这个Activity进行交互(点击、滑动等)

  • onResume():可见并且获得焦点,用户已经可以和这个Activity进行交互(点击、滑动等)

  • onPause():可见,但是失去焦点。

  • onStop():完全不可见

  • onDestroy():销毁时调用

  • onRestart():Activity从不可见变为可见时调用

  • 按Home键,系统依次回调onPause()onStop(),Activity进入停止状态,进程还在(后台进程);若再次进入该Activity,系统会依次回调onRestart()onStart()onResume(),Activity重新进入运行状态

  • 按Back键,系统依次回调onPause()onStop()onDestroy(),Activity被销毁,进程还在(空进程);若再次进入该Activity,系统会依次回调onCreate()onStart()onResume(),Activity重新进入运行状态

    • 按返回键,Android系统会回调onBackPressed()方法,该方法调用了finish(),所以Activity会被销毁
  • 当另一个优先级更高的进程需要内存而手机内存不足时,Android系统才会杀死之前启动的进程,按照进程优先级和LRU算法(优先级相同时)决定杀死哪个进程。

  • 用户也可以到应用管理界面手动杀死某个进程。

Activity的四种启动模式

  Task是我们在执行某种工作时所交互的activity的集合,这些activity集合按照打开的顺序被放置在同一个栈中,这个栈叫作Back Stack,Activity的启动模式决定了Back Stack的操作规则,对于启动同一应用中的Activity(启动其他应用中的Activity,四种启动模式的表现形式略微复杂,后续探讨),四种启动模式的表现如下:

  • standard:默认模式,每次发送一个Intent启动standard模式的Activity时,Android总会为目标Activity创建一个新的实例,并将该Activity实例添加到启动它的Activity所在的Task栈的栈顶

  • singleTop:Task栈顶单例模式,与标准模式仅有一点不同:当启动的目标Activity已经位于当前Activity所在Task栈的栈顶时,Intent不会再创建一个目标Activity实例(复用已有的Activity实例,不会触发onCreate()),而是通过onNewIntent()被发送到现有的Activity

    • 应用:浏览器书签历史记录界面CombinedBookmarkHistoryActivity
    • 应用:短信会话记录界面ConversationList
  • singleTask:采用这种启动模式的Activity在整个Android系统内存中只能有一个实例。对于启动同一个应用中的Activity,如果系统内不存在将要启动的目标Activity,系统将会创建目标Activity的实例,并将它压入当前Task栈顶;如果已经存在该Activity的实例,系统会将该Activity所在Task移至前台(多半是已经在前台),再退栈至该Activity,同时也会通过onNewIntent()将Intent发送到该Activity。对于启动不同应用中的Activity,如果系统内不存在将要启动的目标Activity,系统会创建一个新的Task,再创建出目标Activity的实例入栈;如果已经存在该Activity的实例,表现同启动同一应用中的Activity一致

    • 应用:浏览器浏览界面BrowserActivity
  • singleInstance:采用这种启动模式的Activity在整个Android系统内存中也只能有一个实例,且总是独占一个Task,任何被此Activity启动的Activity都会被放到其它的task中。如果目标Activity不存在,系统会先创建一个新的Task,再创建目标Activity的实例压入栈顶;如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中、位于哪个Task中,系统都会把该Activity所在的Task转到前台,从而使该Activity显示出来

    • 应用:来电界面InCallScreen

Activity的横竖屏切换

  • 默认情况横竖屏切换会使Activity销毁重建,触发生命周期方法重新执行

  • 在一些特殊的应用程序中,比如游戏,不希望横竖屏切换导致Activity被销毁重建,因为如果不保存会丢失游戏数据

    • 在清单文件中用以下代码让横竖屏切换时不重建Activity

      android:configChanges="orientation|screenSize|keyboardHidden"
    • 在清单文件中可用以下代码写死Activity的屏幕方向

      android:screenOrientation="portrait"     <!-- 竖屏 -->
      android:screenOrientation="landscape" <!-- 横屏 -->
    • 在java文件中可用以下代码写死Activity的屏幕方向(会覆盖清单文件中设置的屏幕方向,因为后执行)

      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  // 竖屏
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // 横屏

Activity销毁时返回数据

步骤

  • 指定请求码requestCode启动新的Activity

    Intent intent = new Intent(this, SecondActivity.class);
    startActivityForResult(intent, requestCode);// 只有用这种方式启动的Activity在销毁时才会回调原Activity的onActivityResult()方法
  • 在新的Activity中设置要返回的数据

    Intent intent = new Intent();  // 该意图仅用来携带数据
    intent.putExtra("tel", tel);
    setResult(resultCode, intent); // 指定一个结果码resultCode,并把数据会返回给原Activity
    finish();    // 销毁当前的Activity
  • 在原Activity里面实现方法

    // 通过intent获取返回的数据
    onActivityResult(int requestCode, int resultCode, Intent intent) { }
  • 通过判断请求码和结果码确定返回的Intent的作用

    • 先通过请求码requestCode判断返回的Intent来自哪一个Activity

    • 再通过该Activity返回的结果码resultCode来判断Intent所携带的是该Activity返回的哪一个数据

Android应用开发-Activity的更多相关文章

  1. Android应用开发-Activity(重制版)

    Android四大组件:Activity,Service,Broadcast Receiver,Content Provider Activity是Context的子类,同时实现了Window.Cal ...

  2. Android开发--Activity生命周期回顾理解

    Activity和Servlet一样,都用了回调机制.我们通过类比servlet来学习Activity.当一个servlet开发出来之后,该servlet运行于Web服务器中.服务器何时创建servl ...

  3. Android开发 ---Activity的7种运行状态

     Android开发 ---Activity的7种运行状态 创建 --> 启动 --> 运行 -->  暂停 --> 停止 --> 销毁 重启 操作图解: 1.MainA ...

  4. Android开发——Activity生命周期

    Android开发--Activity生命周期 Activity作为四大组件之首,也是使用最频繁的一种组件.本文将主要讲解Activity生命周期,包括正常情况下的Activity生命周期和异常情况下 ...

  5. Android N开发 你需要知道的一切

    title: Android N开发 你需要知道的一切 tags: Android N,Android7.0,Android --- 转载请注明出处:http://www.cnblogs.com/yi ...

  6. Android开发之Activity的创建跳转及传值

    在Android系统的江湖中有四大组件:活动(Activity), 服务(Service), 广播接收器(Broadcast Reciver)和内容提供者(Content Provider).今天所介 ...

  7. 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING

    <Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th  2014 Email:skyseraph00@163.com 更多精彩请直接 ...

  8. Android安全开发之浅谈密钥硬编码

    Android安全开发之浅谈密钥硬编码 作者:伊樵.呆狐@阿里聚安全 1 简介 在阿里聚安全的漏洞扫描器中和人工APP安全审计中,经常发现有开发者将密钥硬编码在Java代码.文件中,这样做会引起很大风 ...

  9. Android NDK开发Hello Word!

    在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...

随机推荐

  1. Android避免OOM(内存优化)

    Android内存优化是性能优化很重要的一部分,而如何避免OOM又是内存优化的核心. Android内存管理机制 android官网有一篇文章 Android是如何管理应用的进程与内存分配 Andro ...

  2. 阿里云服务器搭建FTP

    操作系统:Windows Server 2008 R2企业版. 首先,创建一个用户组:ftpUsers,创建一个用户:ftpAdmin.并将ftpAdmin隶属于ftpUsers组 其次,需要安装ft ...

  3. sysbench安装、对Mysql压力测试、结果解读及mysql数据库跟踪优化

    sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试. sysbench支持以下几种测试模式: 1.CPU运算性能 2.磁盘IO性能 3.调度程序性 ...

  4. RestTemplate的使用

    1.postForObject :传入一个业务对象,返回是一个String 调用方: BaseUser baseUser=new BaseUser(); baseUser.setUserid(user ...

  5. TCP template 代码

    服务端 from socket import * server= socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server. ...

  6. PYTHON-模块time&datetime+ 目录规范

    1.目录规范 ***** (1)文件夹的规范写法 bin 可执行文件 conf 配置文件 core 主要业务逻辑 db 数据文件 lib 库 (公共代码 第三方模块) log 日志文件 readme ...

  7. Laravel 禁用指定 URL POST 请求的 csrf 检查

    由于在 chrome 插件中使用了跨域请求,所以需要禁用掉 laravel 默认的 post csrf 检查. 配置方法: 在 app/Http/Middleware/VerifyCsrfToken. ...

  8. 如何将Oracle 当前日期加一天、一分钟

    在Oralce中我发现有add_months函数,加天数N可以用如下方法实现,select sysdate+N from dual sysdate+1 加一天sysdate+1/24 加1小时sysd ...

  9. C/S权限系统得到拼音和五笔的自定义函数(二)

    得到五笔: CREATE FUNCTION [dbo].[fun_getWB](@Str VARCHAR(2000)) RETURNS VARCHAR(2000) AS BEGIN DECLARE @ ...

  10. 【C++】三大概念要分清--重载,隐藏(重定义,覆盖(重写)

    { c++三大概念要分清--重载,隐藏(重定义),覆盖(重写)} 重载 •  概念:在同一个作用域内:函数名相同,参数列表不同(参数个数不同,或者参数类型不同,或者参数个数和参数类型都不同),返回值类 ...