探索Android,探索发现

Android开发艺术探索读书笔记之AIDL

AIDL是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

目前创新互联建站已为上1000+的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、诸暨网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

AIDL可以实现跨进程的方法调用。定义进程通信接口供服务端和客户端调用。

在AIDL文件中并不是所有数据类型都可以使用。只支持下列数据类型

默认情况下AIDL的调用过程是同步的,所以不能直接进行比较耗时的操作,否则容易导致客户端ANR。如果需要进行异步操作,在服务端不需要另起线程,但是在客户端需要另起线程访问远程方法,再通过Handler通知到UI线程即可!

Android: Activity启动模式 FLAG_ACTIVITY_NEW_TASK 详细探索

最近遇到了一个小问题,在我使用了多种Activity启动模式的时候,重新打开其中的一个Activity会启动另一个我已经停止的Activity,从而调用了一些已经失效的方法导致程序崩溃。

由于项目工程复杂,Activity名称不够直观,我新建了一个ActivityTaskTest 工程来重现遇到的问题。

ActivityA是工程的主活动。因为一些必要的原因, ActivityA的启动模式是SingleInstance的。ActivityA可以启动ActivityB,ActivityB没有设置任何启动模式,即默认的standard启动模式。在ActivityB中,将会启动一个ServiceA。 ServiceA中启动一个了一个ActivityC,由于Activity是在非Acitivity环境下启动的,需要设置 FLAG_ACTIVITY_NEW_TASK标签(这里就是我们讨论的重点,稍候会详细分析)。当ActivityC完成任务后会重新跳转到ActivityA。

最后,见证奇葩的时刻到了,我们点击ActivityA的启动ActivityB的button,ActivityC出现在了我们的眼前,而不是ActivityB!!这一刻我仿佛刘谦附体,但在我发现我身边并没有董卿之后,我深刻地意识到了我是一个工程师,不能搞这些装神弄鬼的事情。ok,Let's find out what‘s going on with our precious app!

关于Activity启动模式和Activity Task的内容推荐一篇非常好的文章: Android中Activity四种启动模式和taskAffinity属性详解 。这篇文章已经讲得非常详细了,这里就不再赘述了,偷个懒哈哈。

如果你已经看了文章,你应该已经知道问题的所在了,对,就是这个该死的taskAffinity。简单的说,就是我们虽然使用了FLAG_ACTIVITY_NEW_TASK标签去启动了ActivityC,但是因为我们忘了给Activity设置taskAffinity这个小婊砸,所以导致ActivityC的taskAffinity值和ActivityB一样都是默认的包名。所以我们启动ActivityC的时候系统将ActivityC压入了ActivityB所在的task。我们可以使用adb shell dumpsys activity activities 指令看下一在我们重新从A中启动B之前,Task的情况:

我们可以看到正如我们所想的,ActivityC和ActivityB在一个Task中,由于ActivityA是singleInstance模式,所以A只能做一辈子单身狗了。那么为什么我们明明启动的是B,怎么会出现C呢?

我们来先看看Google官方文档对于FLAG_ACTIVITY_NEW_TASK是怎么说的:

注意文档中的内容,“如果要启动的 activity 已经运行于某 task 中,则那个 task 将调入前台,最后保存的状态也将恢复”,注意这里是所在task被直接调入前台,也就是说B所在的整个Task将被移入前台。这就解释了为什么我们去启动B而出现的是C了。看起来我们好像大功告成了,但是,等等,总觉得哪里有点不太对劲,我们的ActivityB明明没有设置启动模式啊,你这个是FLAG_ACTIVITY_NEW_TASK标签,我没用啊,我读书多你可别骗我。

仔细想想应该是ActivityA的singleInstance的锅。

我们再来看看Google官方文档对于singleInstance是怎么说的吧:

看到最后一句,终于可以结案了。也就是说,当一个被设置为singleInstance的Activity去启动其他的Activity的时候,其默认是自带FLAG_ACTIVITY_NEW_TASK标签的。

1、FLAG_ACTIVITY_NEW_TASK标签必须配合taskAffinity属性使用,如果不设置taskAffinity属性值,将不会生成新task。

2、当从启动模式为singleInstance的Acitivity中启动新的Acitivity时,新的Activity自带FLAG_ACTIVITY_NEW_TASK标签。

心得:官方文档是个好东西。

Android 仿微博,探索使用ShortcutManager添加应用程序的快捷方式

