宁静的世界

致我逝去的青春


  • 首页

  • 标签

  • 分类

  • 归档

Mac vscode快捷键

发表于 2019-12-06 | 分类于 VScode

全局

快捷键 说明
Command + Shift + P / F1 显示命令面板
Command + P 快速打开
Command + Shift + N 打开新窗口
Command + W 关闭窗口

基本

快捷键 说明
Command + X 剪切(未选中文本的情况下,剪切光标所在行)
Command + C 复制(未选中文本的情况下,复制光标所在行)
Option + Up 向上移动行
Option + Down 向下移动行
Option + Shift + Up 向上复制行
Option + Shift + Down 向下复制行
Command + Shift + K 删除行
Command + Enter 下一行插入
Command + Shift + Enter 上一行插入
Command + Shift + \ 跳转到匹配的括号
Command + [ 减少缩进
Command + ] 增加缩进
Home 跳转至行首
End 跳转到行尾
Command + Up 跳转至文件开头
Command + Down 跳转至文件结尾
Ctrl + PgUp 按行向上滚动
Ctrl + PgDown 按行向下滚动
Command + PgUp 按屏向上滚动
Command + PgDown 按屏向下滚动
Command + Shift + [ 折叠代码块
Command + Shift + ] 展开代码块
Command + K Command + [ 折叠全部子代码块
Command + K Command + ] 展开全部子代码块
Command + K Command + 0 折叠全部代码块
Command + K Command + J 展开全部代码块
Command + K Command + C 添加行注释
Command + K Command + U 移除行注释
Command + / 添加、移除行注释
Option + Shift + A 添加、移除块注释
Option + Z 自动换行、取消自动换行

多光标与选择

快捷键 说明
Option + 点击 插入多个光标
Command + Option + Up 向上插入光标
Command + Option + Down 向下插入光标
Command + U 撤销上一个光标操作
Option + Shift + I 在所选行的行尾插入光标
Command + I 选中当前行
Command + Shift + L 选中所有与当前选中内容相同部分
Command + F2 选中所有与当前选中单词相同的单词
Command + Ctrl + Shift + Left 折叠选中
Command + Ctrl + Shift + Right 展开选中
Alt + Shift + 拖动鼠标 选中代码块
Command + Shift + Option + Up 列选择 向上
Command + Shift + Option + Down 列选择 向下
Command + Shift + Option + Left 列选择 向左
Command + Shift + Option + Right 列选择 向右
Command + Shift + Option + PgUp 列选择 向上翻页
Command + Shift + Option + PgDown 列选择 向下翻页

查找替换

快捷键 说明
Command + F 查找
Command + Option + F 替换
Command + G 查找下一个
Command + Shift + G 查找上一个
Option + Enter 选中所有匹配项
Command + D 向下选中相同内容
Command + K Command + D 移除前一个向下选中相同内容

进阶

快捷键 说明
Ctrl + Space 打开建议
Command + Shift + Space 参数提示
Tab Emmet 插件缩写补全
Option + Shift + F 格式化
Command + K Command + F 格式化选中内容
F12 跳转到声明位置
Option + F12 查看具体声明内容
Command + K F12 分屏查看具体声明内容
Command + . 快速修复
Shift + F12 显示引用
F2 重命名符号
Command + Shift + . 替换为上一个值
Command + Shift + , 替换为下一个值
Command + K Command + X 删除行尾多余空格
Command + K M 更改文件语言

导航

快捷键 说明
Command + T 显示所有符号
Ctrl + G 跳转至某行
Command + P 跳转到某个文件
Command + Shift + O 跳转到某个符号
Command + Shift + M 打开问题面板
F8 下一个错误或警告位置
Shift + F8 上一个错误或警告位置
Ctrl + Shift + Tab 编辑器历史记录
Ctrl + - 后退
Ctrl + Shift + - 前进
Ctrl + Shift + M Tab 切换焦点

编辑器管理

快捷键 说明
Command + W 关闭编辑器
Command + K F 关闭文件夹
Command + \ 编辑器分屏
Command + 1 切换到第一分组
Command + 2 切换到第二分组
Command + 3 切换到第三分组
Command + K Command + Left 切换到上一分组
Command + K Command + Right 切换到下一分组
Command + K Command + Shift + Left 左移编辑器
Command + K Command + Shift + Right 右移编辑器
Command + K Left 激活左侧编辑组
Command + K Right 激活右侧编辑组

