首先新建一个 Android 项目,这个就不用过多介绍了,相信接触过的都有了解,这里不是重点。
网络请求是用 RxJava + Retrofit 实现。使用的是 夜神 模拟器
首先添加依赖
final String support_design_version = "27.1.1"
final String ktx_version = "0.3"
final String constraint_version = "1.1.3"
final String circle_image_version = "2.2.0"
final String glide_version = "4.7.1"
final String rx_android_version = "2.0.2"
final String rx_java_version = "2.1.1"
final String retrofit_version = "2.3.0"
final String logging_version = "3.9.0"
final String leak_canary_version = "1.6.1"
final String paging_version = "1.0.1"
final String lifecycle_version = "1.1.1"
api "com.android.support:appcompat-v7:$support_design_version"
api "com.android.support:appcompat-v7:$support_design_version"
api "com.android.support:support-v4:$support_design_version"
api "com.android.support:design:$support_design_version"
api "com.android.support:cardview-v7:$support_design_version"
api "com.android.support:recyclerview-v7:$support_design_version"
api "com.android.support:gridlayout-v7:$support_design_version"
api "com.android.support.constraint:constraint-layout:$constraint_version"
api "de.hdodenhof:circleimageview:$circle_image_version"
api "android.arch.paging:runtime:$paging_version"
api "android.arch.lifecycle:extensions:$lifecycle_version"
api "androidx.core:core-ktx:$ktx_version"
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
api "com.github.bumptech.glide:glide:$glide_version"
annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"
api "io.reactivex.rxjava2:rxandroid:$rx_android_version"
api "io.reactivex.rxjava2:rxjava:$rx_java_version"
api "com.squareup.retrofit2:retrofit:$retrofit_version"
api "com.squareup.retrofit2:converter-gson:$retrofit_version"
api "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"
api "com.squareup.retrofit2:converter-scalars:$retrofit_version"
api "com.squareup.okhttp3:logging-interceptor:$logging_version"
debugApi "com.squareup.leakcanary:leakcanary-android:$leak_canary_version"
releaseApi "com.squareup.leakcanary:leakcanary-android-no-op:$leak_canary_version"
定义接口
注意哦,这里不是单纯的 Retrofit,还是结合 RxJava 的,所以返回值定义的不是 Call
package com.kuky.base.kotlin.demo.test.api;
import com.kuky.base.kotlin.demo.test.bean.UserInfo;
import io.reactivex.Observable;
import retrofit2.http.POST;
import retrofit2.http.Query;
/**
* author:Jiwenjie
* email:278630464@qq.com
* time:2018/12/13
* desc:
* version:1.0
*/
public interface ApiService {
@POST("user/login")
Observable getLoginUser(@Query("username") String username, @Query("password") String password);
}
UserInfo 实体类
这里定义实体类的时候需要注意,和后台定义的实体类会略有区别,后台的实体类就和数据库的保持一致就行,但是在这里需要加上返回值的状态。因为我们使用 Gson 来自动解析数据,如果不是对应完整的话会解析失败
package com.kuky.base.kotlin.demo.test.bean;
import java.io.Serializable;
import java.util.List;
/**
* author:Jiwenjie
* email:278630464@qq.com
* time:2018/12/14
* desc:
* version:1.0
*/
public class UserInfo implements Serializable {
/**
* {
* "code":200,
* "message":"succeed",
* "user":{
* "id":2,
* "username":"admin",
* "phone":"13965972584",
* "isAdmin":0}
* }
**/
private Integer code;
private String message;
private User user;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public class User implements Serializable {
private Integer id;
private String username;
private String phone;
private int isAdmin;
private String avatar;
private String password;
private List files;
public class UserFile implements Serializable {
private int id;
private String fileName;
private String filePath;
@Override
public String toString() {
return "UserFile{" +
"id=" + id +
", fileName='" + fileName + '\'' +
", filePath='" + filePath + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
}
@Override
public String toString() {
return "User {" +
"id=" + id +
", username='" + username + '\'' +
", phone='" + phone + '\'' +
", isAdmin=" + isAdmin +
", avatar='" + avatar + '\'' +
", password='" + password + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public int getIsAdmin() {
return isAdmin;
}
public void setIsAdmin(int isAdmin) {
this.isAdmin = isAdmin;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List getFiles() {
return files;
}
public void setFiles(List files) {
this.files = files;
}
}
}
Constant 文件,里面的 url 的地址
public class Constans {
public static String BASE_URL = "http://172.16.134.10:8080/";
}
因为我们需要连接本机,所以需要加上 IP 地址,对应这个查询直接 ipconfig 就行
Activity 文件
package com.kuky.base.kotlin.demo.test;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.kuky.base.android.kotlin.RetrofitManager;
import com.kuky.base.kotlin.demo.R;
import com.kuky.base.kotlin.demo.test.api.ApiService;
import com.kuky.base.kotlin.demo.test.bean.UserInfo;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.*;
/**
* author:Jiwenjie
* email:278630464@qq.com
* time:2018/12/13
* desc:测试连接后台部分,查看是否能成功
* version:1.0
*/
@SuppressWarnings("ALL")
public class TestConnectActivity extends AppCompatActivity {
private ProgressDialog progressDialog;
private Button btn;
/** {"code":200,"message":"succeed","user":{"id":2,"username":"admin","phone":"13965972584","isAdmin":0}} **/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
progressDialog = new ProgressDialog(getApplicationContext());
btn = findViewById(R.id.btn_test);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
conn();
}
});
}
/**
* 连接方法
*/
@SuppressLint("CheckResult")
private void conn() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.show();
}
RequestBody body = new FormBody.Builder() //提交表单数据
.add("username", "admin")
.add("password", "123456")
.build();
/**
* RxJava + Retrofit
*/
RetrofitManager.INSTANCE.setBaseUrl(Constans.BASE_URL);
RetrofitManager.INSTANCE.getMRetrofit().create(ApiService.class)
.getLoginUser("admin", "123456")
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(UserInfo userInfo) throws Exception {
Toast.makeText(getApplicationContext(), userInfo.getUser().getUsername(), Toast.LENGTH_LONG).show();
btn.setText(userInfo.getUser().getUsername() + "登陆成功");
}
}, new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(getApplicationContext(), "失败错误", Toast.LENGTH_LONG).show();
}
});
}
}
布局文件就不贴了,只有一个 Button。
之后点击运行
xs17.png
这是刚运行的界面
xs18.png
这是点击运行后的界面。
接下来我们来看下后台的请求显示
xs19.png
讷,从这可以看出前后台彻底打通了。接下来我们就可以搞事情了。
我会在毕设完成前不定期的更新文章总结,希望大家多多指教。代码都会接下来上传到 github 上。目前已经传了后台的代码
前台部分在我规划好正式开始后也会放出。