自定义网络框架开发,功能:
支持请求: json文本类型音频,视频,图片类型,批量下载,上传
请求各种数据时,调用层不关心上船参数分装,如(request.addParameters(key,value)),直接将参数分装成对象传给狂框架,获取数据后,调用层不关心json数据解析
回调时,调用层只需知道传入的json对应的响应类。
回调响应结果发生在主线程(线程切换)
对下载,上传扩展
支持高并发请求,请求队列依次获取,可以设置最大并发数,设置先请求先执行
涉及的知识点:
- 泛型
- 请求队列
- 阻塞队列
- 线程池拒绝策略
设计模式:
- 模板方法模式
- 单例模式
- 策略模式
- 生产者消费者模式
使用的jar包: - fastjson(com.alibaba:fastjson:1.2.23)
- httpcore(httpcomponents-httpcore:httpcore:4.0-alpha6)
下面为json文本请求主要代码和思路
首先设计科三个接口分别为请求网络(IHttpService)网络访问结果回调(IHttpListener)和回调结果给调用层的接口(IDataListener)
public interface IDataListener <M>{
//回调结果给调用层
void onSuccess(M m);
void onFail();
}
public interface IHttpListener {
//网络访问处理结果回调
void onSuccess(HttpEntity httpEntity);
void onFail();
}
public interface IHttpService {
/*
* 设置url
* */
void setUrl(String url);
//执行获取网络
void execute();
//设置处理接口
void setHttpListener(IHttpListener httpListener);
//设置请求参数
void setRequestParameter( byte[] requestParameter);
}
然后主要是接口的实现
IHttpService接口的实现JsonHttpService,主要利用HttpPost(引入的jar包)完成数据请求,并把请求成功的数据传递给IHttpListener的实现类JsonDealListener
public class JsonHttpService implements IHttpService {
private IHttpListener httpListener;
private HttpClient httpClient=new DefaultHttpClient();
private HttpPost httpPost;
private String url;
private byte[] requestParameter;
private HttpRespnceHandler httpRespnceHandler=new HttpRespnceHandler();
@Override
public void setUrl(String url) {
this.url=url;
}
@Override
public void execute() {
httpPost=new HttpPost(url);
ByteArrayEntity byteArrayEntity=new ByteArrayEntity(requestParameter);
httpPost.setEntity(byteArrayEntity);
try{
httpClient.execute(httpPost,httpRespnceHandler);
}catch (IOException e){
httpListener.onFail();
}
}
@Override
public void setHttpListener(IHttpListener httpListener) {
this.httpListener=httpListener;
}
@Override
public void setRequestParameter(byte[] requestParameter) {
this.requestParameter=requestParameter;
}
private class HttpRespnceHandler extends BasicResponseHandler {
@Override
public String handleResponse(HttpResponse response)throws ClientProtocolException {
//响应码
int code=response.getStatusLine().getStatusCode();
//200响应成功,传递请求成功的返回数据
if (code==200){
httpListener.onSuccess(response.getEntity());
}
else {
httpListener.onFail();
}
return null;
}
}
}
IHttpListener的实现类JsonDealListener主要完成将起请求成功的结果传递给调用层(IDataListener的实现者)
public class JsonDealListener<M> implements IHttpListener {
private Class<M> responceClass;
private IDataListener<M> dataListener;
/**
* 获取主线程的handler通过handler
*切换至主线程
* */
Handler handler=new Handler(Looper.getMainLooper());
public JsonDealListener(Class<M> responceClass, IDataListener<M> dataListener){
this.responceClass=responceClass;
this.dataListener=dataListener;
}
@Override
public void onSuccess(HttpEntity httpEntity) {
InputStream inputStream=null;
try {
inputStream = httpEntity.getContent();
String content = getContent(inputStream);
final M responce = JSON.parseObject(content, responceClass);
handler.post(new Runnable() {
@Override
public void run() {
dataListener.onSuccess(responce);
}
});
}catch (IOException e){
dataListener.onFail();
}
}
@Override
public void onFail() {
dataListener.onFail();
}
private String getContent(InputStream inputStream) {
String content = null;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
System.out.println("Error=" + e.toString());
dataListener.onFail();
} finally {
try {
inputStream.close();
} catch (IOException e) {
System.out.println("Error=" + e.toString());
}
}
return sb.toString();
}catch (Exception e){
e.printStackTrace();
dataListener.onFail();
}
return content;
}
}
我们将监听,请求服务,url等封装在ReqestHolder类
public class RequestHolder<T> {
//执行下载类
private IHttpService httpService;
//获取数据回调结果的类
private IHttpListener httpListener;
//i请求参数对应的实体
private T requestInfo;
private String url;
public IHttpService getHttpService() {
return httpService;
}
public void setHttpService(IHttpService httpService) {
this.httpService = httpService;
}
public IHttpListener getHttpListener() {
return httpListener;
}
public void setHttpListener(IHttpListener httpListener) {
this.httpListener = httpListener;
}
public T getRequestInfo() {
return requestInfo;
}
public void setRequestInfo(T requestInfo) {
this.requestInfo = requestInfo;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
我们将封装的实体类RequestHolder传递给ThreadPoolManager,ThreadPoolManager是我们对请求的优化,主要利用了线程池(ThreadPoolExecutor)和阻塞队列(LinkedBlockingQueue)来保存我们开启的线程,当阻塞队列没有任务时,线程池会阻塞等待,直到阻塞队列填充任务
public class ThreadPoolManager {
private static final String TAG="gjh";
private static ThreadPoolManager instance=new ThreadPoolManager();
//生产者消费者模式
private LinkedBlockingQueue<Future<?>> taskQueue=new LinkedBlockingQueue<>();
private ThreadPoolExecutor threadPoolExecutor;
public static ThreadPoolManager getInstance(){
return instance;
}
private ThreadPoolManager(){
/*
* 参数一核心线程数
* 二 最大线程数
* 三 完成任务后空闲时间
* 四 空闲时间单位秒
* 五 阻塞队列
* 六 拒绝策略
* */
threadPoolExecutor=new ThreadPoolExecutor(4,10,10, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4),handler);
threadPoolExecutor.execute(runnable);
}
private Runnable runnable=new Runnable() {
@Override
public void run() {
while(true){
FutureTask futureTask=null;
try{
//阻塞式函数
Log.i(TAG,"等待队列"+taskQueue.size());
//取出任务后如果线程池已满将会执行拒绝策略从新放入taskQueue队列
futureTask= (FutureTask) taskQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (futureTask!=null){
threadPoolExecutor.execute(futureTask);
}
Log.i(TAG,"线程池大小 "+threadPoolExecutor.getPoolSize());
}
}
};
public <T> void execte(FutureTask<T> futureTask) throws InterruptedException {
taskQueue.put(futureTask);
}
private RejectedExecutionHandler handler=new RejectedExecutionHandler(){
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
try {
taskQueue.put(new FutureTask<Object>(runnable,null));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
然后我们写了Vooley类暴露出外部调用的方法,隐藏了具体的实现
public class Volley {
//暴露给调用层
public static <T,M> void sendRequest(T requestInfo, String url,
Class<M> response, IDataListener dataListener){
RequestHolder<T> requestHolder=new RequestHolder<>();
requestHolder.setUrl(url);
IHttpService httpService=new JsonHttpService();
requestHolder.setRequestInfo(requestInfo);
IHttpListener httpListener=new JsonDealListener<>(response,dataListener);
requestHolder.setHttpListener(httpListener);
requestHolder.setHttpService(httpService);
HttpTask<T> httpTask=new HttpTask<>(requestHolder);
try {
ThreadPoolManager.getInstance().execte(new FutureTask<Object>(httpTask,null));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试类:
public class LoginResponse {
private int code;
private String user_id;
private String time;
private String name;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class User {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public class MainActivity extends AppCompatActivity {
public static final String url="";
private static final String Tag="gjh";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void login (View view){
User user=new User();
user.setName("dd");
user.setPassword("sss");
for (int i=0;i<50;i++){
Volley.sendRequest(user, url, LoginResponse.class, new IDataListener<LoginResponse>() {
@Override
public void onSuccess(LoginResponse loginResponse) {
Log.i(Tag,loginResponse.toString());
}
@Override
public void onFail() {
Log.i(Tag,"请求失败");
}
});
}
}
}