一.原理:
· 大概原理
通过java接口以及注解来描述网络请求,并用动态代理的方式,在调用接口方法前后(before/after)注入自己的方法,before通过接口方法和注解生成网络请求的request,after通过client调用相应的网络框架(默认okhttp)去发起网络请求,并将返回的response通过converterFactorty转换成相应的数据model,最后通过calladapter转换成其他数据方式(如rxjava Observable)
· 动态代理
代理对象拦截真实对象的方法调用,在真实对象调用前/后实现自己的逻辑调用
见Retrofit.create()方法
· 重点类
1.Retrofit类 创建接口api的动态代理对象(create()返回api service动态代理对象,调用代理对象上的方法时,会触发代理对象上的invoke方法,这里面会封装好OKHttpCall对象,OKHttpCall的数据返回根据calladapter转换为Observable)
2.ServiceMethod 核心处理类,解析方法和注解,生成HttpRequest(toRequest方法;创建responseConverter(将response流转换为String或者实体类); 创建callAdapter(转换为rxjava observable)
3.OKHttpCall 封装okhttp3的调用
4.Rxjava2CallAdapter 转换成Observable (BodyObservable会对http code做检查,如果错误直接走onError流程)
原理链接:https://blog.youkuaiyun.com/ActiveLi/article/details/80610031
案例
1.导入依赖
//RxJava依赖
implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
//Retrofit依赖
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
//Gson converter gson解析
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//RxJava2 Adapter
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
//okhttp
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
2.添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
3.API接口
public interface API {
@FormUrlEncoded
@POST("register")
Observable<UserEntity> getResisterData2(@FieldMap HashMap<String,String> hashMap);
@FormUrlEncoded
@POST("login")
Observable<UserEntity> getLoginData2(@FieldMap HashMap<String,String> hashMap);
}
封装RetrofitManager
package com.example.a12_11lx_retrofit;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitManager2 {
private RetrofitManager2(){
}
private static RetrofitManager2 retrofitManager2 =new RetrofitManager2();
public static RetrofitManager2 getInstance(){
return retrofitManager2;
}
Retrofit retrofit;
public void create(){
retrofit =new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/user/")
.client(new OkHttpClient.Builder()
.writeTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.connectTimeout(1,TimeUnit.MINUTES)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("appversion", "1.0").build();
return chain.proceed(request);
}
})
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
public Retrofit getRetrofit(){
if (retrofit ==null){
create();
}
return retrofit;
}
}
实体类UserEntity
package com.example.a12_11lx_retrofit;
import java.util.List;
public class UserEntity {
@Override
public String toString() {
return "UserEntity{" +
"data=" + data +
", errorCode=" + errorCode +
", errorMsg='" + errorMsg + '\'' +
'}';
}
/**
* admin : false
* chapterTops : []
* coinCount : 0
* collectIds : []
* email :
* icon :
* id : 116924
* nickname : zang11111
* password :
* publicName : zang11111
* token :
* type : 0
* username : zang11111
*/
private DataBean data;
/**
* data : {"admin":false,"chapterTops":[],"coinCount":0,"collectIds":[],"email":"","icon":"","id":116924,"nickname":"zang11111","password":"","publicName":"zang11111","token":"","type":0,"username":"zang11111"}
* errorCode : 0
* errorMsg :
*/
private int errorCode;
private String errorMsg;
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public static class DataBean {
private boolean admin;
private int coinCount;
private String email;
private String icon;
private int id;
private String nickname;
private String password;
private String publicName;
private String token;
private int type;
private String username;
private List<?> chapterTops;
private List<?> collectIds;
@Override
public String toString() {
return "DataBean{" +
"admin=" + admin +
", coinCount=" + coinCount +
", email='" + email + '\'' +
", icon='" + icon + '\'' +
", id=" + id +
", nickname='" + nickname + '\'' +
", password='" + password + '\'' +
", publicName='" + publicName + '\'' +
", token='" + token + '\'' +
", type=" + type +
", username='" + username + '\'' +
", chapterTops=" + chapterTops +
", collectIds=" + collectIds +
'}';
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public int getCoinCount() {
return coinCount;
}
public void setCoinCount(int coinCount) {
this.coinCount = coinCount;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPublicName() {
return publicName;
}
public void setPublicName(String publicName) {
this.publicName = publicName;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<?> getChapterTops() {
return chapterTops;
}
public void setChapterTops(List<?> chapterTops) {
this.chapterTops = chapterTops;
}
public List<?> getCollectIds() {
return collectIds;
}
public void setCollectIds(List<?> collectIds) {
this.collectIds = collectIds;
}
}
}
布局
<?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:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:hint="账号"
android:id="@+id/ed_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"></EditText>
<EditText
android:inputType="textPassword"
android:hint="密码"
android:id="@+id/ed_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"></EditText>
<EditText
android:inputType="textPassword"
android:hint="再次输入密码"
android:id="@+id/ed_repassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"></EditText>
<Button
android:id="@+id/login"
android:text="登录"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
</LinearLayout>
MainActivity
package com.example.a12_11lx_retrofit;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
public class MainActivity extends AppCompatActivity {
private EditText edUsername;
private EditText edPassword;
private Button login;
private EditText edRepassword;
String username;
String password;
String repassword;
HashMap<String, String> hashMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
username = edUsername.getText().toString();
password = edPassword.getText().toString();
repassword = edRepassword.getText().toString();
hashMap = new HashMap<>();
hashMap.put("username", "jialichao12");
hashMap.put("password", "jialichao12");
hashMap.put("repassword","jialichao12");
//注册
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RetrofitManager2.getInstance().getRetrofit().create(API.class)
.getResisterData2(hashMap)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserEntity userEntity) {
System.out.println("========"+userEntity);
int errorCode = userEntity.getErrorCode();
if (errorCode==0){
Toast.makeText(MainActivity.this,"注册成功",Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.this,LoginActivity.class));
}else {
Toast.makeText(MainActivity.this,userEntity.getErrorMsg(),Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
});
}
private void initView() {
edUsername = (EditText) findViewById(R.id.ed_username);
edPassword = (EditText) findViewById(R.id.ed_password);
login = (Button) findViewById(R.id.login);
edRepassword = (EditText) findViewById(R.id.ed_repassword);
}
}