retrofit2 使用教程 及 Android 网络架构搭建 (原创)
squareup 推出 retrofit2 已经有一段时间了,现在的版本比较稳定,没有什么大坑了。网络上的教程要么太简单,只是个Demo;要么有些落时,要么复用性比较差,所以自己写个教程,供大家参考。代码已上传至 https://github.com/Alex9Xu/RetrofitDemo
1. 首先在build.gradle引入依赖
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
注意,这里的 logging 用于输出网络交互的Log,对于开发调试极其有用。之前retrofit2因为不能输出Log被人嫌弃了很久,各高手实现了几种打印Log的方式,现在总算有官方的了。
2. 这是工具类
package com.alex9xu.hello.net; import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable; import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import com.alex9xu.hello.config.AppConfigInterface;
import com.alex9xu.hello.utils.LogHelper; import java.io.IOException;
import java.lang.ref.WeakReference; /**
* Created by Alex9Xu@hotmail.com on 2016/7/13
*/
public class RetrofitBase {
private static final String TAG = "RetrofitBase"; private static Retrofit mRetrofit;
// private static Dialog mLoadingDialog;
private static WeakReference<Context> mContextRef; public static Retrofit retrofit() {
if (mRetrofit == null) {
OkHttpClient client; // Notice: The only differ of debug is: HttpLoggingInterceptor
// Common Params: "version" and "server_call_version" will in every request
if(!AppConfigInterface.isDebug) {
client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("call_version", AppConfigInterface.TO_SERVER_VERSION)
.addQueryParameter("deviceType", AppConfigInterface.DEVICE_TYPE)
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("user-agent", "android")
.url(url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.build();
} else {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder()
.addInterceptor(logging)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("version", AppConfigInterface.TO_SERVER_VERSION)
.addQueryParameter("deviceType", AppConfigInterface.DEVICE_TYPE)
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("user-agent", "android")
.url(url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.build();
} mRetrofit = new Retrofit.Builder()
.baseUrl(AppConfigInterface.BASE_COM_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return mRetrofit;
} // Encapsulation Request and Response
public static <T> void AddToEnqueue(Call<T> baseCall, Context context, boolean isShowDlg,
final NetRequestListener listener) {
mContextRef = new WeakReference<>(context);
// if(isShowDlg && null == mLoadingDialog && null != mContextRef.get()) {
// mLoadingDialog = DialogUtil.showLoginDialog(mContextRef.get());
// mLoadingDialog.getWindow().setBackgroundDrawable(new BitmapDrawable());
// }
// if(isShowDlg) {
// mLoadingDialog.show();
// } baseCall.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, retrofit2.Response<T> response) {
LogHelper.d(TAG, "toEnqueue, onResponse:");
if (null != response.body()) {
if(response.code() == 200) {
LogHelper.d(TAG, "toEnqueue, onResponse Suc");
// if(null != mLoadingDialog) {
// mLoadingDialog.dismiss();
// }
listener.onRequestSuc(response.code(), response);
} else {
LogHelper.d(TAG, "toEnqueue, onResponse Fail:" + response.code());
// if(null != mLoadingDialog) {
// mLoadingDialog.dismiss();
// }
listener.onRequestFail(response.code(), response.message());
}
} else {
LogHelper.d(TAG, "toEnqueue, onResponse Fail");
// if(null != mLoadingDialog) {
// mLoadingDialog.dismiss();
// }
listener.onRequestFail(response.code(), response.message());
}
} @Override
public void onFailure(Call<T> call, Throwable t) {
LogHelper.d(TAG, "toEnqueue, onFailure Fail");
// if(null != mLoadingDialog) {
// mLoadingDialog.dismiss();
// }
listener.onRequestFail(AppConfigInterface.RESULT_FAIL_UNKNOW, null);
}
});
} public static void stopLoadingDlg(Context context) {
// if(null != mContextRef && context == mContextRef.get() && null != mLoadingDialog) {
// mLoadingDialog.dismiss();
// mLoadingDialog = null;
// }
} }
讲解一下:
(1) 通过 addInterceptor 实现的打印日志及加入多个公共参数功能。
(2) 除了含有 HttpLoggingInterceptor 外,测试的和正式的,没有任何区别。通过全局变量控制是否为正式环境,如果是正式环境则不输出网络交互相关的Log。
(3) 可以通过 addQueryParameter("deviceType", "0") 的形式加入多个公共参数,这样所有的请求都会带该参数。
(4) 这里 BASE_COM_URL 是 http://test.hello.com/ 的形式。
3. 使用方式:
(1) 先写接口
package com.alex9xu.hello.net.apis; import android.support.v4.util.ArrayMap;
import com.alex9xu.hello.config.AppConfigInterface;
import com.alex9xu.hello.model.WeatherResult; import retrofit2.Call; import retrofit2.http.GET;
import retrofit2.http.QueryMap; /**
* Created by Alex9Xu@hotmail.com on 2016/7/14
*/ public interface CityWeatherApi {
@GET(AppConfigInterface.GET_WEATHER)
Call<WeatherResult> getClassify(@QueryMap ArrayMap<String,String> paramMap);
}
这里通过Get提交参数,参数存储在Map里,可以添加多组参数。注意,我使用了ArrayMap,这是Android里特有的一种形式,内存占用只有HashMap的十分之一左右。
String CLASSIFYLIST = "query/classify.html";
(2) 再写返回值结构
package com.alex9xu.hello.model.Entity; /**
* Created by Alex9Xu@hotmail.com on 2016/7/18
*/
public class Weatherinfo {
private String city;
private String cityid;
private String temp;
private String WD;
private String WS;
private String SD;
private String WSE;
private String time;
private String isRadar;
private String Radar;
private String njd;
private String qy; public String getCity() {
return city;
} public String getTemp() {
return temp;
}
}
package com.alex9xu.hello.model; import com.alex9xu.hello.model.Entity.Weatherinfo; /**
* Created by Alex9Xu@hotmail.com on 2016/7/18
*/
public class WeatherResult { private Weatherinfo weatherinfo; public Weatherinfo getWeatherinfo() {
return weatherinfo;
} }
返回的数据写成如上形式,以利于复用。
(3) 调用
import com.alex9xu.test.model.ClassifyListResult;
import com.alex9xu.test.model.entity.ClassfiyBean;
import com.alex9xu.test.net.ClassifyApi;
import com.alex9xu.test.net.RetrofitBase;
/** * Created by Alex9Xu@hotmail.com on 2016/7/14
*/
public class MainActivity extends BaseActivity {
// Note: make all the Activities extends BaseActivity to manage
private static final String TAG = "MainActivity";
private TextView mTvwShowInfo;
private Call<WeatherResult> mWeatherCall;
...
private void getData() {
// Notice: ArrayMap requires less memory in Android compare with HashMap (about 10%)
CityWeatherApi classifyApi = RetrofitBase.retrofit().create(CityWeatherApi.class);
ArrayMap<String,String> paramMap = new ArrayMap<>();
paramMap.put("sortType", "1");
paramMap.put("uid", "654321");
mWeatherCall = classifyApi.getClassify(paramMap);
RetrofitBase.AddToEnqueue(mWeatherCall, MainActivity.this, true, new NetRequestListener() {
@Override
public void onRequestSuc(int code, Response response) {
LogHelper.d(TAG, "onRequestSuc");
Response<WeatherResult> resultResponse = response;
if(null != resultResponse.body().getWeatherinfo()) {
Weatherinfo info = resultResponse.body().getWeatherinfo();
StringBuilder strBld = new StringBuilder();
strBld.append(info.getCity());
strBld.append(getString(R.string.temperature));
strBld.append(getString(R.string.colon));
strBld.append(info.getTemp());
mTvwShowInfo.setText(strBld.toString());
}
}
@Override
public void onRequestFail(int code, String reason) {
LogHelper.d(TAG, "onRequestFail: " + code + ", " + reason);
}
});
}
@Override
protected void onStop() {
super.onStop();
// Notice: If the web operate is to update UI, you can cancel it when onStop
mWeatherCall.cancel();
}
...
讲解:会拼接成 https://test.hello.com/query/classify.html?uid=654321&version=1.0&Id=123456&deviceType=0 ,注意,其中两项是公共参数。
好了,这样就可以正常运行了。
retrofit2 使用教程 及 Android 网络架构搭建 (原创)的更多相关文章
- Retrofit2.0+RxJava+Dragger2实现不一样的Android网络架构搭建
Tamic :csdn http://blog.csdn.net/sk719887916 众所周知,手机APP的核心就在于调用后台接口,展示相关信息,方便我们在手机上就能和外界交互.所以APP中网络框 ...
- 基于Retrofit2.0+RxJava+Dragger2实现不一样的Android网络构架搭建(转载)
转载请注明出处:http://blog.csdn.net/finddreams/article/details/50849385#0-qzone-1-61707-d020d2d2a4e8d1a374a ...
- android 学习运用海马模拟器教程与android环境的搭建
第三方海马玩模拟器 第一天的学习android采用的模拟器是海马,因此就分享给大家海马模拟器的相关步骤: 海马玩模拟器官网: http://droid4x.haimawan.com 下载相关平台的模拟 ...
- Android网络编程(一)HTTP协议原理
相关文章 Android网络编程(一)HTTP协议原理 Android网络编程(二)HttpClient与HttpURLConnection Android网络编程(三)Volley使用方法全解析 A ...
- Android Navigation 架构组件入门教程
Android Navigation 架构组件入门教程 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:https://www.cnblogs.com/cavalier-/p/1 ...
- Android 网络教程: 开始
原文:Android Networking Tutorial: Getting Started 作者:Eunice Obugyei 译者:kmyhy 从 API 级别 1 开始,网络始终是 Andro ...
- 转---详细的Android开发环境搭建教程
五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程 引言 在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立A ...
- Android基础新手教程——1.2 开发环境搭建
Android基础新手教程--1.2 开发环境搭建 标签: Android基础新手教程 如今主流的Android开发环境有: ①Eclipse + ADT + SDK ②Android Studio ...
- Android开发环境搭建篇详尽的教程实例汇
原文链接:http://android.eoe.cn/topic/android_sdk 一.android开发环境搭建图文教程整理篇: 1.Android开发环境搭建全程演示(jdk+eclip+a ...
随机推荐
- 1、MyBatisNet的安装使用
用到的几个DLL按理说应该到官网下载,但这个官网是谷大哥的,不知道是不是被屏蔽,总打不开,幸好从别人的程序里拷过来一份,直接放在自己的程序里就行! 程序结构如下: Providers.config,S ...
- 转:Ubuntu12.04 LTS 使用心得-开机挂载其他分区
1.在/media目录下创建好用来关联你要挂载的分区的文件夹(相当于一个虚拟目录/挂载点,链接/映射到你要挂载的盘符去) 我要挂载4个分区,所以创建了四个挂载点,名字随便取,只要你自己认的出来哪个对应 ...
- BZOJ 1013 球形空间产生器
Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁 ...
- Linux共享库两种加载方式简述
Linux共享库两种加载方式简述 动态库技术通常能减少程序的大小,节省空间,提高效率,具有很高的灵活性,对于升级软件版本也更加容易.与静态库不同,动态库里面的函数不是执行程序本身 的一部分,而是 ...
- Linux kernel ‘fib6_add_rt2node’函数安全漏洞
漏洞名称: Linux kernel ‘fib6_add_rt2node’函数安全漏洞 CNNVD编号: CNNVD-201307-265 发布时间: 2013-07-16 更新时间: 2013-07 ...
- ZOJ-3597-Hit the Target!(线段树+扫描线)
题解引自:http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474614.html 这题和着题解一块看,看了半天才看懂的....菜菜.... 题意:有 ...
- 【动态规划】【缩点】NCPC 2014 G Outing
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1793 题目大意: 一辆公交车,上面M个座位,N个人(M<=N<=1000) ...
- Python import / pyd / dll
使用Python import 模块时, 先会在模块的搜索path里依次搜索(前面会覆盖之后出现的同名模块),次序为: 1. 程序的主目录(交互模式下当前的工作目录或 脚本文件所在的目录) 2. 环境 ...
- HDOJ(HDU) 2133 What day is it(认识下Java的Calendar类---日期类)
Problem Description Today is Saturday, 17th Nov,2007. Now, if i tell you a date, can you tell me wha ...
- linux下安装python linux下一些常用的命令
注意 ubuntukylin-14.04.2-desktop-amd64 自带python2.7.6 这个说的比较详细 http://wenku.baidu.com/link?url=gaeFcQrc ...