网络框架Retrofit(一)--了解封装的Okhttp
对于网络框架,一直都处于一知半解的状态,所以除了基本的应用之外,怎么延伸都不知从何下手,于是,我就抽时间进一步的去了解:
众所周知,retrofit是对okhttp进行封装,而retrofit只是简单的去使用okhttp的框架,但是想更深入了解网络请求,建议还是先从okhttp进行了解,所以下面我会先去了解okhttp:
1、导入okhttp:
访问https://github.com/square/okhttp
获取最新版本的okhttp,进入项目的build.gradle添加依赖
2、根据官网的提示去使用okhttp
image.png
发现出现这样的报错,那是因为最新的okhttp要求的最低版本是21以及jdk版本为8.0,解决方案如下:
image.png
顺便说下怎么找到对应的配置方法,可以在官网里面看到作者写的android-text文档,然后点开他的build.gradle,就可以看到作者是怎么配置,那样就可以拿到最新的配置。
还有需要说明下:因为android9.0及以上的版本会默认不予许直接方法http的,因为官网觉得这样不安全,所以需要做如下的配置:
①访问官网:
https://developer.android.com/training/articles/security-config
然后往下面拉的话,就会看到各种证书的添加方法,我就直接上我的吧:
<network-security-config>
<base-config cleartextTrafficPermitted="true">//支持访问HTTP协议的
<trust-anchors>
<certificates src="system" />//信任系统里面内置的CA证书
<certificates src="user" />//信任用户自己安装的证书,这个是为了抓包软件可以正常工作,记得还要安装抓包的插件
</trust-anchors>
</base-config>
</network-security-config>
3、添加okhttp拦截器,打印我们构造出来的请求和已接收到结果,在官网中okhttp-logging-interceptor这个文档中就可以看到怎添加使用
然后下面就直接上代码了,代码细节都写在里面,好好看哈:
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.retrofit"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation("com.squareup.okhttp3:okhttp:4.8.1")
implementation("com.squareup.okhttp3:logging-interceptor:4.8.1")
}
INetCallBack
public interface INetCallBack {
void onSuccess(String response);
void onFailed(Throwable ex);
}
OkhttpUtils
public class OkhttpUtils {
private OkHttpClient client;
private OkhttpUtils(){
//添加拦截器
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.d("jeffrey",message);
}
});
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder()
.addInterceptor(new AuthIntercetor())
.addInterceptor(logging)
.build();
}
private static OkhttpUtils sInstance=new OkhttpUtils();
//对外公开一个获取方法
public static OkhttpUtils getInstance(){
return sInstance;
}
private Handler mUiHandler=new Handler(Looper.getMainLooper());
/* //同步请求
public String doGet(String url){
try {
//1、构造OkHttpClient对象;
OkHttpClient client=new OkHttpClient();
//2.通过Request.Builder()去构造Request对象;
Request request=new Request.Builder()
.url(url)
.build();
//3、通过Request对象去拿到Call对象;
Call call=client.newCall(request);
//4.通过Call对象执行去拿到Response对象
Response response = call.execute();
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}*/
//异步请求
public void doGet(String url,HashMap<String,String> headers,INetCallBack callBack){
//添加请求头信息
Request.Builder builder=new Request.Builder();
if (headers !=null){
for (String key:headers.keySet()){
builder.addHeader(key,headers.get(key));
}
}
Request request=builder
.url(url)
.build();
executeRequest(callBack, request);
}
//注意下POST请求的参数不是接到url后面的,所以需要参数2
public void doPost(String url, HashMap<String,String> headers,HashMap<String,String> params,INetCallBack callBack){
FormBody.Builder formBodyBuilder=new FormBody.Builder();
if (params!=null){
for (String param:params.keySet()){
formBodyBuilder.add(param,params.get(param));
}
}
Request.Builder requsetBuilder=new Request.Builder();
if (headers !=null){
for (String key:headers.keySet()){
requsetBuilder.addHeader(key,headers.get(key));
}
}
Request request = requsetBuilder
.url(url)
.post(formBodyBuilder.build())
.build();
executeRequest(callBack, request);
}
public void doPostMultiPart(String url,HashMap<String,String> headers, HashMap<String,String> params,INetCallBack callBack){
MultipartBody.Builder multipartBodyBuilder=new MultipartBody.Builder();
multipartBodyBuilder.setType(MultipartBody.FORM);
if (params!=null){
for (String param:params.keySet()){
multipartBodyBuilder.addFormDataPart(param,params.get(param));
}
}
Request.Builder requsetBuilder=new Request.Builder();
if (headers !=null){
for (String key:headers.keySet()){
requsetBuilder.addHeader(key,headers.get(key));
}
}
Request request=requsetBuilder
.url(url)
.post(multipartBodyBuilder.build())
.build();
executeRequest(callBack, request);
}
public void doPostJson(String url,HashMap<String,String> headers,String jsonStr,INetCallBack callBack){
//MediaType代表jSon字符串所含的格式
MediaType jsonMediaType=MediaType.get("application/json");
RequestBody requestBody=RequestBody.create(jsonStr,jsonMediaType);
Request.Builder requsetBuilder=new Request.Builder();
if (headers !=null){
for (String key:headers.keySet()){
requsetBuilder.addHeader(key,headers.get(key));
}
}
Request request=requsetBuilder
.url(url)
.post(requestBody)
.build();
executeRequest(callBack, request);
}
private void executeRequest(INetCallBack callBack, Request request) {
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onFailed(e);
}
});
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//注意response.body().string()也是耗时操作,所以要拿出来
String respStr = null;
try {
respStr = response.body().string();
} catch (IOException e) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onFailed(e);
}
});
return;
}
String finalRespStr = respStr;
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onSuccess(finalRespStr);
}
});
}
});
}
}
AuthIntercetor
public class AuthIntercetor implements Interceptor {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request originRequest=chain.request();
Request newRequest=originRequest.newBuilder()
.addHeader("author","jeffrey")
.build();
return chain.proceed(newRequest);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private Button mBtnGet,mBtnPost,mBtnPostMultipart,mBtnPostJson;
private TextView mTvContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initEvents();
}
private void initEvents() {
mBtnGet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<String,String> headers=new HashMap<>();
headers.put("author_headr","jeffer");
OkhttpUtils.getInstance()
.doGet("",headers, new INetCallBack() {
@Override
public void onSuccess(String response) {
mTvContent.setText(response);
}
@Override
public void onFailed(Throwable ex) {
Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
}
});
/* //发送网络请求
new Thread(){
@Override
public void run() {
super.run();
String content=OkhttpUtils.getInstance().
doGet("");
mUiHandler.post(new Runnable() {
@Override
public void run() {
mTvContent.setText(content);
}
});
}
}.start();*/
}
});
mBtnPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<String,String> headers=new HashMap<>();
headers.put("author_headr","jeffer");
HashMap<String,String> params=new HashMap<>();
params.put("author","jeffrey");
params.put("abc","xyz");
OkhttpUtils.getInstance().doPost("", headers,null, new INetCallBack() {
@Override
public void onSuccess(String response) {
mTvContent.setText(response);
}
@Override
public void onFailed(Throwable ex) {
Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
}
});
}
});
mBtnPostMultipart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<String,String> headers=new HashMap<>();
headers.put("author_headr","jeffer");
HashMap<String,String> params=new HashMap<>();
params.put("author","jeffrey");
params.put("abc","xyz");
OkhttpUtils.getInstance().doPostMultiPart("", headers,null, new INetCallBack() {
@Override
public void onSuccess(String response) {
mTvContent.setText(response);
}
@Override
public void onFailed(Throwable ex) {
Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
}
});
}
});
mBtnPostJson.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<String,String> headers=new HashMap<>();
headers.put("author_headr","jeffer");
OkhttpUtils.getInstance().doPostJson("", headers,"{\"name\":\"jeffrey\",\"age\":18}", new INetCallBack() {
@Override
public void onSuccess(String response) {
mTvContent.setText(response);
}
@Override
public void onFailed(Throwable ex) {
Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
}
});
}
});
}
private void initViews() {
mBtnGet=findViewById(R.id.bt_get);
mTvContent=findViewById(R.id.tv_content);
mBtnPost=findViewById(R.id.bt_post);
mBtnPostMultipart=findViewById(R.id.bt_post_multipart);
mBtnPost=findViewById(R.id.bt_post_json);
}
}
这里我小结一下:
1、其实从开头就开始说如何从文档中读取使用方法,是建议大家真的多去官网看文档,因为很多时候看别人的文章,都是别人总结好的东西,很难去了解所用的框架后面怎么去拓展,所以,最好还是以官网的文档使用为准会比较好;
2、okttp的使用步骤其实就是:
①、构造OkHttpClient对象;
②、通过Request.Builder()去构造Request对象;
③、通过Request对象去拿到Call对象;
④、通过Call对象执行去拿到Response对象
好啦!下一章,我会说下Retrofit的用法,然后进行对比,尽量让大家可以一眼就看透他们的对比性,觉得写得可以话,请关注和点赞哦!!