應(yīng)用到知識點
- 需求:
支持請求 JSON文本類型瓤逼,音頻,圖片類型,批量下載。上傳
請求各種 數(shù)據(jù)時芽死,調(diào)用層不關(guān)心上傳參數(shù)分裝,如(request.addParamas(key,value))
直接將參數(shù)分裝成對象次洼,傳給框架
獲取數(shù)據(jù)后 調(diào)用層不關(guān)心JSON數(shù)據(jù)解析
回調(diào)時 調(diào)用層只需要知道傳入的JSON的對應(yīng)的響應(yīng)類关贵。
回調(diào)響應(yīng)結(jié)果發(fā)生在主線程(線程切換)
對下載,上傳擴展
支持高并發(fā)請求卖毁,請求隊列依次獲取揖曾,可以設(shè)置最大并發(fā)數(shù),設(shè)置先請求先執(zhí)
- 會用到的知識點
泛型
請求隊列
阻塞隊列
線程池拒絕策略
- 設(shè)計模式
模板方法模式
單例模式
策略模式
生產(chǎn)者消費者模式
流程步驟
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炭剪、封裝請求參數(shù)并添加任務(wù)到線程池
請求參數(shù)
public class Volley {
/**
* @param <T> 請求參數(shù)類型
* @param <M> 響應(yīng)參數(shù)類型
* 暴露給調(diào)用層
*/
public static <T, M> void sendRequest(T requestInfo, String url,
Class<M> response, IDataListener dataListener) {
RequestHodler<T> requestHodler = new RequestHodler<>();
requestHodler.setUrl(url);
//執(zhí)行http接口實現(xiàn)類
IHttpService httpService = new JsonHttpService();
//回調(diào)接口
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、線程池管理任務(wù)
將任務(wù)添加到線程池翔脱,這里用戶到了阻塞隊列實現(xiàn)高并發(fā)奴拦。
public class ThreadPoolManager {
private static final String TAG = "ThreadPoolManager";
private static ThreadPoolManager instance = new ThreadPoolManager();
//阻塞隊列
private LinkedBlockingQueue<Future<?>> taskQuene = new LinkedBlockingQueue<>();
//線程池類,添加FutureTask任務(wù)
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 {
/**
* 阻塞式函數(shù)
*/
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);
}
//當(dāng)線程池滿的時候回調(diào)用RejectedExecutionHandler類的rejectedExecution方法届吁,將任務(wù)添加的任務(wù)隊列
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错妖、網(wǎng)絡(luò)請求和響應(yīng)
第三步將任務(wù)HttpTask
添加到線程池中隶糕,該類的網(wǎng)絡(luò)請求及響應(yīng)的接口分別是IHttpService
和IHttpListener
。前者用于執(zhí)行網(wǎng)絡(luò)請求站玄,后者用于處理響應(yīng)并且將響應(yīng)信息回傳給調(diào)用者枚驻。
- 網(wǎng)絡(luò)請求
public class JsonHttpService implements IHttpService {
private IHttpListener httpListener;
private HttpClient httpClient=new DefaultHttpClient();
private HttpPost httpPost;
private String url;
private byte[] requestDate;
/**
* httpClient獲取網(wǎng)絡(luò)的回調(diào)
*/
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 {
//響應(yīng)嗎
int code=response.getStatusLine().getStatusCode();
if(code==200)
{
httpListener.onSuccess(response.getEntity());
}else
{
httpListener.onFail();
}
return null;
}
}
}
- 網(wǎng)絡(luò)響應(yīng)
由于任務(wù)執(zhí)行是在子線程,調(diào)用者(Activity)一般在主線程更新UI株旷,所以要進行線程切換再登。這里要使用主線程的Handler,通過post方法執(zhí)行客戶端回調(diào)接口IDataListener
進行數(shù)據(jù)傳遞晾剖。
public class JsonDealLitener<M> implements IHttpListener {
private Class<M> responese;
/**
* 回調(diào)調(diào)用層 的接口
*/
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();
/*
得到網(wǎng)絡(luò)返回的數(shù)據(jù)
子線程
*/
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;
}
}