android网络通信(十二)

App开发常用的一些网络通信技术,主要包括如何使用多线程完成异步操作、如何进行HTTP接口调用与图片获取、如何实现文件上传和下载操作、如何运用Socket通信技术。

一、 多  线  程 

介绍多线程技术在App开发中的具体运用,首先说明如何利用Message配合Handler完成主线程与分线程之间的简单通信;然后阐述进度对话框的用法,以及如何自定义实现文本进度条与文本进度圈;接着讲述异步任务AsyncTask的具体用法和注意事项;最后分析异步服务IntentService的实现原理和开发步骤。

  1.消息传递Message

           Android系统存在限制,只有主线程才能直接操作界面,因此分线程想修改界面就得另想办法。

          多线程技术并非单单用于拍照预览,还用于网络通信、后台服务等耗时场合,并且这些场合往往希望操纵现有的界                   面。这要求有一种用于线程之间相互通信的机制。

           为此,Android设计了一个Message消息工具,通过结合Handler与Message可简单有效地实现线程之间的通信。                     分线程将消息传递给主线程,再由主线程来操作界面。

主线程与分线程之间传递消息的步骤

          1). 在主线程中构造一个Handler对象,并启动分线程

                    启动分线程有两种方式,既可通过Handler对象的post方法启动Thread,也可直接调用Thread对象的start方                      法。

          2). 在分线程中构造一个Message对象的消息包

                   Message是多线程通信中的消息包裹,类似于Intent机制的Bundle工具。

          3). 在分线程中通过Handler对象将Message消息发出去

                   处理器Handler的消息发送操作主要是各类send方法。

         4). 主线程中的Handler对象处理接收到的消息

                  主线程根据收到的Message消息内容分别进行相应处理。

  2.进度对话框ProgressDialog

                  分线程在处理事务期间不允许用户继续操作界面控件,这时可通过进度对话框ProgressDialog提示用户等待。                               下面是进度对话框的常用方法。

                        setTitle:设置对话框的标题文本。

                        setMessage:设置对话框的消息内容。

                        setProgressStyle:设置进度条的样式。

                        setProgress:设置当前进度的数值。

                        show:显示对话框。

                        dismiss:关闭对话框。

进度对话框的展示效果

android网络通信(十二)_第1张图片

自定义进度条(上)

           (1). 在长条样式中增加文字说明

                     1)通过自定义层次图形修改长条样式的展示效果。

                      2)重写ProgressBar的onDraw方法,往进度条上添加指定文本。

android网络通信(十二)_第2张图片

自定义进度条(下)

           (2). 在圆圈进度中增加文字说明

                      仿照“ 圆弧进度动画”,先画个背景圆环,再根据进度比例画个前景圆弧,最后在圆心处添加进度文本。

android网络通信(十二)_第3张图片

  3.异步任务AsyncTask

                   Android提供了AsyncTask这个轻量级的异步任务工具,内部已经封装好Thread+Handler的线程通信机制。

                   AsyncTask是一个模板类(AsyncTask),它的模板参数说明如下。

                                   Params:任务启动时的输入参数。

                                   Progress:任务执行过程中的进度。

                                   Result:任务执行完的结果参数

如何使用AsyncTask(上)

               开发者自定义的任务类需要实现以下方法。

                         onPreExecute:准备执行任务时触发。

                         doInBackground:在后台执行的业务处理。网络请求等异步处理操作都放在该方法中。注意,该方法运                                行于分线程,不能直接操作界面。

                          onProgressUpdate:在doInBackground方法中调用publishProgress方法时触发。该方法通常用于在处理                              过程中刷新进度条。

                           onPostExecute:任务执行完成时触发。

                           onCancelled :调用任务对象的cancel方法时触发。

如何使用AsyncTask(下)

                AsyncTask有如下可直接调用的启停方法。

                            execute:开始执行异步处理任务。

                            executeOnExecutor:以指定的线程池模式执行任务。

                            publishProgress:更新进度。

                            get:获取处理结果。

                            cancel:取消任务。

                            isCancelled:判断该任务是否取消。

                            getStatus:获取任务状态。