文件管理

快捷键 说明
Command + N 新建文件
Command + O 打开文件
Command + S 保存文件
Command + Shift + S 另存为
Command + Option + S 全部保存
Command + W 关闭
Command + K Command + W 全部关闭
Command + Shift + T 重新打开被关闭的编辑器
Command + K Enter 保持打开
Ctrl + Tab 打开下一个
Ctrl + Shift + Tab 打开上一个
Command + K P 复制当前文件路径
Command + K R 在资源管理器中查看当前文件
Command + K O 新窗口打开当前文件

显示

快捷键 说明
Command + Ctrl + F 全屏、退出全屏
Command + Option + 1 切换编辑器分屏方式(横、竖)
Command + + 放大
Command + - 缩小
Command + B 显示、隐藏侧边栏
Command + Shift + E 显示资源管理器 或 切换焦点
Command + Shift + F 显示搜索框
Ctrl + Shift + G 显示Git面板
Command + Shift + D 显示调试面板
Command + Shift + X 显示插件面板
Command + Shift + H 全局搜索替换
Command + Shift + J 显示、隐藏高级搜索
Command + Shift + C 打开新终端
Command + Shift + U 显示输出面板
Command + Shift + V Markdown预览窗口
Command + K V 分屏显示 Markdown预览窗口

调试

快捷键 说明
F9 设置 或 取消断点
F5 开始 或 继续
F11 进入
Shift + F11 跳出
F10 跳过
Command + K Command + I 显示悬停信息

集成终端

快捷键 说明
Ctrl + ` 显示终端
Ctrl + Shift + ` 新建终端
Command + Up 向上滚动
Command + Down 向下滚动
PgUp 向上翻页
PgDown 向下翻页
Command + Home 滚动到顶部
Command + End 滚动到底部

算法复杂度分析

发表于 2019-11-28 | 分类于 算法、数据结构

事后统计法

事后统计法是指把需要的统计代码跑一遍,通过统计、监控,就能得到算法执行的时间和占用的内存大小。这种统计方法非常有局限性。

事后统计法局限性

  1. 测试结果非常依赖测试环境
  2. 测试结果受数据规模的影响很大

大O复杂度表示法

所有代码的执行时间 T(n) 与每行代码的执行次数 n 成正比。

T(n) = O(f(n))

  • T(n) 它表示代码执行的时间;
  • n 表示数据规模的大小;
  • f(n) 表示每行代码执行的次数总和。因为这是一个公式,所以用 f(n) 来表示。
  • 公式中的 O,表示代码的执行时间 T(n) 与 f(n) 表达式成正比。

时间复杂度分析

在分析时间复杂度的时候比较实用的方法有下面几个:

  1. 只关注循环执行次数最多的一段代码

  2. 加法法则:总复杂度等于量级最大的那段代码的复杂度

  3. 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

几种常见的时间复杂度

常见的时间复杂度从低阶到高阶分别为:

  1. 常量阶:O(1)
  2. 对数阶:O(logn)
  3. 线性阶:O(n)
  4. 线性对数阶:O(nlogn)
  5. 平方阶:O($n^2$)
  6. 指数阶:O($2^n$)
  7. 阶乘阶:O(n!)

最好、最坏情况时间复杂度

下面看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13

// n表示数组array的长度
int find(int[] array, int n, int x) {
int i = 0;
int pos = -1;
for (; i < n; ++i) {
if (array[i] == x) {
pos = i;
break;
}
}
return pos;
}
  • 最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度,即上面循环只遍历一次就得到结果。
  • 最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度,即上面循环把整个数组都遍历一遍

平均情况时间复杂度

  • 平均情况时间复杂度分析,可以先算出该段代码的加权平均值之后再来分析。

均摊时间复杂度

  • 出现O(1)的次数远大于出现O(n)出现的次数,那么平均平摊时间复杂度就是O(1)

空间复杂度

空间复杂度分析可以参考时间复杂度分析。

Android 6.0运行时权限

发表于 2019-08-05 | 分类于 Android

Android 6.0运行时权限

