文章目录
前言
经过前面的分析,已经基本将扫码流程以及页面显示部分的逻辑理清楚了,在扫码流程上,我们最后分析到了 CaptureActivity 的 handleDecode 方法上,停留在了对扫码结果处理的这一步。因此本篇博客将重点对扫码结果处理相关代码进行分析。
一、result 包代码分析
在 CaptureActivity 的 handleDecode 方法中,有:
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
lastResult = rawResult;
ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
可知其在一开始就创建了一个 ResultHandler 来对结果进行处理,下面就先以 ResultHandler 所在的 result 包中的代码进行分析。
整个结果处理部分实际上采用了简单工厂设计模式,梳理 uml 类图如下:
其中的角色结构为:
- ResultHandlerFactory:工厂类角色,在客户端的直接调用下创建产品对象,由具体类实现
- ResultHandler:抽象产品角色,是工厂方法模式所创建的对象的父类,由抽象类实现
- xxResultHandler:具体产品角色,工厂方法模式所创建的任何对象都是这个角色的实例,由具体类实现
ResultHandlerFactory
下面先看一下工厂类 ResultHandlerFactory
:
其中最重要的方法就是创建产品对象的方法 makeResultHandler
public static ResultHandler makeResultHandler(CaptureActivity activity, Result rawResult) {
ParsedResult result = parseResult(rawResult);
switch (result.getType()) {
case ADDRESSBOOK:
return new AddressBookResultHandler(activity, result);
case EMAIL_ADDRESS:
return new EmailAddressResultHandler(activity, result);
......
可知其是通过 rawResult ,获取在解码算法中就解析出的类型信息,根据不同结果类型,创建不同的 ResultHandler 对象
ResultHandler
在抽象产品 ResultHandler 类中,方法繁多,这里我们只看一下那些公用到的方法作用
方法 | 作用 |
---|---|
getButtonCount() | 标识继承类有多少按钮 |
getButtonText(int) | 获取每个按钮上的文字 |
handleButtonPress(int) | 处理按下每个按钮后的逻辑 |
areContentsSecure() | 某些条形码内容被认为是安全的,不应保存到历史记录中,而应复制到剪贴板,或以其他方式保留 |
getDisplayContents() | 设置当前条码要展示的文字内容 |
可以知道,在 ResultHandler 中,设置了具体产品类将要重写的一些方法,主要是相关显示文字内容和处理按钮逻辑
xxResultHandler
具体的结果处理类共有11个,这里列举一下相应的含义,就不进行展开分析了
类名 | 含义 |
---|---|
AddressBookResultHandler | 处理通讯录结果 |
CalendarResultHandler | 处理以二维码编码的日历结果 |
EmailAddressResultHandler | 处理邮箱地址结果 |
GeoResultHandler | 处理地理坐标结果 |
ISBNResultHandler | 处理图书ISBN码结果 |
ProductResultHandler | 处理非图书的通用产品 |
SMSResultHandler | 处理短信息地址,提供撰写新短信息或彩信的选择 |
TelResultHandler | 提供电话号码的相关操作 |
TextResultHandler | 处理扫码后为文字的相关结果 |
URIResultHandler | 处理对URL的相关结果 |
WifiResultHandler | 处理Wifi接入信息 |
二、结果后续处理
在图像解码处理那篇博客中,我们已经分析了在 CaptureActivity 的 handleDecode() 方法中,根据扫码类型(IntentSource)调用了不同的方法对结果进行处理,下面我们对 handleDecodeExternally() 和 handleDecodeInternally() 方法进行详细分析
handleDecodeInternally
这个方法是当得到扫码结果后,就直接在程序内部对结果进行处理,其主要做了以下几件事:
- 将扫码结果复制到剪贴板
- 进行分享设置,判断如果设置了自动打开扫描网页,则直接打开web页面
- 去除之前设置的 statusView、viewfinderView 和 resultView
- 在页面上显示扫码结果信息,并通过 ResultHandler 获取所有处理该类型条码结果的按钮,为其设置上监听
上图就是通过 handleDecodeInternally 方法得到的页面,其基本包含以下几个部分:
- 条码的位图,ImageView barcodeImageView
- 文字显示条码格式,通过 rawResult.getBarcodeFormet() 获得,设置到 TextView 上
- 文字显示条码类型,通过 rawResult.getType() 获得,设置到 TextView 上
- 文字显示当前时间,通过 rawResult.getTimestamp() 获得,设置到 TextView 上
- 文字显示元数据,通过 rawResult.getResultMetadata() 获得,设置到 TextView 上
- 条码结果文字内容,通过 resultHandler.getDisplayContents() 获得,设置到 TextView 上
- 处理按钮,通过 resultHandler.getButtonCount() 获得,设置到 TextView 上
handleDecodeExternally
这个方法的主要作用就是简要显示了条形码的内容,然后发送消息,在程序外部处理扫码结果。
这里对程序外部可以理解为:因为 Zxing 安卓端既可以作为一个完整的 Android 程序运行,也可以集成到其他程序内部,所以当获得扫码结果后,可以不直接在 Zxing 安卓端这部分进行结果处理,将扫码结果封装为一个 message ,发送消息到调用 Zxing 扫码功能的应用。
总结
在本次代码分析中,Zxing 项目对 ResultHanlder 的处理部分运用了简单工厂设计模式。简单工厂模式在上学期面向对象课程中有所涉及,而这部分代码是将设计模式具体应用到大型工程上的一个很好的例子,也带给了我编程上的很大启发。