使用AsyncTask的注意事项

              AsyncTask在简单场合已经足够使用,如果要用于大量并发处理,就要注意以下两点:

                          (1)AsyncTask默认的线程池模式是SERIAL_EXECUTOR,即按照先后顺序依次调用。假设有两个网                                            络请求任务,第一个是文件下载,第二个是接口调用,那么接口调用任务会等待文件下载完毕后执行,                                          而不是在调用时立刻执行。                                     

                            (2)由于顺序模式存在排队等待的情况,因此Android提供了executeOnExecutor方法,允许开发者指                                           定任务线程池。但该线程池的最大线程个数是CPU个数的两倍再加1,所以线程池的处理能力依赖于手                                           机的CPU数量。

  4. 异步服务IntentService

            后台服务经常要做一些耗时操作,比如批量处理、文件导入、网络访问等,此时不应该影响用户在界面上的操                             作,而应该开启分线程执行耗时操作。可以通过Thread+Handler机制实现异步处理,也可以通过Android封装好的                         异步服务IntentService处理。

              使用IntentService有两个好处:

                   (1)免去复杂的消息通信流程;

                   (2)处理完成后无须手工停止服务,开发者可集中精力进行业务逻辑的编码。

IntentService的实现步骤

                   SDK源码里的IntentService实现步骤如下:

                  (1)创建异步服务时,初始化分线程的Handler对象。

                  (2)异步服务开始运行时,通过Handler对象将请求数据送给分线程。

                  (3)分线程在Handler对象的handleMessage方法中,先通过onHandleIntent方法执行具体的事务处理,再调                          用stopSelf结束指定标识的服务。

使用IntentService的注意事项

                  (1)增加一个构造方法,并分配内部线程的唯一名称。

                  (2)onStartCommand方法要调用父类的onStartCommand,因为父类方法会向分线程传递消息。

                  (3)耗时处理的业务代码要写在onHandleIntent方法中,不可写在onStartCommand方法中。因为                                               onHandleIntent方法位于分线程,而onStartCommand方法位于主线程。

                  (4)IntentService实现了onStart方法,却未实现onBind方法,意味着异步服务只能用普通方式启停,不能用                               绑定方式启停。

二、HTTP接口访问

       介绍HTTP接口访问的相关技术与具体使用,首先说明如何利用连接管理器ConnectivityManager检测网络连接的状态;然后阐述App用于接口调用的移动数据格式JSON的构建与解析;接着举例说明通过HttpURLConnection实现基本的接口调用;最后讲述利用HttpURLConnection从网络获取小图片的方法。

  1.网络连接检查

           添加网络权限配置后,可利用连接管理器ConnectivityManager检测网络连接。

           调用连接管理器对象的getActiveNetworkInfo方法,返回一个NetworkInfo实例,通过该实例可获取详细的网络连接               信息。

           下面是NetworkInfo的常用方法。

                  getType:获取网络类型。

                 getState:获取网络状态。状态为CONNECTED表示已连接。

                 getSubtype:获取网络子类型。

网络连接的检查结果

android网络通信(十二)_第4张图片

  2. 移动数据格式JSON

            网络通信的交互数据格式有两大类,分别是JSON和XML 。

            对于App来说,基本采用JSON格式与服务器通信。

JSON相比XML的优势主要有两个:

          (1)手机流量很贵,表达同样的信息,JSON串比XML串短很多。

          (2) JSON串解析得更快,也更省电,XML不但慢而且耗电。

如何解析json串(上)

            Android自带JSON解析工具,提供对下列两个对象的解析处理:

            1). JSONObject

                      JSONObject的常用方法如下:

                       构造函数:从指定字符串构造一个JSONObject对象。

                       getJSONObject:获取指定名称的JSONObject对象。

                       getString:获取指定名称的字符串。

                       getInt:获取指定名称的整型数。

                       getDouble:获取指定名称的双精度数。

                       getBoolean:获取指定名称的布尔数。

                       getJSONArray:获取指定名称的JSONArray数组对象。

                       put:添加一个JSONObject对象。

如何解析json串(下)

                     2). JSONArray

                             JSONArray的常用方法如下:

                             length:获取JSONArray数组的长度。

                             getJSONObject:获取JSONArray数组在指定位置的JSONObject对象。

                             put:往JSONArray数组中添加一个JSONObject对象

  3.JSON串与实体类自动转换

                            json解析除了系统自带的org.json,谷歌公司也提供了一个增强库gson,专门用于json串的自动解析。

                           由于gson是第三方库,因此首先要修改模块的build.gradle文件,在里面的dependencies节点下添加下                                 面一行配置,表示导入指定版本的gson库:

                               implementation "com.google.code.gson:gson:2.8.2"

