Android Activity备忘

第一行代码:Android读书笔记(一)

app/src/main/res目录内容:

.
├── drawable 图片目录
│ └── ic_launcher_background.xml
├── drawable-v24
│ └── ic_launcher_foreground.xml
├── layout 布局文件
│ └── activity_main.xml
├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xxhdpi 应用图标目录
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── values 字符串,样式,颜色配置目录
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
└── values-night
└── themes.xml

  • 在代码中,我们通过R.string.app_name可以获得对某个字符串的引用
  • 在XML中,通过@string/app_name可以获得对某个字符串的引用

基本的语法就是如上的两种方式,其中string部分是可以替换的,如果引用的是图片资源则使用drawable,如果引用的是应用图标,则可以替换成mipmap。如果引用的是布局文件,则可以替换成layout

任何Activity都要继承AppCompatActivity类,并且重写onCreate(bundle)方法,然后在app/src/main/res目录的AndroidManifest.xml文件中注册Activity。对于主Activity,我们需要使用<intent-filter>标签指定其为主Activity。一个示例如下:

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

其中的android:label属性指定了Activity中标题栏的内容,还会成为启动器中应用程序所显示的名称。如果一个应用程序没有指定任何主Activity,则其无法在启动器中看到和打开,只能作为第三方服务供其他应用在内部进行调用。

Activity

显式Intent和隐式Intent

显式Intent(通过schme+host+port+path+mimeType显式打开一个Activity)

binding.button1.setOnClickListener(){
            val intent = Intent(Intent.ACTION_VIEW)
            intent.data= Uri.parse("https://www.google.com.hk")
            startActivity(intent)
        }

隐式Intent(通过schme隐式打开一个Activity)

<activity android:name=".SecondActivity">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="https"/>
            </intent-filter>
        </activity>

其中标签被包含于标签中,用于向intent过滤器添加数据规范。该规范可以是只有数据类型(mimeType 属性),可以是只有 URI,也可以是既有数据类型又有 URI。URI 由其各个部分的单独属性指定:

<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]

⚠️用于指定网址格式的以下属性是可选的,但也相互依赖:

  • 如果没有为 Intent 过滤器指定 scheme,则系统会忽略其他所有 URI 属性。
  • 如果没有为过滤器指定 host,则系统会忽略 port 属性以及所有路径属性。

同一 <intent-filter> 元素中包含的所有 <data> 元素都对同一过滤器起作用。例如,以下过滤器规范:

<intent-filter . . . >
        <data android:scheme="something" android:host="project.example.com" />
        . . .
    </intent-filter>

等同于以下规范:

<intent-filter . . . >
        <data android:scheme="something" />
        <data android:host="project.example.com" />
        . . .
    </intent-filter>

您可以在 <intent-filter> 内放置任意数量的 <data> 元素,为其提供多个数据选项。它的属性都没有默认值。而显然,intent过滤器是通过匹配intent对象的规则来工作的。

属性:

android:scheme

URI 的模式部分。这是指定 URI 时最基本的属性;必须至少为过滤器设置一个 scheme 属性,否则其他 URI 属性都没有意义。

指定的模式应不带尾随冒号(例如,应指定 http,而不是 http:)。

如果为过滤器设置了数据类型(mimeType 属性),但未设置模式,则采用 content:file: 架构。

注意:Android 框架中的架构匹配区分大小写,这一点与 RFC 不同。因此,您应始终使用小写字母指定架构。

android:host

URI 授权方的主机部分。除非也为过滤器指定了 scheme 属性,否则此属性没有意义。要匹配多个子网域,请使用星号 (*) 匹配主机中的零个或多个字符。例如,主机 *.google.com 匹配 www.google.com.google.comdeveloper.google.com

星号必须是主机属性的第一个字符。例如,主机 google.co.* 无效,因为星号通配符不是第一个字符。

注意:Android 框架中的主机名匹配区分大小写,这一点与正式的 RFC 不同。因此,您应始终使用小写字母指定主机名。

android:port

URI 授权方的端口部分。仅当同时为过滤器指定了 schemehost 属性时,此属性才有意义。

android:path

android:pathPrefix

android:pathPattern

URI 的路径部分,必须以 / 开头。path 属性指定与 Intent 对象中的完整路径匹配的完整路径。pathPrefix 属性指定只与 Intent 对象中的路径的初始部分匹配的部分路径。pathPattern 属性指定与 Intent 对象中的完整路径匹配的完整路径,但它可以包含以下通配符:

  • 星号(“*”)匹配出现零次到多次的紧邻前面的字符的一个序列。
  • 句点后跟星号(“.*”)匹配零个到多个字符的任意序列。

由于在从 XML 读取字符串时(在将其解析为模式之前)将“\”用作转义字符,因此您需要进行双重转义。例如,字面量“*”将编写为“\\*”,字面量“”将编写为“\\\\”。这基本上与采用 Java 代码构造字符串时需要编写的内容一样。详细类型可以查PatternMatcher类中的PATTERN_LITERALPATTERN_PREFIXPATTERN_SIMPLE_GLOB三个常量的说明。

