效果图:
Retrofit 内部封装了okhttp+gson解析,Rxjava用来灵活地切换线程,
先注入依赖:
//retrofit
compile 'com.squareup.retrofit2:retrofit:+'
compile 'com.squareup.retrofit2:converter-gson:+'
//Rxjava2
compile 'io.reactivex.rxjava2:rxjava:+'
compile 'io.reactivex.rxjava2:rxandroid:+'
//让retrofit支持Rxjava2
compile 'com.squareup.retrofit2:adapter-rxjava2:+'
//黄油刀butterKnife
annotationProcessor 'com.jakewharton:butterknife-compiler:+'
compile 'com.jakewharton:butterknife:+'
//EventBus
compile 'org.greenrobot:eventbus:+'//eventBus引用
最后注册清单,记得加网络权限和跳转的activity:
<uses-permission android:name="android.permission.INTERNET"/>
<activity android:name=".SecondActivity"/>
项目结构图:
首先是RetrofitManager 的工具类:
public class RetrofitManager {
//这个接口后期可以写个公共类的属性
public static final String BASE_URL = "http://120.27.23.105/";
private final Retrofit mRetrofit;
public static class SINGLE_HOLDER {
public static final RetrofitManager INSTANCE = new RetrofitManager(BASE_URL);
}
public static RetrofitManager getInstance() {
return SINGLE_HOLDER.INSTANCE;
}
private RetrofitManager(String baseUrl) {
mRetrofit = buildRetrofit();
}
private OkHttpClient buildOkHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.build();
}
private Retrofit buildRetrofit() {
return new Retrofit.Builder()
.client(buildOkHttpClient())
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
public <T> T create(Class<T> clazz) {
return mRetrofit.create(clazz);
}
}
然后是请求网络接口的方法类RetrofitAPIs:
public interface RetrofitAPIs {
//get
// 用@Query修饰拼接参数
// @GET("user/login")
// Observable<LoginBean> login(@Query("mobile") String mobile, @Query("password") String password);
//post
@FormUrlEncoded
@POST("user/login")
Observable<LoginBean> login(@Field("mobile") String mobile, @Field("password") String password);
}
bean类:
public class LoginBean {
/**
* msg : 登录成功
* code : 0
* data : {"age":null,"appkey":"679455a233086e26","appsecret":"F259D879B03CCA7C403B9A90A5B8F41A","createtime":"2018-01-03T09:57:35","email":null,"fans":null,"follow":null,"gender":null,"icon":null,"latitude":null,"longitude":null,"mobile":"17600044511","money":null,"nickname":null,"password":"7F14BAAF818358E25E2D9C5259AA47DD","praiseNum":null,"token":"2F8EBE49EE227C2017C470689C62E524","uid":3881,"userId":null,"username":"17600044511"}
*/
private String msg;
private String code;
private DataBean data;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public static class DataBean {
/**
* age : null
* appkey : 679455a233086e26
* appsecret : F259D879B03CCA7C403B9A90A5B8F41A
* createtime : 2018-01-03T09:57:35
* email : null
* fans : null
* follow : null
* gender : null
* icon : null
* latitude : null
* longitude : null
* mobile : 17600044511
* money : null
* nickname : null
* password : 7F14BAAF818358E25E2D9C5259AA47DD
* praiseNum : null
* token : 2F8EBE49EE227C2017C470689C62E524
* uid : 3881
* userId : null
* username : 17600044511
*/
private Object age;
private String appkey;
private String appsecret;
private String createtime;
private Object email;
private Object fans;
private Object follow;
private Object gender;
private Object icon;
private Object latitude;
private Object longitude;
private String mobile;
private Object money;
private Object nickname;
private String password;
private Object praiseNum;
private String token;
private int uid;
private Object userId;
private String username;
public Object getAge() {
return age;
}
public void setAge(Object age) {
this.age = age;
}
public String getAppkey() {
return appkey;
}
public void setAppkey(String appkey) {
this.appkey = appkey;
}
public String getAppsecret() {
return appsecret;
}
public void setAppsecret(String appsecret) {
this.appsecret = appsecret;
}
public String getCreatetime() {
return createtime;
}
public void setCreatetime(String createtime) {
this.createtime = createtime;
}
public Object getEmail() {
return email;
}
public void setEmail(Object email) {
this.email = email;
}
public Object getFans() {
return fans;
}
public void setFans(Object fans) {
this.fans = fans;
}
public Object getFollow() {
return follow;
}
public void setFollow(Object follow) {
this.follow = follow;
}
public Object getGender() {
return gender;
}
public void setGender(Object gender) {
this.gender = gender;
}
public Object getIcon() {
return icon;
}
public void setIcon(Object icon) {
this.icon = icon;
}
public Object getLatitude() {
return latitude;
}
public void setLatitude(Object latitude) {
this.latitude = latitude;
}
public Object getLongitude() {
return longitude;
}
public void setLongitude(Object longitude) {
this.longitude = longitude;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Object getMoney() {
return money;
}
public void setMoney(Object money) {
this.money = money;
}
public Object getNickname() {
return nickname;
}
public void setNickname(Object nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Object getPraiseNum() {
return praiseNum;
}
public void setPraiseNum(Object praiseNum) {
this.praiseNum = praiseNum;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public Object getUserId() {
return userId;
}
public void setUserId(Object userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
@Override
public String toString() {
return "LoginBean{" +
"msg='" + msg + '\'' +
", code='" + code + '\'' +
", data=" + data +
'}';
}
}
第一个布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher_round" />
</LinearLayout>
<EditText
android:id="@+id/edt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"/>
<EditText
android:id="@+id/edt_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"/>
<Button
android:id="@+id/login_But"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登陆"/>
<TextView
android:id="@+id/new_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新用户"/>
</LinearLayout>
第二个布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_marginTop="20dp">
<Button
android:id="@+id/copy_but"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="接收数据"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_marginTop="30dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账号:"
android:textColor="@color/colorAccent"
android:textSize="22sp"/>
<TextView
android:id="@+id/copy_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="XXXX"
android:layout_marginLeft="10dp"
android:textSize="22sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textColor="@color/colorAccent"
android:textSize="22sp"/>
<TextView
android:id="@+id/copy_pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="XXXX"
android:layout_marginLeft="10dp"
android:textSize="22sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
其次是view层定义接口,接口里面定义:登录成功(LoginSurccess)和登录失败(LoginFaild)的抽象方法:
public interface LoginIView {
void LoginSurccess(LoginBean loginBean);
void LoginFaild(Throwable e);
}
Model层:
public class LoginIModel {
public Observable<LoginBean> login(String name, String pass) {
RetrofitAPIs retrofitAPIs = RetrofitManager.getInstance().create(RetrofitAPIs.class);
return retrofitAPIs.login(name, pass);
}
}
presenter层IPresenter是基类公共的可以在任何项目中通用:
public abstract class IPresenter<T extends IView> {
protected T view;
public IPresenter(T view) {
this.view = view;
init();
}
protected abstract void init();
}
再就是LoginPresenter类:
public class LoginIPresenter extends IPresenter<LoginIView>{
private LoginIModel loginIModel;
private Observable<LoginBean> observableLogin;
public LoginIPresenter(LoginIView view) {
super(view);
}
@Override
protected void init() {
loginIModel = new LoginIModel();
}
public void login(String name,String pass){
observableLogin = loginIModel.login(name, pass);
observableLogin.subscribeOn(Schedulers.io())
.subscribe(new Consumer<LoginBean>() {
@Override
public void accept(LoginBean loginBean) throws Exception {
view.LoginSurccess(loginBean);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
view.LoginFaild(throwable);
}
});
}
}
MainActivity类:
public class MainActivity extends AppCompatActivity implements LoginIView {
@BindView(R.id.edt_name)
EditText edtName;
@BindView(R.id.edt_pass)
EditText edtPass;
@BindView(R.id.login_But)
Button loginBut;
@BindView(R.id.new_user)
TextView newUser;
private LoginIPresenter loginIPresenter;
private String pass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
loginIPresenter = new LoginIPresenter(this);
}
@OnClick(R.id.login_But)
public void onLoginButClicked() {
String name = edtName.getText().toString();
pass = edtPass.getText().toString();
loginIPresenter.login(name, pass);
}
@OnClick(R.id.new_user)
public void onNewUserClicked() {
Toast.makeText(this, "等待完善...", Toast.LENGTH_SHORT).show();
}
@Override
public void LoginSurccess(LoginBean loginBean) {
EventBus.getDefault().postSticky(loginBean);
Log.e("+++++++++++++++++++", "访问数据:" + "/rn" + loginBean.toString());
if (loginBean.getCode().equals("0")) {
startActivity(new Intent(this, SecondActivity.class));
}
}
@Override
public void LoginFaild(Throwable e) {
Log.e("+++++++++++++++++++", "登录失败,失败原因:" + "/rn" + e.getMessage().toString());
}
}
第二个activity:
public class SecondActivity extends Activity {
@BindView(R.id.copy_but)
Button copyBut;
@BindView(R.id.copy_name)
TextView copyName;
@BindView(R.id.copy_pass)
TextView copyPass;
private LoginBean.DataBean data;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
ButterKnife.bind(this);
EventBus.getDefault().register(this);
}
//EventBus的具体事件
@Subscribe(sticky = true) //形容接受的方法 , 接受的方法的方法名字自定义,参数是 bean类
public void saveEventBus1(LoginBean loginBean) {
Toast.makeText(this, "接受到了", Toast.LENGTH_SHORT).show();
data = loginBean.getData();
copyName.setText(data.getMobile());
copyPass.setText(data.getPassword());
}
//销毁EventBus
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@OnClick(R.id.copy_but)
public void onViewClicked() {
copyName.setText(data.getMobile());
copyPass.setText(data.getPassword());
}
}
有些匆忙,回头再做修改