在Android 7.1(API 25)之后添加的新功能,应用快捷方式。ShortcutManager管理一个应用程序的快捷方式。只要在长按应用图标的情况下,在应用图标上显示的快捷方式,用户可以快速访问任意一个Activity。

现在市场上已经是有很多应用增加了这项功能,例如微博、美团、支付宝、知乎、印象笔记等。

按照惯例,我们先看看效果图:

二、这个Dome主要是通过动态的方式,下面我们来看看动态创建的方式,是通过ShortcutManager实现快捷方式的增加、删除、更新的操作,使用起来很简单。

strings.xml

在进来的页面中,我们通过传值去做一些业务逻辑判断

好了,本篇文章就这样啦,存在总结不到位的地方还望指导,感谢~

最后附上官网地址:

《Android开发艺术探索》值得买吗

值得买。《Android开发艺术探索》深入的讲解View的工作原理,View的事件体系,属性动画,IPC机制,JNI技术,缓存与优化等知识。作者不仅仅没有简单的堆砌文档,而是结合自身工作经验来讲解。由于这些技术属于Android进阶技术,所以不适合新手入门,比较适合进阶中高的开发的工程师。

android深度探索 hal与驱动开发 怎么样

 《Android深度探索(卷1):HAL与驱动开发》注重理论和实践相结合。在介绍了大量的基础知识的同时,为每一个知识点提供了完整的案例,使读者可以通过实际的代码更好地理解Linux驱动和Android底层技术。

探索 Android 中的 Span

在 Android 中,使用 Span 定义文本的样式. 通过 Span 改变几个文字的颜色,让它们可点击,放缩文字的大小甚至是绘制自定义的项目符号点(bullet points,国外人名中名字之间的间隔符号 · ,HTML 中无序列表项的默认符号)。Span 能够改变 TextPaint 属性,在 Canvas 上绘制,甚至是改变文本的布局和影响像行高这样的元素。Span 是可以附加到文本或者从本文分离的标记对象(markup objects);它们可以被应用到部分或整段的文本中。

让我们来看看Span如何使用、提供了哪些开箱即用的功能、怎样简单地创建我们自己的 Span 以及如何使用和测试它们。

Styling text in Android

Creating custom spans

Testing custom spans implementation

Testing spans usage

Android 提供了几种定义文本样式的方法:

单一样式 使用 XML 属性或者 样式和主题 引入了 TextView 的所有内容的样式。这种方式实现简单,通过 XML 即可实现,但是并不能只定义部分内容的样式。举个例子,通过设置 textStyle=”bold” ,所有的文本都会变为黑体;你不能只定义特定的几个字符为黑体。

多重样式 引入了给一段文本添加多种样式的功能。例如,一个单词斜体而另一个粗体。多重样式可以通过使用 HTML 标签、 Span 或者是在 Canvas 上处理自定义的文本绘制。

左图:单一样式文本。设置了 textSize=”32sp” 和 textStyle=”bold” 的 TextView 。右图:多重样式文本。设置了 ForegroundColorSpan, StyleSpan(ITALIC), ScaleXSpan(1.5f), StrikethroughSpan 的文本。

HTML 标签 是解决简单问题的简单办法,例如使文本加粗、斜体,甚至是显示项目符号点。为了展示含有 HTML 标签的文本,使用 Html.fromHtml 方法。在内部实现时,HTML 标签被转换成了 span 。但是请注意, Html 类并不支持完整的 HTML 标签和 CSS 样式,例如将小黑点改为其他的颜色。

当你有文本样式的需求,但是 Android 平台默认不支持时,你还可以手动地在 Canvas 上绘制文本,例如让文字弯曲排布。

Span 允许你实现具有更细粒度自定义的多重样式文本。举个例子,通过 BulletSpan ,你可以定义你的段落文本拥有项目符号点。你可以定制文本和点号之间的间距和点号的颜色。从 Android P 开始,你甚至可以 设置点号的半径 。你也可以创建 span 的自定义实现。在文章中查看 “创建自定义 span” 部分可以找到如何实现。

左图:使用 HTML 标签;中图:使用 BulletSpan,默认圆点大小;右图:在 Android P 上使用 BulletSpan 或者自定义实现。

你可以组合使用单一样式和多重样式。你可以考虑将设置给 TextView 的样式作为一种“基本”样式,而 span 文本样式是应用在基本样式“之上”并且会覆盖基本样式的样式。例如,当给一个 TextView 设置了 textColor=”@color.blue” 属性且给头4个字符应用了 ForegroundColorSpan(Color.PINK) ,则头4个字符会使用 span 设置的粉色,而其他文本使用 TextView 属性设置的颜色。