如何使用gson库

                           在java源码的文件头部添加如下一行导入语句,表示后面会用到Gson工具类:

                                 import com.google.gson.Gson;

                           Gson常用的方法有两个:

                           (1)一个方法名叫toJson,可把数据对象转换为json字符串;

                           (2)另一个方法名叫fromJson,可将json字符串自动解析为数据对象。

  4. HTTP接口调用

                          HTTP接口调用的代码标准有两个,分别是HttpURLConnection与HttpClient。

                          移动端的代码标准基本采用更轻量级的HttpURLConnection。

                          HTTP接口调用主要有GET和POST两种方式:

                                          (1)GET方式只是简单的数据获取操作,类似于数据库的查询操作;

                                          (2)POST方式有提交具体的表单信息,类似于数据库的增、删、改操作。

如何使用HttpURLConnection

                        HttpURLConnection实例从URL对象的openConnection方法获得。

                        下面是它的常用方法。

                         setRequestMethod:设置请求类型。

                         setConnectTimeout:设置连接的超时时间。

                         setRequestProperty:设置请求包头的属性信息。

                         getOutputStream:获取HTTP输出流。在此写入要发送的数据。

                         connect:建立HTTP连接。

                         getInputStream:获取HTTP输入流。在此读出接收的数据。

                         getResponseCode:获取HTTP返回码。

                         disconnect:断开HTTP连接。

HTTP调用的特殊情况处理

                         HTTP访问还要处理好几种特殊情况,否则就不会正常工作。常见的特殊情况有两种:

                                  1. URL串中对汉字的转义处理

                                             使用GET方式传递请求数据,参数放在URL中直接传送过去。如果参数值有汉字,就进行                                                       UTF8编码转义处理,比如“你”要转为“%E4%BD%A0”。同理,对于服务器返回的UTF8编码也要                                                      进行反转义。

                                  2. 返回内容为压缩数据时的解压处理

                                             HTTP请求的包头带有Accept-Encoding:gzip,deflate,表示客户端支持gzip压缩。服务器可                                                能返回gzip压缩的应答数据,此时应答包头中会有Content-Encoding:gzip。此时压缩数据必须先                                                  解压才能正常读取。

HTTP接口调用的实现例子

                            利用Google Map的开放API,通过HTTP调用传入经纬度的数值,然后对方返回一个JSON格式的地址                                       信息字符串,通过解析JSON串就能得到具体的地址。

                             下面是根据经纬度成功获取地址信息的效果图。

android网络通信(十二)_第5张图片

  5.HTTP图片获取

                       HttpURLConnection还可用于获取网络小图片。比如验证码图片、头像图标等,这些小图不大,一般也无                              须缓存,可直接从网络上获取最新的图片。

                      通过HttpURLConnection获取图片的关键代码如下,主要是利用BitmapFactory的decodeStream方法得到位                              图数据:            

                       // 从HTTP连接获取输入流        

                      InputStream is = conn.getInputStream();      

                      // 对输入流中的数据进行解码,得到位图对象        

                       resp_data.bitmap = BitmapFactory.decodeStream(is);

HTTP图片获取的实现效果

android网络通信(十二)_第6张图片

三、上传和下载

                 介绍App与服务器之间上传文件和下载文件的实现与管理,首先对下载管理器DownloadManager进行详细说明;然后              阐述基于Fragment技术的文件对话框实现;最后介绍通过HttpURLConnection的POST方式如何实现文件的上传操作。

1. 下载管理器DownloadManager

            使用HttpURLConnection虽然可以获取小图片,但是这么做有诸多限制,比如:

            (1)无法断点续传,一旦中途失败,只能从头开始获取。

            (2)只能获取图片,不能获取其他文件。

            (3)不是真正意义上的下载操作,没法设置下载参数。

   因为下载功能比较常用且业务功能相对统一,所以Android提供了专门的下载工具—— DownloadManager统一管理下载               操作。

如何使用DownloadManager

              下载管理器DownloadManager的对象从系统服务

              Context.DOWNLOAD_SERVICE中获取,具体使用过程分为3步:

              1). 构建下载请求

                         要想使用下载功能,首先得构建一个下载请求,说明从哪里下载、下载参数是什么、下载的文                                               件保存到哪里等。

              2). 进行下载操作

                         构建完下载请求才能进行下载的相关操作。

             3). 查询下载进度

                          如果App自身也想了解当前的下载进度,就要调用下载管理器的query方法。该方法返回结果集的Cursor                           游标,通过游标即可获得下载信息。

