应用到知识点
- 需求:
支持请求 JSON文本类型,音频,图片类型,批量下载。上传
请求各种 数据时,调用层不关心上传参数分装,如(request.addParamas(key,value))
直接将参数分装成对象,传给框架
获取数据后 调用层不关心JSON数据解析
回调时 调用层只需要知道传入的JSON的对应的响应类。
回调响应结果发生在主线程(线程切换)
对下载,上传扩展
支持高并发请求,请求队列依次获取,可以设置最大并发数,设置先请求先执
- 会用到的知识点
泛型
请求队列
阻塞队列
线程池拒绝策略
- 设计模式
模板方法模式
单例模式
策略模式
生产者消费者模式
流程步骤
1、客户端请求
public void login(View view) {
User user = new User();
user.setName("13343491234");
user.setPassword("123456");
for (int i = 0; i < 50; i++) {
Volley.sendRequest(user, url, LoginRespense.class, new
IDataListener<LoginRespense>() {
@Override
public void onSuccess(LoginRespense loginRespense) {
Log.i(TAG, loginRespense.toString());
}
@Override
public void onFail() {
Log.i(TAG, "获取失败");
}
});
}
}
2、封装请求参数并添加任务到线程池
请求参数
public class Volley {
/**
* @param <T> 请求参数类型
* @param <M> 响应参数类型
* 暴露给调用层
*/
public static <T, M> void sendRequest(T requestInfo, String url,
Class<M> response, IDataListener dataListener) {
RequestHodler<T> requestHodler = new RequestHodler<>();
requestHodler.setUrl(url);
//执行http接口实现类
IHttpService httpService = new JsonHttpService();
//回调接口
IHttpListener httpListener = new JsonDealLitener<>(response, dataListener);
requestHodler.setHttpService(httpService);
requestHodler.setHttpListener(httpListener);
HttpTask<T> httpTask = new HttpTask<>(requestHodler);
try {
ThreadPoolManager.getInstance().execte(new FutureTask<Object>(httpTask, null));
} catch (InterruptedException e) {
dataListener.onFail();
}
}
3、线程池管理任务
将任务添加到线程池,这里用户到了阻塞队列实现高并发。
public class ThreadPoolManager {
private static final String TAG = "ThreadPoolManager";
private static ThreadPoolManager instance = new ThreadPoolManager();
//阻塞队列
private LinkedBlockingQueue<Future<?>> taskQuene = new LinkedBlockingQueue<>();
//线程池类,添加FutureTask任务
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(runable);
}
private Runnable runable = new Runnable() {
@Override
public void run() {
while (true) {
FutureTask futrueTask = null;
try {
/**
* 阻塞式函数
*/
Log.i(TAG, "等待队列 " + taskQuene.size());
futrueTask = (FutureTask) taskQuene.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (futrueTask != null) {
threadPoolExecutor.execute(futrueTask);
}
Log.i(TAG, "线程池大小 " + threadPoolExecutor.getPoolSize());
}
}
};
public <T> void execte(FutureTask<T> futureTask) throws InterruptedException {
taskQuene.put(futureTask);
}
//当线程池满的时候回调用RejectedExecutionHandler类的rejectedExecution方法,将任务添加的任务队列
private RejectedExecutionHandler handler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
taskQuene.put(new FutureTask<Object>(r, null) {
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
4、网络请求和响应
第三步将任务HttpTask
添加到线程池中,该类的网络请求及响应的接口分别是IHttpService
和IHttpListener
。前者用于执行网络请求,后者用于处理响应并且将响应信息回传给调用者。
- 网络请求
public class JsonHttpService implements IHttpService {
private IHttpListener httpListener;
private HttpClient httpClient=new DefaultHttpClient();
private HttpPost httpPost;
private String url;
private byte[] requestDate;
/**
* httpClient获取网络的回调
*/
private HttpRespnceHandler httpRespnceHandler=new HttpRespnceHandler();
@Override
public void setUrl(String url) {
this.url=url;
}
@Override
public void excute() {
httpPost=new HttpPost(url);
ByteArrayEntity byteArrayEntity=new ByteArrayEntity(requestDate);
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 setRequestData(byte[] requestData) {
this.requestDate=requestData;
}
private class HttpRespnceHandler extends BasicResponseHandler
{
@Override
public String handleResponse(HttpResponse response)
throws ClientProtocolException {
//响应吗
int code=response.getStatusLine().getStatusCode();
if(code==200)
{
httpListener.onSuccess(response.getEntity());
}else
{
httpListener.onFail();
}
return null;
}
}
}
- 网络响应
由于任务执行是在子线程,调用者(Activity)一般在主线程更新UI,所以要进行线程切换。这里要使用主线程的Handler,通过post方法执行客户端回调接口IDataListener
进行数据传递。
public class JsonDealLitener<M> implements IHttpListener {
private Class<M> responese;
/**
* 回调调用层 的接口
*/
private IDataListener<M> dataListener;
Handler handler=new Handler(Looper.getMainLooper());
public JsonDealLitener(Class<M> responese, IDataListener<M> dataListener) {
this.responese = responese;
this.dataListener = dataListener;
}
@Override
public void onSuccess(HttpEntity httpEntity) {
InputStream inputStream=null;
try {
inputStream=httpEntity.getContent();
/*
得到网络返回的数据
子线程
*/
String content=getContent(inputStream);
final M m= JSON.parseObject(content,responese);
handler.post(new Runnable() {
@Override
public void run() {
dataListener.onSuccess(m);
}
});
} 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) {
dataListener.onFail();
System.out.println("Error=" + e.toString());
} 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;
}
}