自己对MVP+Retrofit2+RxJava的理解

说起MVP+Retrofit2+RxJava还是自己来公司之后才了解到的,在此之前学习Java了解使用了MVC,甚知使用之后对于项目的维护和管理有这很大帮助,所以一直想很好的彻底的了解一下在Android中该如何使用,所以自己在网上学习做出了一个简单的栗子,希望对初学的人有所帮助!

前言...简单了解一下MVP,Retrofit2,RxJava各自的在项目中的作用

1.MVP,类似于MVC一种基于Android应用的模式,但稍有一些不同,就记住,Moudel与View不能直接联系就行,而MVC是可以的。

2.Retrofit2,一种网络请求框架,其实我现在也没有明白它的好处,嘿嘿,请见谅!

3.RxJava, 用于异步请求数据。

正文:此demo只是简单的登录、注册,带参传入,访问服务器,以验证正误

先看一下项目结构,该如何放置各个主要类,仅供参考

1.jar包添加

 //网络请求框架
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    //异步请求
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.5'
    //自动注解
    compile 'com.jakewharton:butterknife:7.0.1'

2.先说MVP的设计步骤,布局如下,我就不放XML文件了

这里有一个progressBar是隐藏的,登录注册请求期间显示,成功后隐藏。

1)设置Moudel中的实体类,以便数据的交互,实体类也很简单;

public class LoginResult {
    public long time;
    public long openid;
    public UserBindInfo userBindInfo;
    public int errno;
    public String errmsg;
    public String token;
    public String UserLastLoginTime;

    public class UserBindInfo {
        public String user_is_set_question;
        public String user_is_bind_email;
        public String user_is_bind_phone;


    }
}

2)设置View,就是在Activity中需要哪些返回数据做界面UI更新。

此demo中就是需要访问服务器之后,拿到返回数据来提示用户登录或者注册是否成功;

public interface ILoginView {
    void onLoginResult(LoginResult result);
    void onRegisterResult(RegisterResult result);
    void onSetProgressBarVisibility(int visibility);
}
3)设置Presenter,编写一些在Activity中需要用到的逻辑代码,以减少Activity中的代码臃肿。

此demo中就是处理当点击登录或者注册后向服务器发送请求,和获取返回数据供Activity使用;

接口类:

public interface ILoginPresenter {
    void login(String name, String pass);
    void register(String name, String pass);
}
实现类:

public class LoginPresenterImpl implements ILoginPresenter {
    private ILoginView loginView;
    private Context context;

    public LoginPresenterImpl(Context context, ILoginView loginView) {
        this.loginView = loginView;
        this.context = context;
    }

    @Override
    public void login(String user, String pswd) {
        loginView.onSetProgressBarVisibility(View.VISIBLE);
        //这里就是请求服务器的操作,也可以其他框架处理
        RetrofitManager.getInstance().login(user, pswd, new BaseSubscribe<LoginResult>(context) {
            @Override
            protected void _onNext(LoginResult result) {
                loginView.onLoginResult(result);
                loginView.onSetProgressBarVisibility(View.GONE);
            }

            @Override
            protected void _onError(Throwable e) {
                loginView.onSetProgressBarVisibility(View.GONE);
            }
        });

    }

    @Override
    public void register(String user, String pswd) {
        loginView.onSetProgressBarVisibility(View.VISIBLE);
        RetrofitManager.getInstance().register(user, pswd, new BaseCallback<RegisterResult>(context) {
            @Override
            protected void _onResponse(Response<RegisterResult> response) {
                loginView.onRegisterResult(response.body());
                loginView.onSetProgressBarVisibility(View.GONE);
            }

            @Override
            protected void _onFailure(Throwable e) {
                loginView.onSetProgressBarVisibility(View.GONE);
            }
        });

    }
}
4)MainActivity中的使用

public class MainActivity extends AppCompatActivity implements ILoginView {
    @Bind(R.id.user)
    EditText username;
    @Bind(R.id.pass)
    EditText password;
    @Bind(R.id.login)
    Button login;
    @Bind(R.id.register)
    Button register;
    @Bind(R.id.progress_login)
    RelativeLayout relativeLayout;

