【文档说明】Android移动开发基础教程第8章--高级编程课件.pptx,共(68)页,2.970 MB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-2159.html
以下为本文档部分文字说明:
刘刚主编高伟南副主编◼前面几章我们介绍了Android开发的一些基础知识,本章我们将会在此基础上做一些拓展,如网络编程。对于一个Android设备来说,网络请求是很常见的操作,所以掌握一些网络编程的知识是必要的。另外,在UI方面,Andro
id系统提供了一些动画的API,可以提高用户体验。在与用户的交互中,如果一个操作比较耗时,可能会造成用户长时间等待的现象,甚至会因为ANR(ApplicationNotResponding)造成应用异常退出。本章我们会介绍如何使用线程做耗时
的操作,另外还会介绍Fragment和RecycleView组件。8.1网络编程网络编程是指多个设备之间通过网络进行数据交换,网络通信基于“请求-响应模型”,即一台设备发送通信请求,另一台设备进行反馈。发送请求端称为客户端,响应请求端称为服务端。例如常见的QQ程
序,用户打开QQ客户端程序之后,输入账号和密码,再单击“登录”,即向腾讯服务端发送登录请求,服务端把请求结果反馈到客户端。Android是基于Java进行开发的,所以JDK中关于网络编程的API在Android中均可使用。8.1.1TCP、UDP协议基础两台设备之间进
行通信,一定要有通信协议,即客户端以一定的格式将数据发送出去,服务端接收到数据之后,可以根据同样的协议将数据的内容解析出来。在现有的网络中,通信方式有两种:TCP和UDP。TCP是传输控制协议,提供的是面向
连接、可靠的字节流服务,通信双方必须先建立一个TCP连接,然后才能传输数据。而且TCP协议还提供了超时重发、数据校验、拥塞控制等功能,保证了数据的可靠传输。UDP是用户数据报协议,只是简单地把数据报发送
出去,但是并不能保证数据能到达目的地,不提供可靠性。所以TCP应用于需要安全可靠传输数据的场景,但是开销比较大。UDP应用于对数据可靠性要求不是太高的传输,其优点是开销小,另外UDP没有数据校验、拥塞控制等操作,故而传输比较快。对于上层
应用来说,无论是TCP还是UDP,通信都包括客户端和服务端,处理流程也具有一般性,具体如表8.1所示。表8.1客户端和服务端的处理流程8.1.2Socket通信对于TCP和UDP的通信,Java均有对应的
API。现在我们以TCP为例,通过一个实例说明网络通信的方式。对于TCP通信,Java中使用Socket类做客户端开发,使用ServerSocket做服务端开发。8.1.3下载网络资源在Android开发中,经常需要请求网络资源,例如播放在线音乐,
或者加载显示一张网络图片。Java提供了HttpURLConnection和HttpsURLConnection,两者都可以基于URL实现简单的请求响应功能,区别在于是访问http链接还是访问https链接。本例通过HttpURLConn
ection获取网络图片。案例分析代码中首先根据网络图片的链接地址创建了一个URL对象,然后调用openConnection()方法开启一个连接,接着设置相关参数,如超时时间等。然后调用getInputStream()方法获取输
入流,后续就是输入/输出流的基本处理,可以调用BitmapFactory的decodeStream()方法将输入流解析成Bitmap图片。8.2图形图像和动画对于一个应用来说,图片是一种很丰富的表达形式。Android中也为图片的处理提供了大量的API,不仅包括图片的显示、绘制,还
包括一些简单的动画效果。本节我们将介绍这些API的使用方法。8.2.1Bitmap和BitmapFactoryAndroid中提供了Bitmap类用于图片处理,一个Bitmap对象代表一张位图,存储了图片的宽高
、颜色、像素点等信息,Bitmap类提供了大量的方法,其常见的方法如表8.2所示。表8.2Bitmap常见的方法续表BitmapFactory主要用于加载Bitmap对象,可以从资源文件加载,也可以根据图片的路径进行加载,还可以根据输入
流对Bitmap对象进行解析,相应的方法如表8.3所示。表8.3BitmapFactory的方法8.2.2Android绘图基础除了显示已有的图片之外,Android还支持一些简单的二维绘图,其实对于Android的一些基本组件,如TextView、Button等,也都是系统绘制出来的,绘制的操作
在View类的onDraw(Canvascanvas)方法中,每个组件需要实现onDraw(Canvascanvas)方法进行自定义的绘制。所以,Android的绘图应该定义一个类继承自View组件,并重新定义onDraw(Canvascanvas)方法。其
中,参数Canvas可以理解为画布,绘制操作均在Canvas上执行。Canvas支持的一些方法如表8.4所示。表8.4Canvas类支持的操作举例续表从表8.4中可以看到,每一个方法中都包含一个Paint类的参数,Paint类代表画笔,它指定了画笔的
颜色和粗细等,相关的方法如表8.5所示。表8.5Paint类相关的方法例说明绘制API的方法,运行结果如图8.1所示。图8.1图形的绘制8.2.3补间动画在Android应用中,经常会出现一些动画效果,例如控件的滑入滑出、图片的渐隐等。常见的
实现方式有补间动画和属性动画,补间动画是指开发者指定好控件的初始状态和结束状态,系统自动补齐显示控件的中间状态。Android补间动画支持的效果比较简单,包括平移、缩放、旋转、透明度变化,对应的类如表8.6所示。表8.6补间动画对应的类本例在Activity上显示一
张图片和4个按钮,4个按钮分别用于触发4种动画,运行结果如图8.2所示。图8.2补间动画实例8.2.4属性动画属性动画是在API11之后加入的功能,它几乎可以作用在任何对象上,而且不同于补间动画只能支持4种变换,属性动画是在一定时间内将对象的属性从一个初始值改变到另一个值,因此,只要是
对象存在的属性,无论是可见还是不可见的,都可以实现动画效果。属性动画可以通过ObjectAnimator实现。下面我们通过一个实例说明一下属性动画的具体属性。本例在Activity中定义了两个按钮,一个用于触发图片的平移,另一个用于触发图片的透明度的变换。案例分析单击按钮后,使用Ob
jectAnimator类实现属性动画,首先调用ofFloat()方法获取ObjectAnimator对象,ofFloat()方法第1个参数为需要变换的对象,第2个参数为需要改变的属性,“translationX”表示水平方向上的平移,“
alpha”为透明度的改变,其他的还有“rotationX”“rotationY”等,设置好需要控制的对象和属性之后,调用setDuration()设置动画执行的时间,最后调用start()方法执行动画。8
.3多媒体应用开发在Android应用中,经常需要播放媒体资源,如音乐播放器、视频播放器和游戏的背景音乐等。Android提供了MediaPlayer类,可以很简单地实现播放本地存储或者网络上的音/视频文件。8.3.1M
ediaPlayer类介绍MediaPlayer提供了大量的方法可以控制音/视频的播放、暂停、定位等,常见的方法如表8.7所示。表8.7MediaPlayer类的方法续表使用MediaPlayer播放音/视频时,首先调用setDataSourc
e()方法设置需要播放的视频源,然后调用prepare()或prepareAsync()方法做视频播放的准备工作。两个方法的区别在于prepareAsync()是异步方法,不会阻塞程序的执行,可以通过调用setOnPreparedListener()方法监听播放器是
否已经准备好,准备好之后就可以调用start()方法进行播放。8.3.2使用MediaPlayer和SurfaceView播放视频播放的视频必须显示在View上,而且视频的画面一直在改变,所以View需要一直重绘。对于这种需要不断更新View内容的场景,An
droid提供了SurfaceView类,SurfaceView关联了一个SurfaceHolder对象,专门用于绘制SurfaceView的内容。SurfaceHolder会有3个回调方法反馈SurfaceView的状态,具体如表8.8所示。表8.8Surf
aceHolder的回调方法本例实现视频播放,单击“暂停”按钮时,暂停播放视频;单击“播放”按钮时,重新开始播放视频。最终可以退出播放页面。案例分析实例中首先获取了SurfaceView对象,然后调用getHolder()方法获取关联的SurfaceHolder
对象,设置监听事件,当SurfaceView创建完成之后将SurfaceHolder设置给MediaPlayer。然后调用setDataSource()方法设置视频源,为MediaPlayer设置监听事件。接
着调用prepareAsync()方法做MediaPlayer的准备工作,准备完成之后会回调onPrepared()方法,在其中开始播放视频。单击“暂停”按钮时,调用pause()方法暂停播放视频;单击“播放”按钮时,调用play()方法重新开始播放视频。退出播放页面
时,调用release()方法释放MediaPlayer占用的资源。8.4线程开发线程在程序开发中是一个很重要的概念,在Android中,线程分为主线程和子线程。主线程又叫作UI线程,主要处理和界面有关的事情,用
于界面的绘制和交互。对于用户来说,随时都有可能操作页面,而且对响应速度要求较高,因此,主线程中不能做太耗时的操作,否则会给用户视觉上造成卡顿的现象,甚至有可能会因为执行阻塞产生ANR(ApplicationNotResponding
)而导致应用异常退出。Android基于Java开发,所以对于线程也有很好的支持,除了JDK中支持的一些API之外,Android也针对自身的机制做了一些拓展。下面我们将介绍两个常用的类:AsyncTask和ThreadPoolExecutor。8.4.
1AsyncTask及其使用AsyncTask是一个执行异步操作的类,它在主线程中创建和触发,但是在子线程中执行后台任务,然后将执行的进度和最终结果传递给主线程并在主线程中更新UI。例如有一种很常见的操作,应用中如果要在Ima
geView控件中显示一张网络图片,首先需要从网络上下载图片,然后显示到控件上。图片的下载依赖于网络情况,如果在主线程中执行下载操作,可能会造成用户长时间等待,并且不能及时响应用户的操作。这时就可以使用AsyncTask类在子
线程中执行下载操作,然后通知主线程下载完成并显示。AsyncTask有3个主要的回调方法,如表8.9所示。表8.9AsyncTask的主要回调方法8.4.2ThreadPoolExecutor介绍当一个应用中需要创建多个线程时,可以将其放入线程池
中进行管理,Java中使用Executor做线程池的管理和线程的调度。Executor是一个接口,它的实现类为ThreadPoolExecutor。创建ThreadPoolExecutor对象时,可以向构造函数传入一系列的参数来配置线程池。常用的构造函数有ThreadPoolExec
utor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueue<Runnable>workQu
eue,ThreadFactorythreadFactory)。其中,corePoolSize是指线程池的核心线程数,maximumPoolSize指线程池可以容纳的最大的线程个数,keepAliveTime指非核心线程在空闲时
可以存活的时间,TimeUnit是参数keepAliveTime的单位,workQueue是指线程队列,ThreadFactory指线程工厂,用于线程池创建线程。为了帮助读者理解以上各个参数的含义,下面我们说明一下线程池的工作步骤。(1)当调用了
ThreadPoolExecutor的execute()方法要求执行一个任务时,线程池会判断当前的线程个数是否超过核心线程数,如果没有超过,则启动一个核心线程来执行任务。(2)如果当前的线程个数超过了核心线程的个数
,则将任务放到线程队列中排队等候。(3)如果线程队列已满,则启动一个非核心线程来执行任务。(4)如果线程的总个数已经达到了线程池最大的线程个数,则拒绝接收任务。(5)如果线程池有线程处于空闲状态,则在指定keepAliveTime后回收线程,当线程个数等于
核心线程数后,停止回收线程。8.5Fragment为了更加动态和灵活地支持UI设计,Android在API11版本之后引入了Fragment,它可以将UI碎片化,也可以被复用。Fragment必须显示在Activity
中,可以被动态地添加、移除、替换,但是每个Fragment也都具有自己的生命周期方法,并且可以各自处理用户的输入事件。常见的微信界面就可以使用Fragment来实现,如图8.3所示,单击下面的“微信”,上面就会对应显示聊天记
录,单击“通讯录”,上面就会显示联系人列表。如果使用Activity实现比较麻烦,但是如果使用Fragment实现就比较简单,界面的整体定义为一个Activity,中间的内容区域设计为一个Fragment,可
以根据用户单击的Item动态地更换显示区域的Fragment。图8.3微信界面8.5.1Fragment的创建和Activity类似,创建自定义的Fragment需要继承自Fragment类,并实现父
类的相关回调方法。其中比较常见的是onCreate()、onCreateView()、onPause()方法。onCreate()方法在创建Fragment时会回调;onCreateView()在绘制Fragm
ent视图的时候会回调,开发者需要在该方法中加载Fragment需要显示的布局文件;onPause()方法在用户离开Fragment时会回调。另外,Android通过FragmentManager类管理在A
ctivity中的Fragment,具体的操作在FragmentTransaction中。首先可以通过getFragmentManager()方法获取FragmentManager对象,然后调用FragmentM
anager的beginTransaction()开启一个事务执行具体的操作。FragmentTransaction类支持的常见操作如表8.10所示。表8.10FragmentTransaction类支持
的操作➢案例8.7单击底部按钮,上面内容区域动态改变本例运行结果如图8.4所示,单击下面的按钮,上面的内容会动态改变。图8.4Fragment实例案例分析本例为每一种内容都定义了一个Fragment,在Fragm
ent的onCreateView()方法中可以加载自己想要显示的布局文件,布局的处理并无特殊。然后在Activity中可以动态地控制Fragment的显示,非常灵活。8.5.2Fragment的生命周期Fragment有自己的生命周
期,但是其生命周期又依赖于Activity。当Activity处于不可见状态时,Fragment也一定处于不可见状态。当Activity处于销毁状态时,Fragment也一定处于销毁状态。Fragment在各个生命周期阶段也有不同的回调方法,具体流程如图8.5所示。图8.5Frag
ment的生命周期回调方法从图8.5中可以看出,Fragment的生命周期方法有些和Activity一致,意义也一致。表8.11用于说明Fragment特有的生命周期方法的含义。表8.11Fragment的生命周期方法说明
续表本例在Activity中显示两个按钮,单击其中一个按钮,将一个Fragment添加到Activity中,单击另外一个按钮,将Fragment从Activity中移除,界面如图8.6所示。图8.6Fragment生命周期实例界面案例分析单击Activity中的“add”
按钮,将Fragment添加到Activity中,控制台打印如图8.7所示。依次回调了onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onRes
ume()方法,Fragment处于前台可见。按“Home”键,使Activity处于后台不可见状态,Fragment也随之处于不可见状态,控制台打印如图8.8所示。依次回调了onPause()和onStop()
方法。单击Activity中的“remove”按钮,将Fragment移除,控制台打印如图8.9所示,依次回调了onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()方法。图8.7添加Fra
gment图8.8按“Home”键图8.9Fragment销毁8.6RecyclerView在Android应用中,很多时候需要显示大量的数据,例如音乐播放器的歌曲列表,手机中可能存在大量的歌曲文件,
但是同一时刻屏幕上只显示部分歌曲,用户可以通过上下滑动查看更多音乐。这种应用场景可以使用2.2节介绍的ListView和GridView实现布局。但是,Android还提供了一种更灵活的组件——RecyclerView,它可以动态地实现列表布局或网格布局,甚至每个I
tem都可以显示不同的布局文件。而且,RecyclerView内部还实现了View的复用,在用户上下滑动列表或网格时,RecyclerView并不会为每一个子项创建一个View,而是创建若干个View不断复用,更新其中显示的数据。8.6.1RecyclerVi
ew相关类在RecyclerView视图中,每个子项都被表示为ViewHolder对象,开发者必须继承RecyclerView.ViewHolder类实现自定义的ViewHolder类。每个ViewHolder都可以有一个布局文件用于显示一个子项。例如,如果用RecyclerView显
示音乐列表,则每一个ViewHolder可以代表一首歌曲,用来显示歌曲的歌手信息、时长信息等,还可以响应单击和长按事件等。RecyclerView通过Adapter管理ViewHolder,开发者必须继
承RecyclerView.Adapter类实现自定义的Adapter。Adapter中有很多回调方法,其中onCreateViewHolder()方法用于创建一个对应的ViewHolder,onBindViewHolder()用于将数据和Vie
wHolder进行绑定RecyclerView使用LayoutManager对其中的数据进行排列,开发者可以使用系统提供的LayoutManager,也可以自定义LayoutManager类实现自己想要的排列方式。系统提供的LayoutManager有3种,分别是LinearLayoutMan
ager、GridLayoutMananger和StaggeredGridLayoutManager。LinearLayoutManager将RecyclerView中的子项以一维列表的形式排列,类似于ListView的显示方式。GridLayoutManager将Re
cyclerView中的子项以二维网格的形式排列,类似于GridView的显示方式。StaggeredGridLayoutManager以瀑布流的方式排列RecyclerView中的子项。8.6.2RecyclerView的使用下面我们通过一个实例说明一下RecyclerView的具体使用,
运行结果如图8.10所示。图8.10RecyclerView的使用案例分析从实例中可以看到,RecyclerView在配置文件中的使用与普通组件一样,然后在代码中调用了findViewById()方法获取RecyclerView控件。在自定义的CustomAdapter类中,重
写了父类RecyclerView.Adapter中的onCreateViewHolder()和onBindViewHolder()方法。在onCreateViewHolder中,创建并返回了一个自定义的ViewH
older对象,在onBindViewHolder()方法中,将数据和ViewHolder绑定并显示。本章我们主要扩展地介绍了一些进阶知识,随着移动互联网的高速发展,移动应用几乎都需要一些网络通信。本章我们首先介绍了An
droid中的网络编程,然后介绍了一些图形图像和动画的知识,可以丰富Android页面的显示。8.3节介绍了MediaPlayer类,可以用于播放一些音/视频。在Android应用中,经常会有一些比较耗时的任务,本章我们介绍了AsyncTask用于异步刷新,ThreadPoolExecuto
r用于管理线程。最后介绍的Fragment可以支持更加灵活的碎片式开发,RecyclerView可以方便用户更好地自定义实现ListView和GridView。在掌握基础知识的同时,读者多了解一些新的开发技术和控件,可以更灵活地开发出更丰富
的界面和功能。