依赖
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'io.reactivex.rxjava2:rxjava:2.1.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.facebook.fresco:fresco:0.12.0'
compile 'com.jakewharton:butterknife:8.8.1'
compile 'org.greenrobot:eventbus:3.1.1'
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'com.android.support:design:+'
接口
public interface ApiService { //注册接口 @GET("user/reg") Flowable<RegisteBean> getRegist(@QueryMap Map<String,String> map); //登录接口 @GET("user/login") Flowable<LoginBean> getLogin(@QueryMap Map<String,String> map); //商品列表https://www.zhaoapi.cn/product/getProducts?pscid=39&page=1 @GET("product/getProducts") Flowable<GoodsListBean> getGoodsList(@QueryMap Map<String,String> map); //商品详情https://www.zhaoapi.cn/product/getProductDetail @GET("product/getProductDetail") Flowable<GoodsDetailBean> getGoodsDetail(@QueryMap Map<String,String> map); //添加购物车http://120.27.23.105/product/addCart @GET("product/addCart") Flowable<AddBean> getAdd(@QueryMap Map<String,String> map); //购物车http://120.27.23.105/product/getCarts @GET("product/getCarts") Flowable<CartBean> getCart(@QueryMap Map<String,String> map); //删除购物车 @GET("product/deleteCart") Flowable<Delete> getDelete(@QueryMap Map<String,String> map); }
UtilsM层接口public class RetrofitUtils { private static volatile RetrofitUtils instance; public ApiService getApiService() { return apiService; } private final ApiService apiService; public static RetrofitUtils getInstance(String url){ if (instance==null){ synchronized (RetrofitUtils.class){ if (instance==null){ instance=new RetrofitUtils(url); } } } return instance; } private RetrofitUtils(String url){ Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(url) .build(); apiService = retrofit.create(ApiService.class); } }
登录M层public interface IModel { void getData(Map<String,String> map, String url); }
P层接口public class LoginModel implements IModel{ private LoginPresenter loginPresenter; public LoginModel(LoginPresenter loginPresenter){ this.loginPresenter=loginPresenter; } @Override public void getData(Map<String, String> map, String url) { Flowable<LoginBean> flowable = RetrofitUtils.getInstance(url).getApiService().getLogin(map); loginPresenter.getNews(flowable); } }
登录P层public interface BasePresenter { void getData(Map<String,String> map, String url); }
public class LoginPresenter implements BasePresenter { private IView iView; private DisposableSubscriber subscriber; public void attachView(IView iView){ this.iView=iView; } public void detachView(){ if (iView!=null){ iView=null; } if (subscriber!=null){ if (!subscriber.isDisposed()){ subscriber.dispose(); } } } public void getNews(Flowable<LoginBean> flowable){ subscriber = (DisposableSubscriber)flowable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSubscriber<LoginBean>() { @Override public void onNext(LoginBean listNewsBean) { // if (listNewsBean != null) { iView.onSuccessed(listNewsBean); // } } @Override public void onError(Throwable t) { iView.onFailed(new Exception(t)); } @Override public void onComplete() { } }); } @Override public void getData(Map<String, String> map, String url) { LoginModel model = new LoginModel(this); model.getData(map,url); } }
注册M层
public class RegistModel implements IModel{ private RegistPresenter newsPresenter; public RegistModel(RegistPresenter newsPresenter){ this.newsPresenter=newsPresenter; } @Override public void getData(Map<String, String> map, String url) { Flowable<RegisteBean> flowable = RetrofitUtils.getInstance(url).getApiService().getRegist(map); newsPresenter.getNews(flowable); } }
public class RegistPresenter implements BasePresenter { private IView iView; private DisposableSubscriber subscriber; public void attachView(IView iView){ this.iView=iView; } public void detachView(){ if (iView!=null){ iView=null; } if (subscriber!=null){ if (!subscriber.isDisposed()){ subscriber.dispose(); } } } public void getNews(Flowable<RegisteBean> flowable){ subscriber = (DisposableSubscriber)flowable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSubscriber<RegisteBean>() { @Override public void onNext(RegisteBean listNewsBean) { // if (listNewsBean != null) { iView.onSuccessed(listNewsBean); // } } @Override public void onError(Throwable t) { iView.onFailed(new Exception(t)); } @Override public void onComplete() { } }); } @Override public void getData(Map<String, String> map, String url) { RegistModel model = new RegistModel(this); model.getData(map,url); } }
V层接口
beanpublic interface IView { void onSuccessed(Object o); void onFailed(Exception e); }
public class LoginBean { /** * msg : 天呢!密码错误 * code : 1 */ private String msg; private String code; 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 class RegisteBean { /** * msg : 注册成功 * code : 0 */ private String msg; private String code; 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; } }
登录布局
注册布局<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/img_logo" android:src="@drawable/logo" android:layout_width="match_parent" android:layout_height="300dp" /> <EditText android:layout_below="@id/img_logo" android:id="@+id/ed_phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入手机号" /> <EditText android:id="@+id/ed_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberPassword" android:hint="请输入密码" android:layout_below="@+id/ed_phone" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Button android:id="@+id/btn_login" android:layout_below="@id/ed_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="登录" /> <Button android:id="@+id/btn_regis" android:layout_below="@id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#f67017"> <ImageView android:id="@+id/img_back" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/leftjiantou" /> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="新用户注册界面" /> </LinearLayout> <EditText android:id="@+id/ed_phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入手机号"/> <EditText android:id="@+id/ed_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:inputType="numberPassword"/> <Button android:id="@+id/btn_regis" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册" android:layout_marginBottom="169dp" android:layout_alignParentBottom="true" /> </LinearLayout>
登录注册public class MainActivity extends AppCompatActivity implements IView { @BindView(R.id.img_logo) ImageView imgLogo; @BindView(R.id.ed_phone) EditText edPhone; @BindView(R.id.ed_pass) EditText edPass; @BindView(R.id.btn_login) Button btnLogin; @BindView(R.id.btn_regis) Button btnRegis; private LoginPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick({R.id.btn_login, R.id.btn_regis}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_login: String user = edPhone.getText().toString().trim(); String pass = edPass.getText().toString().trim(); presenter = new LoginPresenter(); presenter.attachView(this); HashMap<String, String> map = new HashMap<>(); map.put("mobile",user); map.put("password",pass); if (checkData(user,pass)){ presenter.getData(map,"http://120.27.23.105/"); } break; case R.id.btn_regis: //跳到注册页面 startActivity(new Intent(MainActivity.this,RegisActivity.class)); break; } } public boolean checkData(String phone,String pass) { if(TextUtils.isEmpty(phone)||TextUtils.isEmpty(pass)){ Toast.makeText(MainActivity.this,"用户名或密码不能为空",Toast.LENGTH_SHORT).show(); return false; } //验证是否为手机号的正则表达式 String regex = "^1[3|4|5|7|8]\\d{9}"; if(!Pattern.matches(regex,phone)){ Toast.makeText(MainActivity.this,"手机号格式不正确",Toast.LENGTH_SHORT).show(); return false; } // if(pass.length()<6){ // Toast.makeText(MainActivity.this,"密码长度需要大于6位",Toast.LENGTH_SHORT).show(); // return false; // } return true; } @Override public void onSuccessed(Object o) { LoginBean loginBean= (LoginBean) o; if (loginBean.getCode().equals("0")){ //登录成功跳转到商品列表页面 startActivity(new Intent(MainActivity.this,GoodsListActivity.class)); }else { Toast.makeText(MainActivity.this,loginBean.getMsg(),Toast.LENGTH_SHORT).show(); } } @Override public void onFailed(Exception e) { //正常情况不会执行,只有请求网络失败的时候才会执行,这里的失败是指网页打不开的失败 Toast.makeText(MainActivity.this,"网络异常,登录失败",Toast.LENGTH_SHORT).show(); } //防止内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (presenter!=null){ presenter.detachView(); } } }
public class RegisActivity extends AppCompatActivity implements IView { @BindView(ed_phone) EditText edPhone; @BindView(ed_pass) EditText edPass; @BindView(R.id.btn_regis) Button btnRegis; @BindView(R.id.img_back) ImageView imgBack; private RegistPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_regis); ButterKnife.bind(this); } @OnClick({R.id.btn_regis, R.id.img_back}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_regis: String user = edPhone.getText().toString().trim(); String pass = edPass.getText().toString().trim(); presenter = new RegistPresenter(); presenter.attachView(this); HashMap<String, String> map = new HashMap<>(); map.put("mobile",user); map.put("password",pass); if (checkData(user,pass)){ presenter.getData(map,"http://120.27.23.105/"); } break; case R.id.img_back: Toast.makeText(RegisActivity.this,"再次点击退出应用程序",Toast.LENGTH_SHORT).show(); break; } } public boolean checkData(String phone,String pass) { if(TextUtils.isEmpty(phone)||TextUtils.isEmpty(pass)){ Toast.makeText(RegisActivity.this,"用户名或密码不能为空",Toast.LENGTH_SHORT).show(); return false; } //验证是否为手机号的正则表达式 String regex = "^1[3|4|5|7|8]\\d{9}"; if(!Pattern.matches(regex,phone)){ Toast.makeText(RegisActivity.this,"手机号格式不正确",Toast.LENGTH_SHORT).show(); return false; } if(pass.length()<6){ Toast.makeText(RegisActivity.this,"密码长度需要大于6位",Toast.LENGTH_SHORT).show(); return false; } return true; } @Override public void onSuccessed(Object o) { finish(); } @Override public void onFailed(Exception e) { } //防止内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (presenter!=null){ presenter.detachView(); } } }