仅当同时为过滤器指定了 schemehost 属性时,这些属性才有意义。

android:mimeType

MIME 媒体类型,如 image/jpegaudio/mpeg4-generic。子类型可以是星号通配符 (*),以指示任何子类型都匹配。

Intent 过滤器经常会声明仅包含 android:mimeType 属性的 <data>

注意:Android 框架中的 MIME 类型匹配区分大小写,这一点与正式的 RFC MIME 类型不同。因此,您应始终使用小写字母指定 MIME 类型。

在Activity之间传递数据

向下一个Activity传递数据

我们可以直接调用Intent类的putExtra方法来向Intent对象中传入数据。例如:

val someData="Hello, second Activity"
val intent = Intent(FirstActivity.this, SecondActivity::class.java)
intent.putExtra("some_data", someData)
startActivity(intent)

然后在下一个Activity中拿到对应的数据,例如:

val data:String=intent.getStringData("some_data")

很容易想到,Intent对象肯定还有些重载的方法,比如:getIntExtra(..), getBooleanExtra(..)等。

为了某个数据启动Activity

有时候,我们启动某个Activity只是单纯的为了获得数据,这个时候,我们会调用startActivityForResult(..)

首先,我们会在视图绑定中启动一个Activity:

binding.button1.setOnClickListener{
    intent = Intent(this, SecondActivity::class.java)
    // 第一个参数是Intent,第二个参数是一个RequestCode,响应时用来区分是哪个活动
    startActivityForResult(intent, 1)
}

然后,我们在某个Activity中对数据进行填充:

binding.button2.setOnClickListener{
    intent = Intent()
    intent.putExtra("data_return", "Hello, first Activity")
    setResult(RESULT_OK, intent)
    finish()
}

当我们启动第二个Activity并点击了button2之后,便会回调第一个Activity中的onActivityResult(..)函数,这个时候,我们响应就好:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when(requestCode){
            1 -> {
                if(resultCode == RESULT_OK){
                    returnedData=data.getStringExtra("data_return")
                    Log.d("FirstActivity", returnedData)
                }
            }
        }
    }

Activity生命周期

lifecycle

Activity的七个回调方法:

  • onCreate():会在Activity第一次被创建的时候调用。在此方法中可以完成Activity的初始化,比如加载布局,绑定事件等
  • onStart():这个方法在Activity由不可见变成可见的时候被调用
  • onResume():这个方法在Activity准备好和用户进行交互的时候被调用
  • onPause():这个方法在系统准备去启动或者恢复另一个Activity的时候被调用。可以在这个方法中将一些耗CPU的资源释放掉,以及保存一些关键数据,不过这就要求这个过程一定要快。
  • onStop():在App完全不可见的时候被调用。和onPause方法的不同之处在于,如果启动的新Activity是一个对话框式的Activity,那么onPause被执行而onStop方法不会被执行。
  • onDestroy():这个方法在Activity被销毁之前调用,之后的Activity将变为销毁状态。
  • onRestart():这个方法在Activity由停止状态变为运行状态之前调用,也就是Activity被重新启动了。

Activity的启动模式

  • "standard"(默认模式)

    默认值。系统在启动该 Activity 的任务中创建 Activity 的新实例,并将 intent 传送给该实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例。

  • "singleTop"

    如果当前任务的顶部已存在 Activity 的实例,则系统会通过调用其 onNewIntent() 方法来将 intent 转送给该实例,而不是创建 Activity 的新实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例(但前提是返回堆栈顶部的 Activity 不是该 Activity 的现有实例)。

    例如,假设任务的返回堆栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈为 A-B-C-D;D 位于顶部)。收到以 D 类型 Activity 为目标的 intent。如果 D 采用默认的 "standard" 启动模式,则会启动该类的新实例,并且堆栈将变为 A-B-C-D-D。但是,如果 D 的启动模式为 "singleTop",则 D 的现有实例会通过 onNewIntent() 接收 intent,因为它位于堆栈顶部,堆栈仍为 A-B-C-D。但是,如果收到以 B 类型 Activity 为目标的 intent,则会在堆栈中添加 B 的新实例,即使其启动模式为 "singleTop" 也是如此。

  • "singleTask"

    系统会创建新任务,并实例化新任务的根 Activity。但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其 onNewIntent() 方法将 intent 转送到该现有实例,而不是创建新实例。Activity 一次只能有一个实例存在。

  • "singleInstance"

    "singleTask" 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的Task中打开。

我们在AndroidManifest.xml文件的<Activity>标签中完成这些指定:

<activity
            android:name=".SecondActivity"
          <!-- 指定以singleTop模式启动SecondActivity-->
            android:launchMode="singleTop">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="https"/>
            </intent-filter>
        </activity>
posted @ 2021-01-13 16:00  hwa  阅读(53)  评论(0编辑  收藏  举报