Android学习之基础知识十三—网络编程的最佳实践

  上一讲已经掌握了HttpURLConnection和OkHttp的用法,知道如何发起HTTP请求,以及解析服务器返回的数据,但是也许你还没发现,之前我们的写法其实是很有问题的,因为一个应用程序很可能会在许多地方使用到网络功能,而发送HTTP请求的代码基本都是相同的,如果我们每次都去编写一遍发送HTTP请求的代码,这显然是非常差劲的做法。

  通常情况下我们都应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候,只需要简单的调用一下这个方法即可,比如使用如下的写法:

以后每当需要发起一条HTTP请求的时候就可以这样写:

   在获取到服务器响应的数据后,我们就可以对它进行解析和处理了,但是需要注意的是,网络请求通常都是属于耗时操作,而:sendHttpRequest()方法的内部并没有开启线程,这样就可能导致在调用:sendHttpRequest()方法的时候使得主线程被阻塞。

  如果我们在:sendHttpRequest()方法内部开启一个线程来发起HTTP请求,那么服务器响应的数据是无法进行返回的,所有的耗时逻辑都是在子线程里进行的,sendHttpRequest()方法会在服务器还没来得及响应的时候就执行结束了,当然就无法返回响应的数据了。

  那么遇到这种情况时该怎么办呢?其实解决办法并不难,只需要使用Java的回调机制就可以了。下面就来学习一下回调机制到底是如何使用的:

首先需要定义一个接口,比如将它命名为HttpCallbackListener,代码如下:

  可以看到,我们在接口中定义了两个方法,onFinish()方法表示当服务器成功响应我们请求的时候调用,onError()表示当进行网络操作出现错误的时候调用,这两个方法都带有参数,onFinish()方法中的参数代表着服务器返回的数据,而onError()方法中的参数记录着错误的详细信息。

接着修改HttpUtil中的代码:

  我们首先给sendHttpRequest()方法添加了一个HttpCallbackListener参数,并在方法的内部开启了一个子线程,然后在子线程里去执行具体的网络操作,注意,子线程中是无法通过return语句来返回数据的,因此这里我们将服务器响应的数据传入了HttpCallbackListener的onFinish()方法中,如果出现了异常就将异常原因传入到onError()方法中。

  现在sendHttpRequest()方法接收两个参数,因此我们在调用它的时候还需要将HttpCallbackListener的实例传入,如下所示:

  这样的话,当服务器成功响应的时候,我们就可以在onFinish()方法里对响应数据进行处理了。类似的,如果出现了异常,就可以在onError()方法里对异常情况进行处理,如此一来,我们就巧妙地利用回调机制将响应数据成功返回给调用方了。

  不过你会发现,上述使用HttpURLConnection的写法总体来说还是比较复杂的,那么使用OkHttp会变得简单吗?答案是肯定的,而且要简单得多,下面我们来具体看一下:在HttpUtil中加入一个sendOkHttpRequest()方法,如下所示:

  可以看到,sendOkHttpRequest()方法中有一个okhttp3.Callback参数,这个是OkHttp库中自带的一个回调接口,类似于我们刚才自己编写的HttpCallbackListener,然后在client.newCall()之后没有像之前那样一直调用execute()方法,而是调用了一个enqueue()方法,并把okhttp3.Callback参数传入。这里可以猜到:OKHttp在enqueue()方法的内部已经帮我们开好了线材了,然后会在子线程中去执行HTTP请求,并将最终的请求结果回调到okhttp3.Callback当中。

  那么我们在调用sendOkHttpRequest()方法的时候就可以这样写:

  由此可以看出,OkHttp的接口设计的确实非常人性化,它将一些常用的功能进行了很好的封装,使得我们只需编写少量的代码就能完成较为复杂的网络操作,当然这并不是OKHttp的全部,后面我们还会继续学习它的相关知识

  另外需要注意的是:不管是使用HttpURLConnection还是OkHttp,最终的回调接口都还是在子线程中运行的,因此我们不可以在这里执行任何的UI操作,除非借助runOnUiThread()方法来进行线程转换,至于具体的原因后面会说到。

原文地址:https://www.cnblogs.com/hh8888-log/p/10295778.html

时间: 2024-11-05 19:01:21

Android学习之基础知识十三—网络编程的最佳实践的相关文章