TextView 组合使用 XML 属性和 span 样式

当使用 span 时,你会和以下类的其中之一打交道: SpannedString , SpannableString 或 SpannableStringBuilder 。 它们之间的区别在于文本或标记对象是可改变的还是不可改变的以及它们使用的内部结构: SpannedString 和 SpannableString 使用线性数组记录已添加的 span,而 SpannableStringBuilder 使用 区间树 。

下面是如何决定使用哪一个的方法:

举个例子,你用到的文本并不会改变,但你想要附加 span 时,你应该使用 SpannableString 。

上面所有的这些类都继承自 Spanned 接口,但拥有可变标记的类( SpannableString 和 SpannableStringBuilder ) 同时也继承自 Spannable 。

Spanned -- 带有不可变标记的不可变文本

Spannable (继承自 Spanned) -- 带有可变标记的不可变文本

通过 Spannable 对象调用 setSpan(Object what, int start, int end, int flags) 方法应用 span。 What 对象是一个标记,应用于从开始到结束的索引之间的文本。falg 标志位标记了 span 是否应该扩展至包含插入文本的开始和结束的点。任何标志位设置以后,只要插入文本的位置位于开始位置和结束位置之间,span 就会自动的扩展。

举个例子,设置 ForegroundColorSpan 可以像下面这样完成:

因为 span 设置时使用了 SPAN_EXCLUSIVE_INCLUSIVE 标志位,在 span 的后面插入文本时,新插入的文本也会自动地继承此 span。

左图:带有 ForegroundColorSpan 的文本;右图:带有 ForegroundColorSpan 和 Spannable.SPAN_EXCLUSIVE_INCLUSIVE 的文本。

如果 span 设置了 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 标志位,在 span 后面插入文本时则不会修改 span 的结束索引。

多个 span 可以被组合且同时附加到同一段文本上。例如,粗体红色的文本可以像这样构建:

带有多种 span 的文本:ForegroundColorSpan(Color.RED) 和 StyleSpan(BOLD)

Android framework 定义了几个接口和抽象类,它们会在测量和渲染时被检查。这些类有允许 span 访问像 TextPaint 或 Canvas 对象的方法。

Android framework 在 android.text.style 包、主要接口的字类和抽象类中提供了20+的 span, 我们可以通过下面几个方式对 span 进行分类:

span 类别:字符对比段落,外形对比大小

第一种类型以修改外形的方式在字符级别起作用:文本或背景颜色、下划线、中横线等等,它会触发文本重新绘制但是并不会重新布局。这些 span 引入了 UpdateAppearance 且继承自 CharacterStyle . CharacterStyle 字类通过提供更新 TextPaint 的访问方法,定义了怎样绘制文本。

影响外形的 span

影响尺寸 的 span 更改了文本的尺寸和布局,因此观察 span 的变化的对象会重新绘制文本以保证布局和渲染的正确。

举个例子,影响文本字体大小的 span 要求重新测量和布局,也要求重新绘制。这种 span 通常继承自 MetricAffectingSpan 类。这个抽象类通过提供对 TextPaint 的访问,允许字类定义 span 如何影响文本测量,而 MetricAffectingSpan 继承自 CharacterSpan ,子类在字符级别影响文本的外形。

影响尺寸的 span

你可能会想要一直重新创建带有文本和标记的 CharSequence 并且调用 TextView.setText(CharSequence) 方法,但是这样做很有可能一直触发已经创建好的布局和额外的对象的重新测量和重新绘制。为了减少性能损耗,将文本设置为 TextView.setText(Spannable, BufferType.SPANNABLE) ,然后当你需要更改 span 的时候,通过将 TextView.getText() 转换为 Spannable 从 TextView 获得 Spannable 对象。我们会在未来的文章中详细讨论 TextView.setText 的实现原理和不同的性能优化方式。

举个例子,考虑通过这样的方式设置和获取 Spannable :

现在,当我们在 spannableText 上设置了 span 之后,我们就不需要再调用 textView.setText 了,因为我们正在直接修改 TextView 持有的 CharSequence 对象的引用。

这是当我们设置了不同的 span 之后会发生什么:

情形1: 影响外观的 span

