Android网络请求是个耗时的操作,一定要在子线程中运行,添加网络权限,目前有很多流行的网络框架。比如okhttp,volley,xutils等等。使用okhttp很简单,它的请求/响应 API设计,运用了流利的builder,确保方式多样而又固定,支持异步请求和回调。它支持android 2.3或以上,jdk版本要求不低于1.7。
在使用OkHttp之前,需要先在项目中添加OkHttp库的依赖。编辑app/build.gradle文件,在dependencies闭包中添加如下内容,下载OkHttp库和Okio库.
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.4.1'
}
还有另外一种添加OkHttp库依赖包的方法:
按Android Studio中快捷键Ctrl+Shift+Alt+s,在库中搜索OKhttp并添加:
在日常开发中最常用到的网络请求就是GET和POST两种请求方式。
OkHttp通过“GET”发送HTTP请求核心代码:
/**
*由于Android本身是不允许在UI线程做网络请求操作的,
* 同步写法,需要放在子线程中使用.
*/
new Thread(new Runnable() {
@Override
public void run() {
try {
//创建一个OkHttpClient实例
OkHttpClient client=new OkHttpClient();
//创建一个Request对象,在build()之前连缀很多其他方法来丰富
//这个Request对象,比如用url()方法来设置网络地址。
Request request= new Request.Builder().
url("https://www.baidu.com/").build();
//调用OkHttpClient的newCall()方法来创建一个对象Call对象,
//并调用它的execute()方法来发送请求并获取返回的数据。
Response response=client.newCall(request).execute();
//获取服务器返回的具体数据
String responseData=response.body().string();
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
Request是OkHttp中访问的请求,Builder是辅助类,Response即OkHttp中的响应。
同步的get请求方法还有另外一种写法;
Responses(响应), 响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder().url(url).build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); }
}
Response类:
public boolean isSuccessful()
Returns true if the code is in [200..300), which means the request was successfully received, understood, and accepted.
response.body()返回ResponseBody类
response.body()返回ResponseBody类
可以更方便的获取string:
public final String string() throws IOException
Returns the response as a string decoded with the charset of the Content-Type header. If that header is either absent or lacks a charset, this will attempt to decode the response body as UTF-8.
Throws:
IOException
以上的请求都是同步请求,下面异步请求:
OkHttp通过“GET”发送异步请求核心代码:
//创建OkHttpClient对象,用于稍后发起请求
OkHttpClient client = new OkHttpClient();
//根据请求URL创建一个Request对象
Request request = new Request.Builder().url("url").build();
//根据Request对象发起Get同步Http请求
Response response = client.newCall(request).execute();
//根据Request对象发起Get异步Http请求,并添加请求回调
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(final Response response) {
//请求成功,此处对请求结果进行处理
//String result = response.body().string();
//InputStream is = response.body().byteStream();
//byte[] bytes = response.body().bytes();
}
@Override
public void onFailure(Request request, IOException e) {
//请求失败
}
});
HTTP异步 POST请求。
POST异步提交Json数据:
try {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
if(response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}catch (Exception e){
e.printStackTrace();
}
POST异步提交键值对:
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody formBody = new FormEncodingBuilder()
.add("platform", "android")
.add("name", "bug")
.add("subject", "XXXXXXXXXXXXXXX")
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code" + response);
}
}
使用OkHttp下载网络图片栗子:
activity_main.xml
Java代码:
public class MainActivity extends AppCompatActivity {
private String url="http://photocdn.sohu.com/20110927/Img320705637.jpg";
private static final int SUCCESS = 1;
private static final int FALL = 2;
private OkHttpClient client;
private Button getButton;
private ImageView getImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initLayout();
}
public void initLayout(){
getImageView=(ImageView) findViewById(R.id.imageView);
getButton=(Button) findViewById(R.id.button);
getButton.setOnClickListener(new View.OnClickListener() {
/**
* 异步get,直接调用
*/
@Override
public void onClick(View v) {
//1.创建一个client对象
client=new OkHttpClient();
//2.创建Request.Builder对象,设置参数,
//请求方式如果是Get,就不用设置,默认就是Get
Request request=new Request.Builder().url(url).build();
//3.创建一个Call对象,参数是request对象,发送请求
Call call=client.newCall(request);
//4.异步请求,请求加入调度
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response)
throws IOException {
//得到从网上获取资源,转换成我们想要的类型
byte[] getData=response.body().bytes();
//通过handler更新UI
Message message=handler.obtainMessage();
message.obj=getData;
message.what=SUCCESS;
handler.sendMessage(message);
}
});
}
});
}
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case SUCCESS:
//通过message,拿到字节数组
byte[] data=(byte[]) msg.obj;
//使用BitmapFactory工厂,把字节数组转化为bitmap
Bitmap bitmap= BitmapFactory
.decodeByteArray(data,0,data.length);
//通过imageview,设置图片
getImageView.setImageBitmap(bitmap);
break;
//当加载网络失败执行的逻辑代码
case FALL:
Toast.makeText(MainActivity.this, "网络出现了问题",
Toast.LENGTH_SHORT).show();
break;
}
}
};
}
记得申请网络权限:
同步get请求下载网络图片代码:由上面的栗子改下点击事件里的逻辑代码即可
@Override
public void onClick(View v) {
/**
* 同步写法,需要放在子线程中使用
*/
new Thread(new Runnable() {
@Override
public void run() {
try {
//创建一个client实例对象
client=new OkHttpClient();
//获取请求对象
Request request=new Request.Builder()
.url(url).build();
Response response=client.newCall(request)
.execute();
InputStream ism=response.body().byteStream();
// //获取响应体(也可以这样写)
// ResponseBody Body=client.newCall(request)
// .execute().body();
// //获取流
// InputStream ism=Body.byteStream();
//转化为bitmap
Bitmap bitmap= BitmapFactory.decodeStream(ism);
//使用Hanlder发送消息
Message msg=handler.obtainMessage();
msg.obj=bitmap;
msg.what=SUCCESS;
handler.sendMessage(msg);
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case SUCCESS:
getImageView.setImageBitmap((Bitmap) msg.obj);
break;
case FALL:
Toast.makeText(OkHttpActivity.this,
"连接超时", Toast.LENGTH_SHORT).show();
break;
}
}
};
异步同步效果图都一样,成功下载图片:
总结一下:
OkHttp 是一个相对成熟的解决方案,据说 Android4.4 的源码中可以看到 HttpURLConnection 已经替换成 OkHttp 实现了。在 Android 6.0 中底层的源码已经使用了 OKHttp 。OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个 IP 连接失败的时候,OkHttp 会自动尝试下一个 IP。OkHttp 还处理了代理服务器问题和 SSL握手失败问题。使用 OkHttp 无需重写您程序中的网络代码。