    private ILoginPresenter loginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        ButterKnife.bind(this);
        loginPresenter = new LoginPresenterImpl(this, this);
    }

    @OnClick({R.id.login, R.id.register})
    public void onClick(Button button) {
        switch (button.getId()) {
            case R.id.login:
                loginPresenter.login(getUsername(), getPassword());
                break;
            case R.id.register:
                loginPresenter.register(getUsername(), getPassword());
                break;
        }

    }

    private String getUsername() {
        return username.getText().toString();
    }

    private String getPassword() {
        return password.getText().toString();
    }

    @Override
    public void onRegisterResult(RegisterResult result) {
        if (result.errno == 0)
            Toast.makeText(this, "注册成功", Toast.LENGTH_LONG).show();
        else
            Toast.makeText(this, result.errmsg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onLoginResult(LoginResult result) {
        if (result.errno == 0)
            Toast.makeText(this, "登录成功", Toast.LENGTH_LONG).show();
        else
            Toast.makeText(this, result.errmsg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onSetProgressBarVisibility(int visibility) {
        relativeLayout.setVisibility(visibility);
    }

}
MVP的模式大家应该知道了,在看看网络请求操作吧

1)请求第一步必然是URL地址的处理

public interface APIService {
    @FormUrlEncoded
    @POST("rest.php?a=auth")
    Observable<LoginResult> login(@Field("user") String user, @Field("pswd") String pswd, @Field("type") String type);

    @FormUrlEncoded
    @POST("rest.php?a=register")
    Call<RegisterResult> register(@Field("user") String user, @Field("pswd") String pswd, @Field("pswd2") String pswd2, @Field("type") String type);
}
URL地址以及参数的上传处理, 见这里有详细说明

如果使用post请求,请加上

@FormUrlEncoded
@Field

2)retrofit2基础公共类

public class RetrofitManager {
    private static RetrofitManager instance;
    private Retrofit retrofit;
    private APIService service;
    private String baseUrl = "这里大家写入一个自己的baseURL";

    private RetrofitManager() {
        //创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(5, TimeUnit.SECONDS);

        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(httpClientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//如果不使用rxjava可不必添加
                .build();

        service = retrofit.create(APIService.class);
    }

    public static RetrofitManager getInstance() {
        if (instance == null) {
            synchronized (RetrofitManager.class) {
                instance = new RetrofitManager();
            }
        }
        return instance;
    }

    public void login(String user, String pswd, Subscriber<LoginResult> subscriber) {
        service.login(user, Md5.md5(pswd), "random")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

    public void register(String user, String pswd, Callback<RegisterResult> callback) {
        service.register(user, Md5.md5(pswd), Md5.md5(pswd), "random")
                .enqueue(callback);
    }
}
这其中也看到登录和注册请求有所不同,是因为一个使用rxjava,而另一个使用retrofit自带的一个call来处理数据,下面都有具体说明

1.rxjava

 @FormUrlEncoded
    @POST("rest.php?a=auth")
    Observable<LoginResult> login(@Field("user") String user, @Field("pswd") String pswd, @Field("type") String type);
public void login(String user, String pswd, Subscriber<LoginResult> subscriber) {
        service.login(user, Md5.md5(pswd), "random")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }
BaseSubscriber类,因为项目中必然多次用到,不能用一次就编写

public abstract class BaseSubscribe<T> extends Subscriber<T> {
    //用户重写使用,方便获取和发送数据
    protected abstract void _onNext(T t);
    protected abstract void _onError(Throwable e);

    private Context context;

    public BaseSubscribe(Context context) {
        this.context = context;
    }

    @Override
    public void onCompleted() {
        Toast.makeText(context, "获取成功!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(Throwable e) {
        if (e instanceof SocketTimeoutException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else if (e instanceof ConnectException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
            Log.i("error", e.getMessage());
            _onError(e);
        }
    }

    @Override
    public void onNext(T t) {
        _onNext(t);
    }
}
因此在PresenterImpl实现类中的使用:

 RetrofitManager.getInstance().login(user, pswd, new BaseSubscribe<LoginResult>(context) {
            @Override
            protected void _onNext(LoginResult result) {
                loginView.onLoginResult(result);
                loginView.onSetProgressBarVisibility(View.GONE);
            }

            @Override
            protected void _onError(Throwable e) {
                loginView.onSetProgressBarVisibility(View.GONE);
            }
        });
2.retrofit自带call与上述如出一辙,大家可自己模仿编写


这样子说明不知大家对MVP+Retrofit2+RxJava的使用有没有进一步理解,如果还有疑惑,那请再学习其他大神的讲解!!!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值