jar包下载地址: https://github.com/square/okhttp
引入 jar包:
/*****
* 注意事项:
1,Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。
2,response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程。
3,response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。
而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。
4. apk 要 adb install 安装不能在线 安装 否则 java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/text/Charsets;
OkHttpClient client = new OkHttpClient();
会出现java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/text/Charsets;
at okio.Buffer.<clinit>(Buffer.kt:2212)
at okhttp3.ResponseBody.create(ResponseBody.java:210)
*
*
*/
activity:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
package com.zengjx.okhttpdemo;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSink;
/*****
* 注意事项:
1,Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。
2,response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程。
3,response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。
而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。
*
*
*
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btn_get,btn_get2,btn_post;
TextView tv_log;
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
private final static int GET=1;
private final static int POST=2;
final String TAG="MainActivity";
OkHttpClient client = new OkHttpClient();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
public void initView(){
btn_get=(Button) findViewById(R.id.btn_get);
btn_get.setOnClickListener(this);
btn_get2=(Button) findViewById(R.id.btn_get2);
btn_get2.setOnClickListener(this);
btn_post=(Button) findViewById(R.id.btn_post);
btn_post.setOnClickListener(this);
tv_log=(TextView)findViewById(R.id.tv_log);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_get:
getDataFromByGet();
// getDatasync();
break;
case R.id.btn_get2:
// getDataFromByGet();
getDatasync();
break;
case R.id.btn_post:
getDataByPost();
break;
default:
break;
}
}
/**
* 使用get请求网络数据
*/
/*
private void getDataFromGet() {
new Thread() {
@Override
public void run() {
super.run();
try {
okHttpClient.
String result = get("http://api.m.mtime.cn/PageSubArea/TrailerList.api");
Log.e("TAG", result);
Message msg = Message.obtain();
msg.what = GET;
msg.obj = result;
mHandler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
*/
/**************************
* 2-17 14:27:33.132 20653-20723/? D/MainActivity: response.code()==200
12-17 14:27:33.132 20653-20723/? D/MainActivity: response.message()==OK
12-17 14:27:33.133 20653-20723/? D/MainActivity: res==<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
*
*
*
*
*/
public void getDatasync(){
new Thread(new Runnable() {
@Override
public void run() {
try {
// client = new OkHttpClient();//创建OkHttpClient对象
Request request = new Request.Builder()
.url("http://api.m.mtime.cn/PageSubArea/TrailerList.api")//请求接口。如果需要传参拼接到接口后面。
.build();//创建Request 对象
Response response = null;
response = client.newCall(request).execute();//得到Response 对象
if (response.isSuccessful()) {
Log.d(TAG,"response.code()=="+response.code());
Log.d(TAG,"response.message()=="+response.message());
// Log.d(TAG,"res=="+response.body().string());
// response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。
Message msg = Message.obtain();
msg.what = GET;
msg.obj = response.body().string();
Log.i(TAG,"get:"+msg.obj);
mHandler.sendMessage(msg);
String str=(String)msg.obj;
Log.d(TAG,"send......"+str);
//此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* get请求
* @param url
* @return
* @throws IOException
*/
private String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
private void getDataFromByGet() {
new Thread(){
@Override
public void run() {
super.run();
try {
String resutl = get("http://api.m.mtime.cn/PageSubArea/TrailerList.api");
Message msg = Message.obtain();
msg.what = GET;
msg.obj = resutl;
Log.i(TAG,"get"+resutl);
mHandler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
private void getDataByPost(){
new Thread(){
@Override
public void run() {
super.run();
try{
String resutl = post("http://api.m.mtime.cn/PageSubArea/TrailerList.api","");
Message msg = Message.obtain();
msg.what = POST;
msg.obj = resutl;
Log.i(TAG,"get"+resutl);
mHandler.sendMessage(msg);
}catch ( IOException e){
e.printStackTrace();
}
}
}.start();
}
/****
*
* @param url
* @param json
* @return
* @throws IOException
*/
private String post(String url,String json) throws IOException{
RequestBody body =RequestBody.create(JSON,json);
Request request =new Request.Builder().url(url).post(body).build();
Response response =client.newCall(request).execute();
return response.body().string();
}
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case GET:
Log.d(TAG,"rev.....get");
tv_log.setText("");
tv_log.setText((String)msg.obj);
String rev=(String)msg.obj;
Log.i(TAG,"get rev"+rev);
break;
case POST:
Log.d(TAG,"rev.....post");
tv_log.setText("");
tv_log.setText((String)msg.obj);
}
return false;
}
});
}
-----------------------------------------------------------------------------------------------------------------------------------------------
build.gradle:
-------
applugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.zengjx.okhttpdemo"
minSdkVersion 22
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
/**第三方依赖库**/
compile 'com.android.support:multidex:1.0.3'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation files('libs/okhttp-3.4.1.jar')
implementation files('libs/okio-1.9.0.jar')
}
//Myaplication :为了解决引入第三方库错误 java.lang.NoClassDefFoundError
package com.zengjx.okhttpdemo;
import android.app.Application;
import android.support.multidex.MultiDex;
/**
* Created by zengjx on 2018/12/17.
*/
public class MyAppplication extends Application{
@Override
public void onCreate() {
MultiDex.install(this);
super.onCreate();
}
}
//权限:Androidmenifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zengjx.okhttpdemo">
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
get 异步:
-----------------------
//异步请求 //这种方式不用再次开启子线程,但回调方法是执行在子线程中,所以在更新UI时还要跳转到UI线程中。 //使用示例如下 private void getDataAsync() { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://www.baidu.com") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if(response.isSuccessful()){//回调的方法执行在子线程。 Log.d(TAG,"获取数据成功了"); Log.d(TAG,"response.code()=="+response.code()); String resutl = response.body().string(); // Log.d(TAG,"response.body().string()=="+response.body().string()); Message msg = Message.obtain(); msg.what = GET; msg.obj = resutl; Log.i(TAG,"get异步"+resutl); mHandler.sendMessage(msg); } } }); } //异步请求 private void getDataSycPost(){ OkHttpClient client = new OkHttpClient(); Log.i(TAG,"post异步"+"getDataSycPost------getDataSycPost-----------"); //post方式 需要表单提交参数 RequestBody requestBody = new FormBody.Builder() .add("pscid","39") .add("page","1") .build(); Request request = new Request.Builder() .url("http://api.m.mtime.cn/PageSubArea/TrailerList.api") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.i(TAG,"post异步"+"postEnqueue------onFailure-----------"); } @Override public void onResponse(Call call, Response response) throws IOException { Log.d(TAG,"onResponse:"+response.isSuccessful()); if(response.isSuccessful()){//回调的方法执行在子线程。 Log.d(TAG,"getDataSycPost获取数据成功了"); Log.d(TAG," getDataSycPost response.code()=="+response.code()); String resutl = response.body().string(); // Log.d("kwwl","response.body().string()=="+response.body().string()); Message msg = Message.obtain(); msg.what = GET; msg.obj = resutl; Log.i(TAG,"post异步"+resutl); mHandler.sendMessage(msg); } //运行在子线程,, runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"成功", Toast.LENGTH_SHORT).show(); } }); System.out.println("postEnqueue = "+response.body().string()); } }); }
----
//布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.zengjx.okhttpdemo.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_get"
android:text="get请求"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_get2"
android:text="get请求2"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_post"
android:text="post请求"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="okhttp"
android:id="@+id/tv_log"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>