网络框架
申明:低级码农问题解决中的参考和解决后的小结,仅用于个人记录,能力有限,可能有些错误,缺陷不自知,欢迎在评论中指正,谢谢!
OKhttp网络框架和核心:并发。把网络请求放到线程,由线程池执行。
比如有个核心线程,一直处于运行状态,用于把添加到请求队列的线程,特别注意,这个队列是阻塞队列。
public class ThreadPoolManager { /** 线程池 */ ThreadPoolExecutor executor; /** 请求队列,fifo */ private LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<>(); static ThreadPoolManager instance; static ThreadPoolManager getInstance() { if (instance == null) { instance = new ThreadPoolManager(); } return instance; } private ThreadPoolManager() { executor = new ThreadPoolExecutor(3, 10, 15, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(4), new RejectedExecutionHandler() { public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { addTask(runnable); } }); executor = new ThreadPoolExecutor(3, 10, 15, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(4)); // 执行便利线程,这个线程必须一开始就运行起来 executor.execute(new CoreRunnable()); } // 添加队列 public void addTask(Runnable r) { try { mQueue.put(r); } catch (InterruptedException e) { } } private class CoreRunnable implements Runnable{ Runnable runnable = null; @Override public void run() { while (true) { try { runnable = mQueue.take(); executor.execute(runnable); } catch (InterruptedException e) { } } } } }
定义请求接口,包括用于处理请求结果的回调,还有网络请求的处理过程的接口。请求的接口的实现类必须包含url,和一个回调用于处理请求结果,还有其他属性,如请求参数、方式(get、post),这里我们例子从简,都忽略掉了。
public interface IHttpRequest {
void setListener(ICallbackListener listener);
void execute();
}
public class HttpRequest implements IHttpRequest { private String url; private ICallbackListener listener; public HttpRequest(String url) { this.url = url; } @Override public void setListener(ICallbackListener listener) { this.listener = listener; } @Override public void execute() { URL url = null; HttpURLConnection urlConnection = null; try { url = new URL(this.url); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setInstanceFollowRedirects(HttpURLConnection.getFollowRedirects()); urlConnection.setConnectTimeout(5000); urlConnection.setReadTimeout(5000); urlConnection.setRequestMethod("GET"); urlConnection.connect(); if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream is = urlConnection.getInputStream(); listener.onSuccess(getData(is)); } else { listener.onFail(); } } catch (Exception e) { } finally { urlConnection.disconnect(); } } private String getData(InputStream inputStream) { BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = br.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { } finally { try { inputStream.close(); } catch (Exception e) { } } return sb.toString(); } }
网络请求应该线线程中执行,看队列的泛型是线程,所以应该创建一个线程类,线程类的成员变量就是HttpRequest,在这个线程中执行HttpRequest.execute,即执行网络请求。
public class HttpTask implements Runnable { IHttpRequest request; public HttpTask(IHttpRequest request) { this.request = request; } @Override public void run() { request.execute(); } }
上面的简单的网络框架用法如下,
private void sendRequest() {
IHttpRequest httpRequest = new HttpRequest(url);
httpRequest.setListener(new ICallbackListener() {
@Override
public void onSuccess(String response) {
Log.v("LOG", response);
}
@Override
public void onFail() {
}
});
HttpTask httpTask = new HttpTask(httpRequest);
ThreadPoolManager.getInstance().addTask(httpTask);
}
上面的okhttp的核心思想吧,但实际情况会比这个复杂的多。retrofit是对okhttp进行封装,使用运行时注解提供功能,okhttp和retrofit都是square的产品,volley是google的。
Volley也是利用阻塞队列添加线程,执行线程的。不过Volley的请求执行用的线程池,而是在一个线程中执行的request,即volley的请求不是并发的,所以很多博客说volley适合小而频繁的网络请求,不合适文件大的下载。原因如此吧。
写到最后,发现最核心的还是阻塞队列和线程池这些基本的东西。
浙公网安备 33010602011771号