当我们附加了一个影响外观的 span 之后, TextView.onDraw 方法被调用但 TextView.onLayout 没有。这是文本重绘,但宽和高保持原样。

情形2: 影响尺寸的 span

因为 RelativeSizeSpan 改变了文本的大小,文本的宽和高变化,文本的布局方式(举个例子,在 TextView 的大小没有变化的情况下,一个特定的单词现在可能会换行)。 TextView 需要计算新的大小所以 onMeasure 和 onLayout 均被调用。

左图:ForegroundColorSpan——影响外观的 span;右图:RelativeSizeSpan——影响尺寸的 span

一个 span 对文本产生的影响既可以在字符级别,更新元素,如背景颜色、样式或大小,也可以在段落级别,更改整个文本块的对齐或者边距。根据所需的样式,span 既可以继承自 CharacterStyle ,也可以引入 ParagraphStyle 。 继承自 ParagraphStyle 的 span 必须从第一个字符附加到单个段落的最后一个字符,否则 span 不会被显示。在 Android 中,段落是基于换行符 (\n) 定义的。

在 Android 中,段落是基于换行符 (\n) 定义的。

影响段落的 span

举个例子,像 BackgroundColorSpan 这样的 CharacterStyle ,可以被附加到文本中的任何字符上。这里,我们把它附加到第五到第八个字符上。

ParagraphStyle 的 span,像 QuoteSpan ,只能够被附加到段落的开始,否则行和文本之间的边距就不会出现。例如,“Text is\nspantastic” 在文本的第8个字符包含了一个换行符,所以我们可以给它附加一个 QuoteSpan ,段落从那里开始就会被添加样式。如果我们在0或8之外的任何位置附加 span,text 就不会被添加样式。

左图:BackgroundColorSpan -- 影响字符的 span。右图:QuoteSpan -- 影响段落的 span

在实现你自己的 span 时,你需要确定你的 span 是否会影响字符或段落级别的文本,以及它是否也会影响文本的布局或外观。但是,在从头开始编写自己的实现之前,检查一下是否可以使用 framework 中提供的 span。

太长不看:

假设我们需要实现一个 span,它允许以一定的比例增加文本的大小,比如 RelativeSizeSpan ,并设置文本的颜色,比如 ForegroundColorSpan 。为此,我们可以扩展 RelativeSizeSpan ,并且 RelativeSizeSpan 提供了 updateDrawState 和 updateMeasureState 回调,我们可以复写绘制状态回调并设置 TextPaint 的颜色。

注意:同样的效果可以通过在同一文本上同时应用 RelativeSizeSpan 和 ForegroundColorSpan 实现。

测试 span 意味着检查确实已对 TextPaint 进行了预期的修改,或者是否已经将正确的元素绘制到了 canvas 上。例如,假设一个 span 的自定义实现为段落添加制定大小和颜色的项目符号点,以及左边距和项目符号点之间的间隙。在 android-text sample 查看具体实现。为了测试这个类,实现一个 AndroidJUnit 类,确实检查:

测试 Canvas 的交互可以通过 mock canvas,给 drawLeadingMargin 方法传 mock 过的引用并使用正确的参数验证是否已调用正确的方法来实现。

在 BulletPointSpanTest 查看其余的测试。

Spanned 接口允许给文本设置 span 和从文本获取 span 。通过实现一个 Android JUnit 测试,检查是否在正确的位置添加了正确的 span。在 android-text sample 我们把项目符号点标记标签转换为了项目符号点。这是通过给文本在正确的位置附加 BulletPointSpans 。 下面展示了它是如何被测试的:

查看 MarkdownBuilderTest 获取更多测试示例。

span 是一个非常强大的概念,它深深的嵌入在文本渲染功能中。它们可以访问 TextPaint 和 Canvas 等组件,这些组件允许在 Android 上使用高度可自定义的文本样式。在 Android P 中,我们为 framework span 添加了大量文档,所以,在实现你自己的 span 之前,查看那些能够获取到的内容。

在以后的文章中,我们将向你详细介绍 span 在底层是如何工作的以及怎样高效地使用它们。例如,你需要使用 textView.setText(CharSequence, BufferType) 或者 Spannable.Factory 。 有关原因的详细信息,请保持关注。

本文原作者 Florina Muntenescu ,Android Developer Advocate @Google . 原文地址: . 本文由 TonnyL 翻译,发表在:


当前标题:探索Android,探索发现
网页地址:http://scjbc.cn/article/dsshpgs.html

其他资讯