Android 6.0这个版本引入了一种新的权限模式———Runtime Permissions。用户可以在程序运行时来管理应用程序的权限。在这种模式能够让用户更好的了解和控制权限。

对于以Android 6.0(API级别23)或更高的版本为目标平台的应用,必须在运行时检查和请求权限。下面具体介绍一下如何在运行时来管理权限。

检查权限

当应用需要危险权限的时候,每次执行都必须要查自己是否拥有该权限。因为不能保证应用每次使用该功能的时候都具有权限。以下是检测应用是否具有相机的权限。

1
2
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CAMERA);

如果应用具有该权限,该方法返回PackageManager.PERMISSION_GRANTED,并且应用可以继续操作。如果应用不具有此权限,则返回PERMISSION_DENIED,此时应用必须向用户请求该权限。

请求权限

如果应用没有权限,则需要调用 requestPermissions()方法来请求权限,以下是检测并请求相机的权限代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {

// 如果需要给用户做一些解释,应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
if (ActivityCompat.shouldShowRequestPermissionRationale(context,
Manifest.permission.CAMERA)) {
//do something
} else {

// 请求相机权限
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);

//MY_PERMISSIONS_REQUEST_CAMERA是我们需要定义请求码
}
}

处理请求权限的回调

当应用请求权限时,系统会向用户显示一个权限对话框,用户做出响应的时候,系统会回调onRequestPermissionsResult() 方法,通过 requestPermissions()方法传递的请求码,来作出相应的回应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CAMERA: {
// 如果请求被取消,则grantResults数组的长度为0.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//权限被允许了
} else {
//权限被拒绝了
}
return;
}
}
}

请求多个权限实例

写了一个简单的例子供以后复习使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class SplashActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback{

//定义权限请求码
public static int PERMISSIONS=2;
//定义请求权限数组
public static String[] permissions = new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermission(SplashActivity.this);
} else {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}

/**
* 检测需要申请的权限
* @param permissions
* @return
*/
private List<String> getPermissionResult(String[] permissions){
List<String> tempList = new ArrayList<String>();
for (String permission : permissions){
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED){
tempList.add(permission);
}
}
return tempList;
}

