网络框架

申明:低级码农问题解决中的参考和解决后的小结,仅用于个人记录,能力有限,可能有些错误,缺陷不自知,欢迎在评论中指正,谢谢!

 

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适合小而频繁的网络请求,不合适文件大的下载。原因如此吧。

 

写到最后,发现最核心的还是阻塞队列和线程池这些基本的东西。

posted @ 2020-05-10 23:20  hellodingc  阅读(587)  评论(0)    收藏  举报