要说起为什么要用这个东西,主要是因为刚刚开始做项目的时候没有什么框架的概念,对代码质量的要求也不高,完全就是为了赶进度,所以写出来的代码可读性差,也在于最近项目没什么需求了,所以想着把代码重构一下,让他至少看上去很美。
看来看去还是先重构网络请求这一块吧,以前网络这块用的是Volley,Volley确实很简单,封装的非常不错,项目里面的网络请求是完全可以满足的,唯一的不好就是感觉会慢一些。
这个只说说在项目中怎么用,想知道原理的同学可以去看看流程。
先说说Refrofit吧,我们要写一个接口类,把网络请求管理起来
public interface HttpServiceApi {
@POST("user/login")
Observable<UserBean> getPin(@Body Map<Object, Object> params, @Path("path") String path);
@POST("{path}/{name}")
Observable<UserBean> loginCookies(@Body Map<Object, Object> params, @Path("path") String path,@Path("name") String name);
@POST("{path}/{name}")
Observable<VersionBean> checkVersion(@Body Map<Object, Object> params, @Path("path") String path, @Path("name") String name);
}
简单说一下把,@POST对应的就是http中的post方法,同样的也有get方法,我们项目中没有使用到get方法,所以这里就没有写get的方法,@Body也就是你要传给服务器的数据,上面的{path}{name}对应下面的方法中的@Path参数,也就是服务端的接口名称,注意在使用@get方法中是不能有@Body的,get方法是不能带Body的。
OK,请求数据接口写好了,然后就是要建立连接了,首先封装Retrofit对应方法:
public class DemoRetrofit {
public static <T> T create(final Class<T> cls,String webSite,OkHttpClient okHttpClient) {
Retrofit.Builder builder = new Retrofit.Builder();
Retrofit retrofit = builder
.baseUrl(webSite)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build();
return retrofit.create(cls);
}
}
稍微说一下baseUrl就是域名,GsonConverterFactory.create()用来Gson解析,okHttpClient使用OKHttp,主要是为了获得cookies,怎么样获得后面继续
OK,现在开始使用Retrofit,先写一个抽象的BaseActivity
public abstract class BaseActivity extends Activity {
Observable<String> addOb;
DemoApiService demoApiService ;
protected void onCreate(Bundle onSaveStateInstance){
super.onCreate(onSaveStateInstance);
demoApiService = DemoRetrofit.create(DemoApiService.class, "http://****.com/****server/", DemoOkHttpClientBuilder.genericClient(getApplicationContext()));
}
@Override
protected void onStart(){
super.onStart();
initView();
initOnClickListener();
}
@Override
protected void onResume(){
super.onResume();
addOb = DemoRxBus.get().register("addFeedTag", String.class);
}
public abstract void initView();
public abstract void initOnClickListener();
@Override
protected void onStop(){
super.onStop();
DemoRxBus.get().unregister("addFeedTag", addOb);
}
public void superStatActivity(Intent intent,Bundle bundle){
startActivity(intent.putExtra("bundleData",bundle));
}
}
上面的代码清楚的显示了实例化了一个网络请求对象,但是里面有一个DemoOkHttpClientBuilder.genericClient(getApplicationContext()),这是什么鬼东西,看看下面的代码就知道了,
public class DemoOkHttpClientBuilder {
public static OkHttpClient genericClient(Context context) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(15, TimeUnit.SECONDS);
builder.interceptors().add(new ReceivedCookiesInterceptor());
OkHttpClient httpClient = builder.build();
return httpClient;
}
}
看了方法名字ok,这个就是给建立的链接一些设置,这里面我只加了超时时间和消息拦截,其他的可以根据需要自己添加,那么这个消息拦截interceptors().add(new ReceivedCookiesInterceptor());干什么用的呢,看看,还是看看代码
public class ReceivedCookiesInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
List<String> cookieList = originalResponse.headers("Set-Cookie");
if (cookieList != null) {
for (String s : cookieList) {
Log.d("Received" ,"s = " + s);
}
}
return originalResponse;
}
}
对喽,你想的没错,主要就是为了获得cookies,得到后保存就是你自己的事了。
然后注意到
addOb = DemoRxBus.get().register(“addFeedTag”, String.class);
DemoRxBus.get().unregister(“addFeedTag”, addOb);
这个就是消息通知了,功能相当于EventBus,具体的还是看看代码吧:
public class DemoRxBus {
private static final String TAG = DemoRxBus.class.getSimpleName();
private static DemoRxBus instance;
public static synchronized DemoRxBus get() {
if (null == instance) {
instance = new DemoRxBus();
}
return instance;
}
private DemoRxBus() {
}
private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public <T> Observable<T> register(@NonNull Object tag, @NonNull Class<T> clazz) {
List<Subject> subjectList = subjectMapper.get(tag);
if (null == subjectList) {
subjectList = new ArrayList<>();
subjectMapper.put(tag, subjectList);
}
Subject<T, T> subject;
subjectList.add(subject = PublishSubject.create());
return subject;
}
public void unregister(@NonNull Object tag, @NonNull Observable observable) {
List<Subject> subjects = subjectMapper.get(tag);
if (null != subjects) {
subjects.remove((Subject) observable);
if (DemoTextUtil.isEmpty(subjects)) {
subjectMapper.remove(tag);
}
}
}
public void post(@NonNull Object content) {
post(content.getClass().getName(), content);
}
@SuppressWarnings("unchecked")
public void post(@NonNull Object tag, @NonNull Object content) {
List<Subject> subjectList = subjectMapper.get(tag);
if (!DemoTextUtil.isEmpty(subjectList)) {
for (Subject subject : subjectList) {
subject.onNext(content);
}
}
}
}
主要三个方法,注册,取消注册,发送,在现有的工程中网络数据都是回调的没有用到RxBus,想用的同学可以自己用一下。
OK,接下来看看怎么用这些东西去登录吧,
public class DemoActivity extends BaseActivity implements DataListener,View.OnClickListener {
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
}
@Override
public void initView() {
button = (Button)findViewById(R.id.buton);
}
@Override
public void initOnClickListener() {
button.setOnClickListener(this);
}
@Override
public void dataResponse(DataBean dataBean) {
}
@Override
public void loginResponse(UserBean userBean) {
UserBean.getInstance().setUserInfo(userBean.getUserInfo());
Toast.makeText(getApplicationContext(),"token = " + UserBean.getInstance().getUserInfo().getVideoLength(),Toast.LENGTH_SHORT).show();
}
@Override
public void errorResponse(Throwable e) {
Toast.makeText(getApplicationContext(),e.toString(),Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.buton:
GetDataFromClient dataFromClient = new GetDataFromClient(this);
Map<Object, Object> params = new HashMap<>();
params.put("token", "");
params.put("accountType", "phone");
params.put("account", "+8611111111111");
params.put("pin", "1234");
params.put("jpushId","000270e4cb6");
params.put("cilentType", 2);
dataFromClient.getDataFromClientLogin(demoApiService, params);
break;
}
}
}
代码很简单,发送网络请求,用回调函数把返回的数据负责单利的UserBean,这里面的UserBean是用户,用的单例模式。
说了半天都有个RxJava这个东西在哪里呢,你写的这玩意在主线程中用发的网络请求,你这是在搞球啊,别着急,里面不是有个方法嘛
dataFromClient.getDataFromClientLogin(demoApiService, params)看看这个是啥
public class GetDataFromClient {
DataListener dataListener;
public GetDataFromClient(DataListener dataListener){
this.dataListener = dataListener;
}
public void getDataFromClientLogin(DemoApiService demoApiService ,Map<Object, Object> params){
demoApiService.sendPhoneNumber(params)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<UserBean>() {
@Override
public void onNext(UserBean userBean) {
dataListener.loginResponse(userBean);
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
dataListener.errorResponse(e);
}
});
}
}
看看,就是这个,里面很简单了主线程中观察,新线程中发送网络请求,onNext中回调,好了至此简单的框架就全部搭建完成了。
项目Demo地址:https://github.com/ss831116/DataBindingRxjavaRetrofitApplication.git