/**
* 请求权限
*/
private void requestPermission(Activity activity){
List<String> permissionList = getPermissionResult(permissions);
if (permissionList.size() != 0){
ActivityCompat.requestPermissions(activity, permissionList.toArray(new String[permissionList.size()]), PERMISSIONS);
} else {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSIONS){
boolean result = true;
for (int grantResult : grantResults){
if (grantResult == PackageManager.PERMISSION_DENIED){
result=false;
break;
}
}
if (!result){
Snackbar.make(SplashActivity.this.findViewById(android.R.id.content),"权限被拒绝!重新进入获取权限", 2000).show();
finish();
} else {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}

Mysql 性能分析工具Explain

发表于 2019-08-04 | 分类于 Mysql

简介

MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化.
EXPLAIN 命令用法十分简单, 在 SELECT 语句前加上 Explain 就可以了, 例如:

1
EXPLAIN SELECT * from user_info WHERE id < 300;

EXPLAIN 输出列

名称 说明
id 执行编号,标识select所属的行。如果在语句中没子查询或关联查询,只有唯一的select,每行都将显示1。否则,内层的select语句一般会顺序编号,对应于其在原始语句中的位置
select_type 显示本行是简单或复杂select。如果查询有任何复杂的子查询,则最外层标记为PRIMARY(DERIVED、UNION、UNION RESUlT)
table 访问引用哪个表(引用某个查询,如“derived3”)
type 数据访问/读取操作类型(ALL、index、range、ref、eq_ref、const/system、NULL)
possible_keys 揭示哪一些索引可能有利于高效的查找
key 显示mysql决定采用哪个索引来优化查询
key_len 显示mysql在索引里使用的字节数
ref 显示了之前的表在key列记录的索引中查找值所用的列或常量
rows 为了找到所需的行而需要读取的行数,估算值,不精确。通过把所有rows列值相乘,可粗略估算整个查询会检查的行数
filtered 表示此查询条件所过滤的数据的百分比
extra 额外的信息

对于EXPLAIN比较重要字段解析

select_type

select_type 表示了查询的类型, 它的常用取值有:

类型 说明
simple 简单查询,不包含子查询和union
primary 包含union或者子查询,最外层的部分标记为primary
subquery 一般子查询中的子查询被标记为subquery,也就是位于select列表中的查询
derived 派生表——该临时表是从子查询派生出来的,位于form中的子查询
union 位于union中第二个及其以后的子查询被标记为union,第一个就被标记为primary如果是union位于from中则标记为derived
union result 用来从匿名临时表里检索结果的select被标记为union result
dependent union 顾名思义,首先需要满足UNION的条件,及UNION中第二个以及后面的SELECT语句,同时该语句依赖外部的查询
subquery 子查询中第一个SELECT语句
dependent subquery 和DEPENDENT UNION相对UNION一样

table

table表示对应行正在访问哪一个表,表名或者别名

  • 关联优化器会为查询选择关联顺序,左侧深度优先
  • 当from中有子查询的时候,表名是derivedN的形式,N指向子查询,也就是explain结果中的下一列
  • 当有union result的时候,表名是union 1,2等的形式,1,2表示参与union的query id

注意:MySQL对待这些表和普通表一样,但是这些“临时表”是没有任何索引的。

type

type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般来说,得保证查询至少达到range级别,最好能达到ref。

类型 说明
All 最坏的情况,全表扫描
index 和全表扫描一样。只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。如在Extra列看到Using index,说明正在使用覆盖索引,只扫描索引的数据,它比按索引次序全表扫描的开销要小很多
range 范围扫描,一个有限制的索引扫描。key 列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可以使用 range
ref 一种索引访问,它返回所有匹配某个单个值的行。此类索引访问只有当使用非唯一性索引或唯一性索引非唯一性前缀时才会发生。这个类型跟eq_ref不同的是,它用在关联操作只使用了索引的最左前缀,或者索引不是UNIQUE和PRIMARY KEY。ref可以用于使用=或<=>操作符的带索引的列。
eq_ref 最多只返回一条符合条件的记录。使用唯一性索引或主键查找时会发生 (高效)
const 当确定最多只会有一行匹配的时候,MySQL优化器会在查询前读取它而且只读取一次,因此非常快。当主键放入where子句时,mysql把这个查询转为一个常量(高效)
system 这是const连接类型的一种特例,表仅有一行满足条件。
Null 意味说mysql能在优化阶段分解查询语句,在执行阶段甚至用不到访问表或索引(高效)

possible_keys

possible_keys显示查询使用了哪些索引,表示该索引可以进行高效地查找,但是列出来的索引对于后续优化过程可能是没有用的

key

key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

key_len

key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好 。

ref

ref列显示使用哪个列或常数与key一起从表中选择行。

rows

rows列显示MySQL认为它执行查询时必须检查的行数。注意这是一个预估值。

Extra

Extra是EXPLAIN输出中另外一个很重要的列,该列显示MySQL在查询过程中的一些详细信息,MySQL查询优化器执行查询的过程中对查询计划的重要补充信息。

类型 说明
Using filesort MySQL有两种方式可以生成有序的结果,通过排序操作或者使用索引,当Extra中出现了Using filesort 说明MySQL使用了后者,但注意虽然叫filesort但并不是说明就是用了文件来进行排序,只要可能排序都是在内存里完成的。大部分情况下利用索引排序更快,所以一般这时也要考虑优化查询了。使用文件完成排序操作,这是可能是order by,group by语句的结果,这可能是一个CPU密集型的过程,可以通过选择合适的索引来改进性能,用索引来为查询结果排序。
Using temporary 用临时表保存中间结果,常用于GROUP BY 和 ORDER BY操作中,一般看到它说明查询需要优化了,就算避免不了临时表的使用也要尽量避免硬盘临时表的使用。
Not exists MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行, 就不再搜索了。
Using index 这是MySQL 5.6出来的新特性,叫做“索引条件推送”。简单说一点就是MySQL原来在索引上是不能执行如like这样的操作的,但是现在可以了,这样减少了不必要的IO操作,但是只能用在二级索引上。
Using where 使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。注意:Extra列出现Using where表示MySQL服务器将存储引擎返回服务层以后再应用WHERE条件过滤。
Using join buffer 使用了连接缓存:Block Nested Loop,连接算法是块嵌套循环连接;Batched Key Access,连接算法是批量索引连接
impossible where where子句的值总是false,不能用来获取任何元组
select tables optimized away 在没有GROUP BY子句的情况下,基于索引优化MIN/MAX操作,或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
distinct 优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

参考资料

https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

Activity的生命周期和启动模式

发表于 2019-08-04 | 分类于 Android

1. Activity的生命周期分析

Activity的生命周期分为两个部分,一个是典型情况下的生命周期,另一个是异常情况下的生命周期。所谓的典型情况下的生命周期是指,是指有用户参与的情况下,Activity所经过的生命周期的改变。而异常情况下的生命周期是指Activity被系统回收,或者当前设备的Configuration发生改变从而导致Activity被销毁重建。

1.1. 典型情况下的生命周期

在正常情况下,Activity会经历的生命周期有:

  • onCreate:表示Activity正在被创建,我们可以在这个方法中做一些初始化的工作。
  • onStart:表示Activity正在被启动,这个时候Activity已经可见了,但是还没有出现在前台,还无法和用户交互。(可以理解为Activity已经显示出来了,但是我们还看不见)
  • onRestart:表示Activity重新启动,此时Activity从不可见状态变为可见状态时,onRestart就会被调用。
  • onResume:表示Activity已经可见了,并且出现在前台。当Activity界面获取焦点的时候(界面按钮可以被点击,文本框可以输入内容)。
  • onPause:表示Activity已经停止,此时Activity界面失去焦点的时候(界面按钮不可以被点击,文本框不可以输入内容,但是界面,用户仍然能看见)。此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容,不能做很耗时的操作。
  • onStop:表示Activity即将停止,此时Activity界面用户不可见时。可以做稍微重量级的回收工作,但是也不能太耗时。
  • onDestroy:表示Activity即将被销毁,可以做一些回收工作和最终的资源释放。

可将Android典型情况下的生命周期分为三种

  • 完整的生命周期

    onCreate–>onStart–>onResume–>onPause–>onStop–>onDestroy
  • 可视生命周期

    onStart–>onResume–>onPause–>onStop
  • 前台生命周期

    onResume–>onPause

下面是google官方给出的Activity生命周期的切换过程:

需要注意的问题

因为前一个Activity执行完成onPause方法以后新Activity的onResume才能执行。所以我们如果在onPause或者onStop中执行耗时操作,尽量在onStop中执行。

1.2 异常情况下的生命周期分析

当系统配置发生变化时,或者系统内存不足时,Activity可能被杀死。

  • 资源相关的系统配置发生改变导致Activity被杀死并重新创建。

    当系统配置发生改变后,Activity会被销毁onPause、onStop、onDestroy都会被调用。
  • 除此以外系统还会调用onSaveInstanceState来保存当前的Activity的状态。这个方法的调用时机是在onStop之前,和onPause没有什么时序关系。该方法正常情况下不会被调用,只有Activity以外终止的时候才会被调用。
  • Activity重新被创建的时候,系统会调用onRestoreInstanceState,我们可以通过该方法取出,onSaveInstanceState方法中所保存的数据。该方法的调用时机发生在onStart之后。
  • 资源内存不足导致低优先级的Activity被杀死

    Activity按照优先级从高到低的可以分为三种:
  • 前台Activity——————正在和用户交互的Activity,优先级最高。
  • 可见但非前台Activity——————比如Activity弹出个对话框。
  • 后台Activity——————已经被暂停的Activity,比如执行了onStop,优先级最低

Tips:
当系统配置改变后,Activity会被重新创建,如果想Activity不被系统重新创建那么我们可以设置Activity的configChanges属性。

android:configChanges="orientation|screenSize"

2. Activity的启动模式

activity的启动模式共有四种。

  • standard:标准模式,也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例。这种模式下,谁启动了这个Activity,那么这个Activity就在启动它那个Activity的堆栈中。

Tips:
ApplicationContext启动standard模式的Activity的时候会报错。因为非Activity的Context并没有任务栈。要解决这个问题的方法,为带启动Activity指定FLAG_ACTIVITY_NEW_TASK标记为。

  • singleTop:栈顶复用模式。如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时他的onNewIntent方法会被回调。如果不是位于栈顶,那么新的Activity仍然会被重新创建。
  • singleTask:栈内复用模式。这是一种单实例模式,这种模式下只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,系统也会回调onNewIntent。
    注意:
  • 任务栈S2和ActivityD两个都不存在,那么系统先创建任务栈S2,然后将D的实例压入到栈S2中。
  • 如果存在S2直接将D的实例压入到栈S2中。
  • singleTask启动模式自带cleartop的功能,例如ABCD,四个Activity,从栈顶到栈底。如果这时候启动DActivity那么任务栈中只剩下D的实例。
  • singleInstance:单实例模式,加强的singleTask模式,除了具有singleTask的所有特性以外,这种模式的Activity只能单独位于一个任务栈中。

    3. Activity的Flags

    主要介绍一下比较常用的Flags

  • FLAG_ACTIVITY_NEW_TASK:这个标记位的作用是为Activity指定“singleTask”启动模式。

  • FLAG_ACTIVITY_SINGLE_TOP:这个标志位的作用是为Activity指定”singleTop”启动模式。
  • FLAG_ACTIVITY_CLEAR_TOP:当这个activity启动的时候,在同一个任务栈中位于它上面的Activity都要出栈。
  • FLAG_ACTIVITY_EXCLUDE_RECENTS:具有这个标记的Activity不会出现在历史的Activity的列表中,当某些情况下我们不希望用户通过历史列表返回到我们的Activity可以使用这个。等同于在XML中指定Activity的属性android:excludeFromRecents="true"

4. IntentFilter的匹配规则

我们知道启动Activity分为两种,显示调用和隐式调用。显示调用需要指定被启动对象的组件信息,包括包名类名,而隐式调用需要明确指定组件信息。隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。下面我们来介绍一下IntentFilter中的各种属性和匹配规则。

  • action的匹配规则:action是一个字符串,action的匹配要求Intent中的action存在并且必须和过滤规则中的其中一个action相同,action区分大小写。
  • category的匹配规则:category是一个字符串,Intent中的每一个category都必须和过滤规则中的category相同。Intent中可以没有category,仍然可以匹配成功。因为系统在调用startActivity或者startActivityForResult的时候会为Intent加上“android.intentcategory.DEFAULT”这个category。
  • data的匹配规则:data的语法
    1
    2
    3
    4
    5
    6
    7
    < data  android:scheme="string"
    android:host="string"
    android:port="string"
    android:path="string"
    android:pathPattern="string"
    android:pathPrefix="string"
    android:mimeType="string"/>

data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg、audio/mpeg4generic和video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI中包含的数据就比较多了。下面是URI的结构:

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

content://com.example.project:200/folder/subfolder/etc

http://www.baidu.com:80/search/info

下面介绍每个数据的含义。

  • Scheme:URI的模式,比如http、file、content等。如果URI中没有指定scheme,那么整个URI的其他参数是无效的。
  • Host:URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI的其他参数是无效的。
  • Port:URI中的端口号,比如80,当URI中的scheme和host参数指定的时候,port参数才有意义。
  • Path、pathPattern和pathPrefix:这三个参数表示路径信息。
  • path:表示完整路径信息
  • pathPattern:表示完整路径信息,但是它里面可以包含通配符“ ”,“ ”表示0个或者多个字符。
  • pathPrefix:表示路径前缀信息。

注意:
如果要为Intent指定完整的data,必须调用setDataAndType方法,不能先调用setData在调用setType,因为两个方法彼此会清除对方的值。

Mac完全卸载JDK

发表于 2018-04-21 | 分类于 Mac

Mac卸载JAVA

mac卸载java只需要删除三个文件就可以了,具体的命令为:

  • 1
    sudo rm -rf /Library/Internet/ Plug-Ins/JavaAppletPlugin.plugin
  • 1
    sudo rm -rf /Library/PreferencePanes/JavaControlPanel.prefPane
  • 1
    sudo rm -rf /Library/Java/JavaVirtualMachines/jdk[version].jdk
12
Henry Ch

Henry Ch

守住自己那颗宁静的心!

16 日志
14 分类
25 标签
© 2022 Henry Ch
由 CH 强力驱动
|
主题 — Henry.Scorpio