下载服务涉及到的下载事件

              系统的下载服务还提供3种下载事件,开发者可通过监听对应的广播消息进行相应的处理。

             1). 下载完成事件 在下载完成时,系统会发出名为DownloadManager.ACTION_DOWNLOAD_COMPLETE的广                             播。

             2). 下载进行时的通知栏点击事件 在下载过程中,只要用户点击通知栏上的下载任务,系统就会发出行为名称是                              DownloadManager.ACTION_NOTIFICATION_CLICKED的广播。

             3). 下载完成后的通知栏点击事件 在不同时刻点击通知栏上的下载任务会触发不同的事件。

动态展示图片下载进度的效果

android网络通信(十二)_第7张图片

2.  文件对话框

               下载和上传操作涉及文件的保存和打开,就像电脑上的文件对话框,既可选择文件又可保存文件。然而Android                 没有提供现成的文件对话框控件,需要开发者自己实现文件对话框。

               这里文件对话框的实现采用了DialogFragment。Fragment拥有如下子类,分别用于不同场合。 

                      DialogFragment:用于对话框的碎片。

                      ListFragment:用于列表的碎片,目的是取代ListActivity。

                      PreferenceFragment:用于参数设置页面,目的是取代PreferenceActivity。

                      WebViewFragment:用于网页视图的碎片。

文件对话框的实现效果

android网络通信(十二)_第8张图片

3.  文件上传

                 文件上传的场合不是很多,通常用于上传用户头像、朋友圈发布图片和视频动态等,而且上传文件需要后端服                    务器配合。

                 Android没有提供专门的文件上传工具,开发者得自己写代码实现上传功能。

                 简单实现文件上传的话,按照HTTP访问的POST流程,只是要采取multipart/form-data的方式分段传输,并加                     入分段传输的边界字符串。

文件上传的实现效果

        文件上传的效果如下图所示。倘若上传成功,还应给出服务器对应的文件下载地址,这样才好验证上传成功与否。

android网络通信(十二)_第9张图片

 四、套接字Socket

             介绍套接字Socket的技术手段与具体用途,首先说明如何使用网络地址工具InetAddress判断某个网络地址的连通性,然          后阐述Socket技术在计算机网络中所处的层次、应用方向以及基本用法。

1. 网络地址InetAddress

      检查设备自身与某个网络地址的连通性用到了InetAddress工具,这是对网络地址的一个封装。

      下面介绍该工具的主要方法说明。

              getByName:根据主机IP或主机名称获取InetAddress对象。

              getHostAddress:获取主机的IP地址。

              getHostName:获取主机的名称。

              isReachable:判断该地址是否可到达,即是否连通。

检查网络地址连通性的效果

android网络通信(十二)_第10张图片

2. Socket通信

          计算机网络有一个大名鼎鼎的TCP/IP协议,TCP/IP是一个协议组,分为3个层次:

           网络层:包括IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。

          传输层:包括TCP协议和UDP协议。

          应用层:包括HTTP、FTP、TELNET、SMTP、DNS等协议。

          Socket属于传输层的技术, API实现TCP协议后即可用于HTTP通信,实现UDP协议后即可用于FTP通信,当然也                 可以直接在底层进行点对点通信。

如何进行Socket编程(上)

                   Android的Socket编程主要使用Socket和ServerSocket两个类:

                 1). Socket

                          Socket是最常用的工具,客户端和服务端都要用到,描述了两边对套接字(Socket)处理的一般行为。主要方                     法如下:

                           connect:连接指定IP和端口。该方法用于客户端连接服务端。

                           getInputStream:获取输入流,即自身收到对方发过来的数据。

                           getOutputStream:获取输入流,即自身向对方发送的数据。

                           getInetAddress:获取网络地址对象。

                            isConnected:判断socket是否连上。

                            isClosed:判断socket是否关闭。

                            close:关闭socket。

如何进行Socket编程(中)

                  2). ServerSocket ServerSocket仅用于服务端,在运行时不停地侦听指定端口。主要方法如下:

                            构造函数:指定侦听哪个端口。

                           accept:开始接收客户端的连接。有客户端连上时就返回一个Socket对象,若要持续侦听连接,则在循环语句                    中调用该函数。

                           getInetAddress:获取网络地址对象。

                           isClosed:判断socket服务器是否关闭。

                           close:关闭socket服务器。

如何进行Socket编程(下)

                          举个Socket通信的案例,详细步骤说明如下:

                        (1)首先在客户端与服务端之间建立Socket连接。

                        (2)然后在Activity中启动Socket连接的线程,等待界面向Socket服务器发送消息,并准备接收消息。

                        (3)最后启动Socket服务器(其实一开始就要启动,这样App运行时才能马上连上后端服务器)。

Socket通信的实现效果

 android网络通信(十二)_第11张图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(App上线)