最近面试了很多公司,感慨良多,面试官都强调要多写技术文章,多阅读源码。仔细想想确实如此,想成为一名好的Android工程师,如果没有源码阅读,怎么能写出好的代码那。
因为是第一篇文章,肯定想拿出一点好东西带大家分享。想想看自己也就写过一个网络框架可以拿出来谈谈。
首先介绍我这个网络框架的思路
1.所有的网络请求都抽象成一个task.
2.网络请求可以配置执行的方式,比如在当前线程执行,在单线程池排队执行,多线程池并发执行
3.网络请求的方法可以方便配置
4.网络解析的方式可以方便配置,比如公司是采用XML JSON 还是其他格式都要可以支持变更
以下是自己写的https://github.com/OneOfBillions/NetExcutor
欢迎牛人来评鉴
这里给大家预览一些代码
这是一个执行请求的方法,可以看出使用builder模式可以有很多可以自由设置的
public static <T> Canceller executorCommonRequest(final Context context,
final NetUIListener<T> uiListener, final NetOptions
options) {
Canceller canceller = new Canceller(null);
try {
if (uiListener != null) {
OkHttpNetEngine engine = new OkHttpNetEngine(context);//网络引擎
NetRequestConfig.Builder builder = new NetRequestConfig.Builder();//设置请求参数
builder.setContext(context);
builder.setNetUIListener(uiListener);
builder.setOptions(options);
builder.setNetEngine(engine);
builder.setMethod(uiListener.getMethod());
builder.setDataParser(new JsonDataParser());
canceller = new Canceller(engine);
new CommonNetTask(builder.build()).start();
}
} catch (Exception e) {
Log.d(NetUtils.TAG, "网络请求错误: " + e.toString());
}
return canceller;
}
网络请求就是一个TASK
public abstract class NetTask implements Runnable {
/**
* 任务处理中的数据中转.
*/
private HashMap<String, Object> data = new HashMap<>();
/**
* 单线程任务池.
*/
private static ExecutorService executorService = Executors
.newSingleThreadExecutor();
/**
* 多线程任务池.
*/
private static ExecutorService executorMutipleService = Executors
.newCachedThreadPool();
/**
* 单线程池,适用于时序要求的任务队列.
*
* @param runnable the runnable
*/
public static void executeRunnbale(Runnable runnable) {
if (runnable != null) {
executorService.execute(runnable);
}
}
/**
* 网络请求的配置类.
*/
private NetRequestConfig netRequest;
/**
* Parameter.
*/
private NetParameter parameter;
/**
* Instantiates a new Net task.
*
* @param netRequest the net request
*/
public NetTask(NetRequestConfig netRequest) {
this.netRequest = netRequest;
if (netRequest != null) {
if (netRequest.getNetEngine() != null) {
if (netRequest.getOptions() != null) {
if (netRequest.getNetUIListener() != null) {
prepareCreateParameter();
this.parameter = netRequest.getNetUIListener().createNetParams();
if (this.parameter != null) {
//init success
} else {
throw new NetException("parameter 不能为空");
}
} else {
throw new NetException("uiListener 不能为空");
}
} else {
throw new NetException("option 不能为空");
}
} else {
throw new NetException("请设置一种执行网络任务的引擎");
}
} else {
throw new NetException("NetRequest 不能为空");
}
}
/**
* Prepare create parameter.
*/
public void prepareCreateParameter() {
}
/**
* Use cache refresh ui.
*
* @param <T> the type parameter
* @param localValue the local value
*/
public <T> void callback(String localValue) {
if (!TextUtils.isEmpty(localValue)) {
// 得到缓存数据
T localResponseBean = GsonUtil.fromJsonStringToCollection(
localValue, getNetUiListener().getType());
if (localResponseBean != null) {
// 用缓存数据先刷新界面
callback(
NetUtils.NetRequestStatus.SUCCESS, localResponseBean);
}
}
}
/**
* 网络请求回调
*
* @param <T> the type parameter
* @param netRequestStatus the net request status
* @param bean the bean
*/
public <T> void callback(
final NetUtils.NetRequestStatus netRequestStatus, final T bean) {
if (getNetUiListener() != null) {
if (getOptions().isPostUIThread()) {
//回调到UI线程
if (getContext() != null && getContext() instanceof Activity) {
Activity activity = (Activity) getContext();
if (!activity.isFinishing()) {
boolean isDes = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
isDes = activity.isDestroyed();
}
if (!isDes) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
getNetUiListener().onComplete(bean, netRequestStatus);
}
});
}
}
}
} else {
//在任务执行线程运行回调
getNetUiListener().onComplete(bean, netRequestStatus);
}
}
}
/**
* 多线程池,适用于并行任务的执行.
*
* @param runnable the runnable
*/
public static void executeMutipleRunnbale(Runnable runnable) {
if (runnable != null) {
executorMutipleService.execute(runnable);
}
}
/**
* Put handler info.
*
* @param key the key
* @param value the value
*/
public void putHandlerInfo(String key, Object value) {
if (!TextUtils.isEmpty(key)) {
data.put(key, value);
}
}
/**
* Gets handler info.
*
* @param <T> the type parameter
* @param key the key
* @param classOfT the class of t
* @return the handler info
*/
public <T> T getHandlerInfo(String key, Class<T> classOfT) {
if (!TextUtils.isEmpty(key) && classOfT != null) {
Object object = data.get(key);
if (object != null && classOfT.isInstance(object)) {
return (T) object;
}
}
return null;
}
/**
* Start.
*/
public void start() {
NetOptions netOptions = getOptions();
if (netOptions != null) {
switch (netOptions.getRunMode()) {
case SINGLE_THREAD_POOL:
executeRunnbale(this);
break;
case MUTIPLE_THREAD_POOL:
executeMutipleRunnbale(this);
break;
case CURRENT_THREAD:
this.run();
break;
}
}
}
/**
* Gets options.
*
* @return the options
*/
public NetOptions getOptions() {
return netRequest.getOptions();
}
/**
* Gets net engine.
*
* @return the net engine
*/
public NetEngine getNetEngine() {
return netRequest.getNetEngine();
}
/**
* Gets context.
*
* @return the context
*/
public Context getContext() {
return netRequest.getContext();
}
/**
* Gets net request.
*
* @return the net request
*/
public NetRequestConfig getNetRequest() {
return netRequest;
}
/**
* Gets net ui listener.
*
* @return the net ui listener
*/
public NetUIListener getNetUiListener() {
return netRequest.getNetUIListener();
}
/**
* Gets parameter.
*
* @return the parameter
*/
public NetParameter getParameter() {
return parameter;
}
/**
* Gets net data parser.
*
* @return the net data parser
*/
public NetDataParser getNetDataParser() {
return netRequest.getDataParser();
}
}
去实现一个通用的网络任务
public class CommonNetTask extends NetTask {
/**
* Instantiates a new Common net task.
*
* @param netRequest the net request
*/
public CommonNetTask(NetRequestConfig netRequest) {
super(netRequest);
}
/**
* Run.
*/
@Override
public void run() {
Object responseBean = null;
NetUtils.NetRequestStatus netRequestStatus = NetUtils.NetRequestStatus.SERVER_ERROR;
NetEngine engine = getNetEngine();
NetRequestConfig netRequest = getNetRequest();
NetResponseInfo netResponseInfo;
NetRequestConfig.Method method = netRequest.getMethod();
netResponseInfo = engine.request
(getParameter(),netRequest.getMethod());
String resultStr = null;
NetUIListener netUIListener = getNetUiListener();
Type type = netUIListener.getType();
if (netResponseInfo != null && netResponseInfo.isSuccess()) {
resultStr = netResponseInfo.getResult();
netUIListener.setOriginalData(resultStr);//保存原始字符
responseBean = netRequest.getDataParser().parse(resultStr, type);
if (responseBean != null) {
netRequestStatus = NetUtils.NetRequestStatus.SUCCESS;
} else {
netRequestStatus = NetUtils.NetRequestStatus.SERVER_ERROR;
}
} else {
netRequestStatus = NetUtils.NetRequestStatus.NET_ERROR;
}
callback(netRequestStatus, responseBean);
}
}
网络请求引擎,实现类一般是各种网络框架okhttp,httpclient.
public interface NetEngine {
/**
* Init context.
*
* @param context the context
*/
void initContext(Context context);
NetResponseInfo request(NetParameter params, NetRequestConfig.Method method);
/**
* Add task tag.
*
* @param taskTag the task tag
*/
void addTaskTag(Object taskTag);
/**
* Cancel task.
*
* @param canceller the canceller
*/
void cancelTask(Canceller canceller);
}
/**
* 用okhttp网络框架实现{@link NetEngine}
*
* @version V1.0
*/
public class OkHttpNetEngine implements NetEngine {
/**
* The DEBUG TAG.
*/
public static final String TAG = OkHttpNetEngine.class.getSimpleName();
/**
* Instantiates a new Ok http net engine.
*
* @param context the context
*/
public OkHttpNetEngine(Context context) {
initContext(context);
}
/**
* Add task tag.
*
* @param taskTag the task tag
*/
@Override
public void addTaskTag(Object taskTag) {
this.taskTag = taskTag;
}
/**
* 任务TAG
*/
private Object taskTag;
/**
* @version V1.0
* @Title: Ok http excutor
* 2016.12.02
* @Title: Ok http excutor
*/
private static class OkHttpExcutor {
/**
* M ok http client.
*/
private static final OkHttpClient okHttpClient = new OkHttpClient();
/**
* 连接超时.
*/
private static final int CONNECT_TIME_OUT_MS = 60 * 1000;
/**
* 读取超时.
*/
private static final int READ_TIME_OUT_MS = 60 * 1000;
static {
okHttpClient.setConnectTimeout(CONNECT_TIME_OUT_MS,
TimeUnit.MILLISECONDS);
okHttpClient.setWriteTimeout(READ_TIME_OUT_MS, TimeUnit.MILLISECONDS);
okHttpClient.setReadTimeout(READ_TIME_OUT_MS, TimeUnit.MILLISECONDS);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] x509Certificates = new X509Certificate[0];
return x509Certificates;
}
}}, new SecureRandom());
okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
/**
* Init persistent cookie store.
*
* @param context the context
*/
public static void initPersistentCookieStore(Context context) {
if (okHttpClient.getCookieHandler() == null) {
if (context != null) {
Context application = context.getApplicationContext();
if (application != null) {
okHttpClient.setCookieHandler(new CookieManager(
new PersistentCookieStore(application), CookiePolicy.ACCEPT_ALL));
}
}
}
}
/**
* Cancel task.
*
* @param taskTag the task tag
*/
public static void cancelTask(Object taskTag) {
if (taskTag != null) {
okHttpClient.cancel(taskTag);
}
}
/**
* Request by post net response info.
*
* @param params the params
* @param taskTag the task tag
* @param method the method
* @return the net response info
*/
public static NetResponseInfo requestByMethod(NetParameter params, Object taskTag, NetRequestConfig.Method method) {
NetResponseInfo netEventInfo = new NetResponseInfo();//返回信息
Request.Builder builder = new Request.Builder();
if (taskTag != null) {
builder.tag(taskTag);
}
ResponseBody responseBody = null;
try {
FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
//请求参数拼装
List<KeyValuePair> list = params.createParameters();
Request request =null;
switch (method){
case GET:
String url = params.getRequestURL();
if (list != null && !list.isEmpty()) {
url += "?"
+ URLEncodedUtils.format(list, "UTF-8");
}
request = builder.url(url).build();
break;
case DELETE:
if (list != null && !list.isEmpty()) {
for (KeyValuePair keyValuePair : list) {
formEncodingBuilder.add(keyValuePair.getKey(),
keyValuePair.getValue());
}
}
request = builder.url(params.getRequestURL())
.delete(formEncodingBuilder.build()).build();
break;
case POST:
if (list != null && !list.isEmpty()) {
for (KeyValuePair keyValuePair : list) {
formEncodingBuilder.add(keyValuePair.getKey(),
keyValuePair.getValue());
}
}
request = builder.url(params.getRequestURL())
.post(formEncodingBuilder.build()).build();
break;
case PUT:
if (list != null && !list.isEmpty()) {
for (KeyValuePair keyValuePair : list) {
formEncodingBuilder.add(keyValuePair.getKey(),
keyValuePair.getValue());
}
}
request = builder.url(params.getRequestURL())
.put(formEncodingBuilder.build()).build();
break;
default:
if (list != null && !list.isEmpty()) {
for (KeyValuePair keyValuePair : list) {
formEncodingBuilder.add(keyValuePair.getKey(),
keyValuePair.getValue());
}
}
request = builder.url(params.getRequestURL())
.post(formEncodingBuilder.build()).build();
break;
}
Call call = okHttpClient.newCall(request);
netEventInfo.setStartTime(String.valueOf(System.currentTimeMillis()));//网络耗时统计
Response response = call.execute();
netEventInfo.setEndTime(String.valueOf(System.currentTimeMillis()));//网络耗时统计
netEventInfo.setHttpCode(String.valueOf(response.code()));///网络返回状态码
if (response.isSuccessful()) {
netEventInfo.setSuccess(true);
responseBody = response.body();
if (responseBody != null) {
String reponseStr = responseBody.string();
if (!TextUtils.isEmpty(reponseStr)) {
//网络返回结果解码
netEventInfo.setResult(params.decodeResponse(reponseStr));
}
}
}
} catch (Exception e) {
netEventInfo.setException(e.toString());//记录网络请求错误
} finally {
try {
responseBody.close();
} catch (Exception e) {
}
}
return netEventInfo;
}
}
/**
* Init context.
*
* @param context the context
*/
@Override
public void initContext(Context context) {
if (context != null) {
OkHttpExcutor.initPersistentCookieStore(context);
}
}
@Override
public NetResponseInfo request(NetParameter params, NetRequestConfig.Method method) {
return OkHttpExcutor.requestByMethod(params, taskTag, method);
}
/**
* Cancel task.
*
* @param canceller the canceller
*/
@Override
public void cancelTask(Canceller canceller) {
if (canceller != null) {
OkHttpExcutor.cancelTask(canceller.getTaskTag());
}
}
private static final String POST = "POST";
private static final String GET = "GET";
private static final String PUT = "PUT";
private static final String DELETE = "DELETE";
}
有 请求了肯定有回调啊,这个是必须的
public abstract class NetUIListener<T> {
/**
* M type.
*/
private Type mType;
/**
* Original data.
*/
private String originalData;
/**
* Gets original data.
*
* @return the original data
*/
public String getOriginalData() {
return originalData;
}
/**
* Sets original data.
*
* @param originalData the original data
*/
public void setOriginalData(String originalData) {
this.originalData = originalData;
}
/**
* Instantiates a new Ui listener.
*/
public NetUIListener() {
mType = getSuperclassTypeParameter(getClass());
}
/**
* Gets type.
*
* @return the type
*/
public Type getType() {
return mType;
}
/**
* Gets superclass type parameter.
*
* @param subclass the subclass
* @return the superclass type parameter
*/
private Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return parameterized.getActualTypeArguments()[0];
}
public NetRequestConfig.Method getMethod(){
return NetRequestConfig.Method.POST;
}
public abstract NetParameter createNetParams();
/**
* 在非主线程中组装参数适用于耗时的任务
*/
public void assembleCommonParamsBeanBackground(){
}
/**
* SUCCESS:服务器成功返回数据并GSON解析完成,业务处理
* SERVER_ERROR:系统错误(例如gson解析错误)
* NET_ERROR:网络错误
* UI线程运行
*
* @param bean the bean
* @param netRequestStatus the net request status
*/
public abstract void onComplete(T bean, NetUtils.NetRequestStatus netRequestStatus);
}
public abstract class CommonNetUIListener<T> extends NetUIListener<T> implements ConfigUrl{
@Override
public NetParameter createNetParams() {
return new CommonNetParameter(createUrl(),submitNetParams());
}
/**
* 提交网络请求参数
* return NULL,不发送网络请求,也不会有结果回调
* UI线程运行
*
* @return the common params bean
*/
public abstract List<KeyValuePair> submitNetParams();
}
网络返回数据解析类,具体可以实现 XML, JSON等格式的转换
public interface NetDataParser {
/**
* Parse t.
*
* @param data the data
* @param classOfT the class of t
* @return the t
*/
Object parse(Object data, Type classOfT);
}
public class JsonDataParser implements NetDataParser {
/**
* Parse t.
*
* @param data the data
* @param classOfT the class of t
* @return the t
*/
@Override
public Object parse(Object data, Type classOfT) {
if (data != null && classOfT != null) {
if (data.getClass() != classOfT) {
return GsonUtil.fromJsonStringToCollection(
String.valueOf(data), classOfT);
} else {
return data;
}
}
return null;
}
可以说费劲九牛二虎之力实现一个很原始的网络框架。。。。哈哈