1.实验目的
(1)熟悉Handler异步通信机制。
(2)了解Butter Knife的用法。
(3)了解Android Material Design风格控件的使用方法。
(4)掌握Web View控件的使用。(5)熟悉相对布局的标签。
2.Handler异步通信机制
Handler实现了Android中的异步通信机制。Android中界面事件由一个线程负责,这个线程被称为UI线程(界面线程)或主线程。Android中只允许UI线程修改Activity组件,所以在实际Android开发中,需要启动子线程通过Handler更改界面属性,如图4.11所示。
图4.11 Handler工作原理
图4.11描述了在创建Handler之前Android先创建了一个Looper对象和一个消息队列MessageQueue。当子线程通过Handler的send Message(Message msg)方法发送消息时,Android会调用入队列方法向MessageQueue中插入这条消息,Looper不断轮询调用MessageQueue的next()方法,如果发现有消息,则调用Message出队列方法读取消息,接着将消息分配给Handler的handle Message(Message msg)方法,UI线程在空闲时将消息更新至界面。
子线程通过Handler给UI线程发送消息主要分为以下4个步骤。
(1)创建一个Handler对象。
(2)从子线程中获取Message对象,通过boolean send Message(Message msg)方法发送消息。
Message对象有多种属性可以选择,其中常用的有以下几种。
•what属性:int类型,主线程用于识别子线程发来的信号量。
•arg1、arg2属性:int类型,如果传递的消息类型为int型,可以赋值给arg1、arg2。
•obj属性:Object类型,如果传递的消息是String或者其他,可以赋值给obj。
(3)在Handler中捕获所需消息,并根据获取的消息更新界面。
(4)通过Handler的post()方法启动子线程。
Handler的用法有很多,表4.4对Handler常用方法进行了总结。
表4.4 Handler常用方法
3.View注入框架Butter Knife
Butter Knife是一个专注于Android系统的View注入框架。Butter Knife具有强大的View绑定和OnClick事件处理功能,可以简化代码和提升开发效率。以前的实验中总有很多find View ById()方法的调用以获取View对象和OnClick点击事件,使用Butter Knife可以略去这些步骤。Butter Knife项目的github地址为https:github.com/JakeWharton/butterknife,其中有最新版本的Butter Knife以及使用说明。Butter Knife的使用步骤如下。
(1)在Project的build.gradle文件的dependencies闭包中添加引用的插件。
(2)在App的build.gradle中添加应用程序模块和依赖。
(3)在Android Studio的settings中安装Android Butter Knife Zelezny插件,安装后重启开发环境生效。
(4)在Activity中生成获取控件和OnClick事件的代码。
4.Material Design
Material Design是由Google公司于2014年推出的全新的设计语言,Google公司表示这种设计语言旨在为手机、平板电脑、台式机和其他平台提供更一致、更广泛的外观和感觉,增强用户的视觉感受,使用户有更好的体验。本实验使用的是Floating ActionButton和Snackbar控件,除此之外常用的还有Drawer Layout、Navigation View、Card View等控件或布局。
使用这些控件时的共同点是必须引入com.android.support.design依赖。当然也有很多开源项目已经将相关的界面封装好,可直接引入相关依赖,按照项目说明使用。
本实验采用了Floating ActionButton控件,该控件的使用与普通控件相似,但是它具有一些特殊的XML属性,主要有以下几种。
(1)android:src:Floating Action Button中显示的图标。
(2)app:background Tint:正常的背景颜色。
(3)app:rippleColor:按下时的背景颜色。
(4)app:elevation:正常的阴影大小。
(5)app:pressed TranslationZ:按下时的阴影大小。
(6)app:layout_anchor:设置Floating ActionButton的锚点,即以哪个控件为参照设置位置。
(7)app:layout_anchor Gravity:Floating ActionButton相对于锚点的位置。
(8)app:fabSize:Floating ActionButton的大小,包括normal和mini(分别对应56 dp和40 dp)。
(9)app:border Width:边框大小,不需要边框则将该值设置为0 dp。
(10)android:clickable:一般设置为true,否则不能触发点击事件。
本实验使用的另一个Material Design控件是Snackbar,其作用和Toast的作用相似。Snackbar与Toast的区别在于:Snackbar可以滑动退出,也可以处理用户交互(点击)事件,但Toast不具备这些功能。Snackbar具有的特性包括以下几种。
(1)Snackbar会在超时后或用户触摸屏幕其他地方后自动消失。
(2)Snackbar可以在屏幕上滑动关闭。
(3)Snackbar出现时不会阻碍用户在屏幕上的输入。
(4)屏幕上同时最多只能显示一个Snackbar。
(5)如果在屏幕上已有一个Snackbar的情况下,需再显示一个Snackbar,则会先将正在显示的Snackbar隐藏,再显示新的Snackbar。
(6)可在Snackbar中添加按钮等控件,处理用户点击事件。
(7)Snackbar使用Coordinator Layout作为父容器时,可以实现右滑退出。
5.WebView控件
Android 5.0系统中内置了一款高性能Web Kit内核浏览器,在SDK中封装为Web View控件。Web View的用法与普通ImageView的用法基本相似,它还提供了大量方法执行浏览器的操作。Web View控件的常用方法如下所示。
(1)void load Url(String url):加载指定URL页面。
(2)void getSettings().setJavaScript Enabled(true):如果访问的页面中有JavaScript,则Web View须设置为支持JavaScript。
(3)void set Web View Client(new Web View Client()):如果页面中存在超链接,且希望点击链接后继续在当前Browser中显示,而不是打开Android系统自带的浏览器去响应该链接,则必须覆盖Web View的Web View Client对象。
(4)int get Height():返回当前Web View容器的高度。
(5)int get Content Height():返回整个HTML页面的高度。
(6)void getSettings().setSupportZoom(true)和void getSettings().setBuiltInZoomControls(true):打开Web View的缩放功能。利用这两个方法可以使页面大小适配当前Web View控件。
最后,要使用Web View打开页面,必须在Android Manifest.xml文件中添加网络访问权限。
6.RelativeLayout
Relative Layout是相对布局,是目前使用较多的布局,RelativeLayout容器内子组件的位置总是相对于其他组件或父容器的位置。Android在设计界面时采用了坐标系设计原理,坐标原点在屏幕的左上角,如图4.12所示,x轴的取值越向右越大,y轴的取值越向下越大。在RelativeLayout中,确定了x轴和y轴的取值就能唯一确定一个控件的位置,如果未指定x轴或y轴的取值,则默认取值为0。
最新版本的Android Studio默认的布局为Constraint Layout,使用RelativeLayout需要按如下代码修改原布局文件。
图4.12 Android坐标系
相对布局中的控件或布局的位置需要通过特殊XML属性标识。例如,Text View android:layout_above="@+id/mybutton"……表示当前Text View控件的底部在ID为mybutton的控件的上方。表4.5所示为Relative Layout常用的属性。
表4.5 RelativeLayout常用的属性
(www.xing528.com)
续表
其中,Baseline是指字母排列的基准线,假设图4.13所示为一个Button控件显示的文字,那么这个按钮的基准线即为倒数第二条线。
图4.13 Baseline(基准线)
7.实验界面与功能
本实验的主要功能是使用Handler更新进度条。点击图4.14(a)所示的界面中的Floating ActionButton,会出现图4.14(b)所示的进度条,并且开始在进度条上方加载网页。页面加载完成后进度条消失,如图4.14(c)所示,并且在Floating ActionButton下方出现Snackbar,如图4.14(d)所示,点击“确定”会弹出一个Toast。
图4.14 Handler实验主要界面
本实验的重点为如何使用Handler更新界面进度条,通过Handler更新界面是Android中广泛使用的方法。
8.实验步骤
步骤1:新建模块App11。
步骤2:修改colors.xml文件,修改color Accent的取值为“#03A9F4”,设定控件的选中效果默认采用该颜色,其他保持默认。
步骤3:将加号图片“add.png”放入mipmap目录下。
步骤4:在模块下的build.gradle文件的dependencies闭包中添加Material Design基础控件所需要的依赖。
步骤5:本实验采用Butter Knife生成控件View绑定和OnClick事件,所以需要修改Project下的builder.gradle文件,添加需要引用的插件。
步骤6:按照如下配置修改模块下的build.gradle文件,增加该模块需要引用的程序包和依赖,依赖包括Butter Knife和使用Material Design控件所需要的Support Design Library。
添加完成后在该文件上方会出现“sync”按钮,单击该按钮Gradle会自动下载相关的库至C:\Users\用户名\.gradle\caches\modules-2\files-2.1目录下供代码使用。
步骤7:安装Butter Knife插件。在联网状态下,选择“File”|“Settings”|“Plugins”|“Marketplace”,在输入框中输入“Butterknife”,在随后出现的界面中单击“Install”进行安装,如图4.15所示,安装完成后需要重新启动Android Studio才能生效。
图4.15 安装Butter Knife插件
步骤8:打开activity_main.xml文件,将该文件的布局按照本实验RelativeLayout部分所述更改为Relative Layout。参考图4.14(b)所示的界面,向界面编辑器中拖入Web View、ProgressBar(Horizontal)进度条,然后对控件做如下设置。
提示:控件属性android:visibility="invisible"和android:visibility="gone"之间的差异在于,当控件的visibility属性为invisible时,界面保留了View控件所占有的空间,而控件属性为gone时,界面不保留View控件所占有的空间。
步骤9:在Main Activity类的代码“setContent View(R.layout.activity_main);”中右击布局文件名称,依次选择“Generate…”|“Generate Butterknife Injections”,在弹出的对话框中,按图4.16所示选中4个复选框,单击“Confirm”即会生成绑定3个控件的代码和Floating ActionButton的OnClick事件,在onCreate()方法中绑定Butter Knife。
图4.16 Butter Knife绑定控件、生成OnClick事件
步骤10:定义一个Handler,用于发送异步消息至进度条,处理消息的代码后面补充。
步骤11:该类使用匿名内部类的方式定义一个线程,在线程中每1秒更新进度条进度i,并且将i赋给Message对象,放入Handler的消息队列,主线程在空闲时会从消息队列中取出该消息,更新至界面。
步骤12:当用户点击界面中的Floating ActionButton时,将进度条设置为可见,并通过Web View加载网页,网页可以和JavaScript交互,Web View可以缩放所访问的页面,如果点击页面中的超链接,仍旧在该控件中打开。最后,通过Handler.post(Runnable r)方法启动线程,并且接收和发送新线程的消息。
提示:进度条默认是不可见的,在步骤8中进度条具有属性android:visibility="invisible"。
步骤13:在updateBar Handler的handle Message(Message msg)方法中通过入参获取update Thread线程中传递来的值。如果进度小于等于100,则更新进度条的进度,并且继续运行子线程获取进度值。如果进度达到100,则设置完进度后将进度条设置为不可见,并将全局变量i置为0,最后在屏幕底部弹出Snackbar。
步骤14:使用Web View打开页面需要在Android Manifest.xml文件中添加网络访问权限。
步骤15:运行并测试App11。
知识拓展:APK签名
APK是Android设备上的安装程序,App开发完成后,一般会以APK的形式进行发布。为了保证APK的完整性、真实性等特点,一般要对APK进行签名。在调试阶段,即制作debug版本的APK时,一般以Android内置的Debug Key对APK进行签名。对外发布的版本(release版本)则需要使用Android Studio自带的APK签名工具对其进行签名。对APK进行签名的步骤如下。
步骤1:在Android Studio工具栏中选择“Generate Signed Bundle/APK…”选项,如图4.17所示,会弹出图4.18所示的“Generate Signed Bundle or APK”窗口。
图4.17 创建APK签名
图4.18 生成APK
步骤2:在“Generate Signed Bundle or APK”窗口中选择“APK”选项,单击“Next”按钮。“Android App Bundle”选项仅限于上传Google Play的应用,国内市场不支持。
步骤3:在图4.19所示的窗口中,如果之前创建过密钥则单击“Choose existing…”按钮选择已创建的密钥,如果没有创建过,则单击“Create new…”按钮创建新的密钥。
图4.19 选择/创建密钥
步骤4:在图4.20所示的窗口中选择密钥库存放路径,设置密钥库密码,输入密钥名称、密钥密码以及证书信息,单击“OK”,返回“Generate Signed Bundle or APK”窗口。
图4.20 创建新密钥
步骤5:在图4.21所示的窗口中选择步骤4中创建的密钥库,单击“Next”。
步骤6:在图4.22所示的窗口中选择“release”,签名方式同时勾选“V1(Jar Signature)”和“V2(Full APK Signature)”。如果打包签名时只勾选V1签名则不产生任何影响,但是在Android 7.0设备上不会使用更安全的验证方式;如果只勾选V2签名,则Android 7.0以下设备会显示未安装,Android 7.0以上设备使用了V2的方式验证。如果同时勾选V1和V2则所有设备都不会出现问题。
图4.21 选择密钥
图4.22 选择版本类型和签名方式
思考
(1)当进度条达到100%时线程是如何终止的?
(2)为什么调用了两次Handler的post()方法?减少一次能否达到相同的效果?
(3)尝试不使用Handler更新界面,直接设置进度条,结果和当前实验结果有什么区别。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。