android学习二十四(网络编程的最佳实践)

前面的博客已经讲解了HttpURLConnection和HttpClient的用法,知道了如何发起HTTP请求,以及解析服务器返回 的数据.但是可能你发现了,因为一个应用程序很多地方都可能使用网络功能,而发送HTTP请求的代码基本相同,如果每次我们都去编写一遍发送HTTP请求的代码,这显然不太好. 通常情况下我们都应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候只需简单地调用一下这个方法即可.比如下面的写法: package com.jack.netwo

Android学习之基础知识十六 — Android开发高级技巧的掌握

一.全局获取Context的技巧 前面我们很多地方都使用到了Context,弹出Toast的时候.启动活动的时候.发送广播的时候.操作数据库的时候.使用通知的时候等等.或许目前来说我们并没有为得不到Context而发愁,因为我们很多地方都是在活动中进行的,而活动本身就是一个Context对象,但是,当应用程序的架构逐渐开始复杂起来的时候,很多的逻辑代码都将脱离Activity类,但此时又恰恰需要使用Context,特许这个时候就会感到有些伤脑筋了. 举个例子,在前面网络编程的最佳实践中,我们编写

JAVA基础知识之网络编程——-网络基础(多线程下载,get,post)

本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web资源,URLDecode和URLEncode用来转换字符串. 本文会写两个例子来演示java网络编程的一些基本用法. 第一个例子,写一个程序用来模拟多线程下载. 本例中用到的技术有,多线程--多个线程同时读文件写文件,可以加快下载速度, 线程池--在本例中线程池不是必须,甚至是多余,只不过是为了演示

Android学习之基础知识十四 — Android特色开发之基于位置的服务

一.基于位置的服务简介 LBS:基于位置的服务.随着移动互联网的兴起,这个技术在最近的几年里十分火爆.其实它本身并不是什么时髦的技术,主要的工作原理就是利用无线电通讯网络或GPS等定位方式来确定出移动设备所在的位置,而这种技术早在很多年前就已经出现了. 那么为什么LBS技术直到最近几年才开始流行呢?这主要是因为,在过去移动设备的功能及其有限,即使定位到了设备所在的位置,也就仅仅只是定位到了而已,我们并不能在位置的基础上进行一些其他的操作.而现在就大大不同了,有了Android系统作为载体,我们可

Android学习之基础知识八—Android广播机制

一.广播机制简介 Android提供了一套完整的API,允许应用程序自由的发送和接受广播,发送广播借助于我们之前学过的:Intent,而接收广播需要借助于广播接收器(Broadcast Receiver) 广播的类型主要分为两种:标准广播和有序广播. 标准广播:一种完全异步执行的广播,在广播发出之后,所有接收器几乎在同一时刻接收到这条广播消息,因此它们之间没有任何的先后顺序可言,这种广播的效率会比较高,但是同时也意味着它无法被截断的.标准广播的工作流程图如图所示: 有序广播:一种同步执行的广播,

Android学习之基础知识九 — 数据存储(持久化技术)之使用LitePal操作数据库

上一节学习了使用SQLiteDatabase来操作SQLite数据库的方法,接下来我们开始接触第一个开源库:LitePal.LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表和增删改查的操作,LitePal的项目主页上也有详细的使用文档,地址是: https://github.com/LitePalFramework/LitePal 一.配置LitePal 要在

JAVA基础知识之网络编程——-基于AIO的异步Socket通信

异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞IO都是针对第一步来划分的,如果发出IO请求会阻塞线程,就是阻塞IO,否则就是非阻塞IO. 同步IO和非同步IO是针对第二步来说的,如果实际IO操作是由操作系统完成,再返回给程序,就是异步IO. 如果实际的IO需要程序本身去执行,会阻塞线程,就是同步IO. JAVA7的NIO.2提供了异步的channel,

JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七层:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层 TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. 网络分层除了OSI模型分层,还有TCP/IP模型分层,将网络划分为四层,应用层.传输层.网际层

JAVA基础知识之网络编程——-基于UDP协议的通信例子

UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramSocket类的receive和send方法即可,但消息需要通过一个特定的类封装(DatagramPacket) 下面是一个基于UDP协议的通信的例子, 服务器端, 1 package udp; 2 3 import java.io.IOException; 4 import java.net.Dat