Android网络框架初步尝试

 最近面试了很多公司,感慨良多,面试官都强调要多写技术文章,多阅读源码。仔细想想确实如此,想成为一名好的Android工程师,如果没有源码阅读,怎么能写出好的代码那。

 因为是第一篇文章,肯定想拿出一点好东西带大家分享。想想看自己也就写过一个网络框架可以拿出来谈谈。
 首先介绍我这个网络框架的思路
 1.所有的网络请求都抽象成一个task.

 2.网络请求可以配置执行的方式,比如在当前线程执行,在单线程池排队执行,多线程池并发执行
 3.网络请求的方法可以方便配置
 4.网络解析的方式可以方便配置,比如公司是采用XML JSON 还是其他格式都要可以支持变更

 以下是自己写的https://github.com/OneOfBillions/NetExcutor 
 欢迎牛人来评鉴
 这里给大家预览一些代码

这是一个执行请求的方法,可以看出使用builder模式可以有很多可以自由设置的

    public static <T> Canceller executorCommonRequest(final Context context,
                                                      final NetUIListener<T> uiListener, final NetOptions
                                                              options) {
        Canceller canceller = new Canceller(null);
        try {
            if (uiListener != null) {
                OkHttpNetEngine engine = new OkHttpNetEngine(context);//网络引擎
                NetRequestConfig.Builder builder = new NetRequestConfig.Builder();//设置请求参数
                builder.setContext(context);
                builder.setNetUIListener(uiListener);
                builder.setOptions(options);
                builder.setNetEngine(engine);
                builder.setMethod(uiListener.getMethod());
                builder.setDataParser(new JsonDataParser());
                canceller = new Canceller(engine);
                new CommonNetTask(builder.build()).start();
            }
        } catch (Exception e) {

            Log.d(NetUtils.TAG, "网络请求错误: " + e.toString());
        }


        return canceller;

    }

网络请求就是一个TASK

public abstract class NetTask implements Runnable {


    /**
     * 任务处理中的数据中转.
     */
    private HashMap<String, Object> data = new HashMap<>();
    /**
     * 单线程任务池.
     */
    private static ExecutorService executorService = Executors
            .newSingleThreadExecutor();
    /**
     * 多线程任务池.
     */
    private static ExecutorService executorMutipleService = Executors
            .newCachedThreadPool();

    /**
     * 单线程池,适用于时序要求的任务队列.
     *
     * @param runnable the runnable
     */
    public static void executeRunnbale(Runnable runnable) {
        if (runnable != null) {
            executorService.execute(runnable);
        }

    }

    /**
     * 网络请求的配置类.
     */
    private NetRequestConfig netRequest;
    /**
     * Parameter.
     */
    private NetParameter parameter;

    /**
     * Instantiates a new Net task.
     *
     * @param netRequest the net request
     */
    public NetTask(NetRequestConfig netRequest) {
        this.netRequest = netRequest;
        if (netRequest != null) {
            if (netRequest.getNetEngine() != null) {

                if (netRequest.getOptions() != null) {
                    if (netRequest.getNetUIListener() != null) {
                        prepareCreateParameter();
                        this.parameter = netRequest.getNetUIListener().createNetParams();
                        if (this.parameter != null) {
                            //init success
                        } else {
                            throw new NetException("parameter 不能为空");
                        }
                    } else {
                        throw new NetException("uiListener 不能为空");
                    }
                } else {
                    throw new NetException("option 不能为空");
                }
            } else {
                throw new NetException("请设置一种执行网络任务的引擎");
            }


        } else {
            throw new NetException("NetRequest 不能为空");
        }
    }

    /**
     * Prepare create parameter.
     */
    public void prepareCreateParameter() {

    }

    /**
     * Use cache refresh ui.
     *
     * @param <T>        the type parameter
     * @param localValue the local value
     */
    public <T> void callback(String localValue) {

        if (!TextUtils.isEmpty(localValue)) {
            // 得到缓存数据


            T localResponseBean = GsonUtil.fromJsonStringToCollection(
                    localValue, getNetUiListener().getType());

            if (localResponseBean != null) {

                // 用缓存数据先刷新界面
                callback(
                        NetUtils.NetRequestStatus.SUCCESS, localResponseBean);

            }


        }

    }

    /**
     * 网络请求回调
     *
     * @param <T>              the type parameter
     * @param netRequestStatus the net request status
     * @param bean             the bean
     */
    public <T> void callback(
            final NetUtils.NetRequestStatus netRequestStatus, final T bean) {

        if (getNetUiListener() != null) {

            if (getOptions().isPostUIThread()) {
                //回调到UI线程

                if (getContext() != null && getContext() instanceof Activity) {
                    Activity activity = (Activity) getContext();
                    if (!activity.isFinishing()) {
                        boolean isDes = false;
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                            isDes = activity.isDestroyed();
                        }
                        if (!isDes) {
                            activity.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    getNetUiListener().onComplete(bean, netRequestStatus);
                                }
                            });


                        }
                    }


                }

            } else {
                //在任务执行线程运行回调
                getNetUiListener().onComplete(bean, netRequestStatus);
            }


        }


    }


    /**
     * 多线程池,适用于并行任务的执行.
     *
     * @param runnable the runnable
     */
    public static void executeMutipleRunnbale(Runnable runnable) {
        if (runnable != null) {
            executorMutipleService.execute(runnable);
        }

    }

    /**
     * Put handler info.
     *
     * @param key   the key
     * @param value the value
     */
    public void putHandlerInfo(String key, Object value) {
        if (!TextUtils.isEmpty(key)) {
            data.put(key, value);
        }

    }


    /**
     * Gets handler info.
     *
     * @param <T>      the type parameter
     * @param key      the key
     * @param classOfT the class of t
     * @return the handler info
     */
    public <T> T getHandlerInfo(String key, Class<T> classOfT) {
        if (!TextUtils.isEmpty(key) && classOfT != null) {
            Object object = data.get(key);
            if (object != null && classOfT.isInstance(object)) {
                return (T) object;


            }


        }
        return null;

    }

    /**
     * Start.
     */
    public void start() {
        NetOptions netOptions = getOptions();
        if (netOptions != null) {
            switch (netOptions.getRunMode()) {
                case SINGLE_THREAD_POOL:
                    executeRunnbale(this);
                    break;
                case MUTIPLE_THREAD_POOL:
                    executeMutipleRunnbale(this);
                    break;
                case CURRENT_THREAD:
                    this.run();
                    break;


            }
        }
    }

    /**
     * Gets options.
     *
     * @return the options
     */
    public NetOptions getOptions() {
        return netRequest.getOptions();
    }


    /**
     * Gets net engine.
     *
     * @return the net engine
     */
    public NetEngine getNetEngine() {
        return netRequest.getNetEngine();
    }


    /**
     * Gets context.
     *
     * @return the context
     */
    public Context getContext() {
        return netRequest.getContext();
    }


    /**
     * Gets net request.
     *
     * @return the net request
     */
    public NetRequestConfig getNetRequest() {
        return netRequest;
    }


    /**
     * Gets net ui listener.
     *
     * @return the net ui listener
     */
    public NetUIListener getNetUiListener() {
        return netRequest.getNetUIListener();
    }


    /**
     * Gets parameter.
     *
     * @return the parameter
     */
    public NetParameter getParameter() {
        return parameter;
    }

    /**
     * Gets net data parser.
     *
     * @return the net data parser
     */
    public NetDataParser getNetDataParser() {
        return netRequest.getDataParser();
    }

}

去实现一个通用的网络任务

public class CommonNetTask extends NetTask {
    /**
     * Instantiates a new Common net task.
     *
     * @param netRequest the net request
     */
    public CommonNetTask(NetRequestConfig netRequest) {
        super(netRequest);
    }

    /**
     * Run.
     */
    @Override
    public void run() {
        Object responseBean = null;
        NetUtils.NetRequestStatus netRequestStatus = NetUtils.NetRequestStatus.SERVER_ERROR;
        NetEngine engine = getNetEngine();


        NetRequestConfig netRequest = getNetRequest();
        NetResponseInfo netResponseInfo;
        NetRequestConfig.Method method = netRequest.getMethod();
        netResponseInfo = engine.request
                (getParameter(),netRequest.getMethod());
        String resultStr = null;
        NetUIListener netUIListener = getNetUiListener();
        Type type = netUIListener.getType();
        if (netResponseInfo != null && netResponseInfo.isSuccess()) {
            resultStr = netResponseInfo.getResult();
            netUIListener.setOriginalData(resultStr);//保存原始字符
            responseBean = netRequest.getDataParser().parse(resultStr, type);
            if (responseBean != null) {
                netRequestStatus = NetUtils.NetRequestStatus.SUCCESS;
            } else {
                netRequestStatus = NetUtils.NetRequestStatus.SERVER_ERROR;
            }
        } else {
            netRequestStatus = NetUtils.NetRequestStatus.NET_ERROR;
        }
        callback(netRequestStatus, responseBean);
    }
}

网络请求引擎,实现类一般是各种网络框架okhttp,httpclient.

public interface NetEngine {
    /**
     * Init context.
     *
     * @param context the context
     */
    void initContext(Context context);

     NetResponseInfo request(NetParameter params, NetRequestConfig.Method method);


    /**
     * Add task tag.
     *
     * @param taskTag the task tag
     */
    void addTaskTag(Object taskTag);

    /**
     * Cancel task.
     *
     * @param canceller the canceller
     */
    void cancelTask(Canceller canceller);


}





/**
 * 用okhttp网络框架实现{@link NetEngine}
 *
 * @version V1.0
 */
public class OkHttpNetEngine implements NetEngine {


    /**
     * The DEBUG TAG.
     */
    public static final String TAG = OkHttpNetEngine.class.getSimpleName();

    /**
     * Instantiates a new Ok http net engine.
     *
     * @param context the context
     */
    public OkHttpNetEngine(Context context) {
        initContext(context);
    }

    /**
     * Add task tag.
     *
     * @param taskTag the task tag
     */
    @Override
    public void addTaskTag(Object taskTag) {
        this.taskTag = taskTag;
    }

    /**
     * 任务TAG
     */
    private Object taskTag;

    /**
     * @version V1.0
     * @Title: Ok http excutor
     *  2016.12.02
     * @Title: Ok http excutor
     */
    private static class OkHttpExcutor {
        /**
         * M ok http client.
         */
        private static final OkHttpClient okHttpClient = new OkHttpClient();
        /**
         * 连接超时.
         */
        private static final int CONNECT_TIME_OUT_MS = 60 * 1000;
        /**
         * 读取超时.
         */
        private static final int READ_TIME_OUT_MS = 60 * 1000;


        static {
            okHttpClient.setConnectTimeout(CONNECT_TIME_OUT_MS,
                    TimeUnit.MILLISECONDS);
            okHttpClient.setWriteTimeout(READ_TIME_OUT_MS, TimeUnit.MILLISECONDS);
            okHttpClient.setReadTimeout(READ_TIME_OUT_MS, TimeUnit.MILLISECONDS);

            okHttpClient.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });


            try {
                SSLContext sslContext = SSLContext.getInstance("SSL");

                sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        X509Certificate[] x509Certificates = new X509Certificate[0];
                        return x509Certificates;
                    }
                }}, new SecureRandom());
                okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }

        }


        /**
         * Init persistent cookie store.
         *
         * @param context the context
         */
        public static void initPersistentCookieStore(Context context) {
            if (okHttpClient.getCookieHandler() == null) {
                if (context != null) {
                    Context application = context.getApplicationContext();
                    if (application != null) {
                        okHttpClient.setCookieHandler(new CookieManager(
                                new PersistentCookieStore(application), CookiePolicy.ACCEPT_ALL));


                    }
                }
            }

        }

        /**
         * Cancel task.
         *
         * @param taskTag the task tag
         */
        public static void cancelTask(Object taskTag) {
            if (taskTag != null) {
                okHttpClient.cancel(taskTag);
            }
        }

        /**
         * Request by post net response info.
         *
         * @param params  the params
         * @param taskTag the task tag
         * @param method  the method
         * @return the net response info
         */
        public static NetResponseInfo requestByMethod(NetParameter params, Object taskTag, NetRequestConfig.Method method) {
            NetResponseInfo netEventInfo = new NetResponseInfo();//返回信息
            Request.Builder builder = new Request.Builder();
            if (taskTag != null) {
                builder.tag(taskTag);
            }


            ResponseBody responseBody = null;
            try {
                FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
                //请求参数拼装
                List<KeyValuePair> list = params.createParameters();
              Request request =null;
                switch (method){
                    case GET:
                        String url = params.getRequestURL();
                        if (list != null && !list.isEmpty()) {
                            url += "?"
                                    + URLEncodedUtils.format(list, "UTF-8");
                        }
                        request = builder.url(url).build();
                        break;
                    case DELETE:
                        if (list != null && !list.isEmpty()) {
                            for (KeyValuePair keyValuePair : list) {
                                formEncodingBuilder.add(keyValuePair.getKey(),
                                        keyValuePair.getValue());

                            }
                        }
                        request = builder.url(params.getRequestURL())
                                .delete(formEncodingBuilder.build()).build();
                        break;
                    case POST:
                        if (list != null && !list.isEmpty()) {
                            for (KeyValuePair keyValuePair : list) {
                                formEncodingBuilder.add(keyValuePair.getKey(),
                                        keyValuePair.getValue());

                            }
                        }
                        request = builder.url(params.getRequestURL())
                                .post(formEncodingBuilder.build()).build();
                        break;
                    case PUT:
                        if (list != null && !list.isEmpty()) {
                            for (KeyValuePair keyValuePair : list) {
                                formEncodingBuilder.add(keyValuePair.getKey(),
                                        keyValuePair.getValue());

                            }
                        }
                        request = builder.url(params.getRequestURL())
                                .put(formEncodingBuilder.build()).build();
                        break;
                    default:
                        if (list != null && !list.isEmpty()) {
                            for (KeyValuePair keyValuePair : list) {
                                formEncodingBuilder.add(keyValuePair.getKey(),
                                        keyValuePair.getValue());

                            }
                        }
                        request = builder.url(params.getRequestURL())
                                .post(formEncodingBuilder.build()).build();
                        break;



                }
                Call call = okHttpClient.newCall(request);
                netEventInfo.setStartTime(String.valueOf(System.currentTimeMillis()));//网络耗时统计
                Response response = call.execute();
                netEventInfo.setEndTime(String.valueOf(System.currentTimeMillis()));//网络耗时统计
                netEventInfo.setHttpCode(String.valueOf(response.code()));///网络返回状态码
                if (response.isSuccessful()) {
                    netEventInfo.setSuccess(true);
                    responseBody = response.body();
                    if (responseBody != null) {
                        String reponseStr = responseBody.string();

                        if (!TextUtils.isEmpty(reponseStr)) {
                            //网络返回结果解码
                            netEventInfo.setResult(params.decodeResponse(reponseStr));
                        }
                    }


                }
            } catch (Exception e) {
                netEventInfo.setException(e.toString());//记录网络请求错误
            } finally {
                try {
                    responseBody.close();
                } catch (Exception e) {

                }


            }
            return netEventInfo;


        }


    }


    /**
     * Init context.
     *
     * @param context the context
     */
    @Override
    public void initContext(Context context) {
        if (context != null) {
            OkHttpExcutor.initPersistentCookieStore(context);
        }
    }

    @Override
    public NetResponseInfo request(NetParameter params, NetRequestConfig.Method method) {
       return OkHttpExcutor.requestByMethod(params, taskTag, method);
    }

    /**
     * Cancel task.
     *
     * @param canceller the canceller
     */
    @Override
    public void cancelTask(Canceller canceller) {
        if (canceller != null) {
            OkHttpExcutor.cancelTask(canceller.getTaskTag());
        }

    }

    private static final String POST = "POST";
    private static final String GET = "GET";
    private static final String PUT = "PUT";
    private static final String DELETE = "DELETE";


}

有 请求了肯定有回调啊,这个是必须的

public abstract  class NetUIListener<T> {

    /**
     * M type.
     */
    private Type mType;
    /**
     * Original data.
     */
    private String originalData;

    /**
     * Gets original data.
     *
     * @return the original data
     */
    public String getOriginalData() {
        return originalData;
    }

    /**
     * Sets original data.
     *
     * @param originalData the original data
     */
    public void setOriginalData(String originalData) {
        this.originalData = originalData;
    }

    /**
     * Instantiates a new Ui listener.
     */
    public NetUIListener() {
        mType = getSuperclassTypeParameter(getClass());

    }

    /**
     * Gets type.
     *
     * @return the type
     */
    public Type getType() {
        return mType;
    }


    /**
     * Gets superclass type parameter.
     *
     * @param subclass the subclass
     * @return the superclass type parameter
     */
    private Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return parameterized.getActualTypeArguments()[0];
    }

    public NetRequestConfig.Method getMethod(){
        return NetRequestConfig.Method.POST;
    }



    public abstract NetParameter createNetParams();
    /**
     * 在非主线程中组装参数适用于耗时的任务
     */
    public void assembleCommonParamsBeanBackground(){

    }

    /**
     * SUCCESS:服务器成功返回数据并GSON解析完成,业务处理
     * SERVER_ERROR:系统错误(例如gson解析错误)
     * NET_ERROR:网络错误
     * UI线程运行
     *
     * @param bean             the bean
     * @param netRequestStatus the net request status
     */
    public abstract void onComplete(T bean, NetUtils.NetRequestStatus netRequestStatus);

}




public abstract  class CommonNetUIListener<T>  extends NetUIListener<T> implements  ConfigUrl{
    @Override
    public NetParameter createNetParams() {
        return new CommonNetParameter(createUrl(),submitNetParams());
    }





    /**
     * 提交网络请求参数
     * return NULL,不发送网络请求,也不会有结果回调
     * UI线程运行
     *
     * @return the common params bean
     */
    public abstract List<KeyValuePair> submitNetParams();

}

网络返回数据解析类,具体可以实现 XML, JSON等格式的转换

public interface NetDataParser {

    /**
     * Parse t.
     *
     * @param data     the data
     * @param classOfT the class of t
     * @return the t
     */
    Object parse(Object data, Type classOfT);
}



public class JsonDataParser implements NetDataParser {

    /**
     * Parse t.
     *
     * @param data     the data
     * @param classOfT the class of t
     * @return the t
     */
    @Override
    public Object parse(Object data, Type classOfT) {
        if (data != null && classOfT != null) {

            if (data.getClass() != classOfT) {
                return GsonUtil.fromJsonStringToCollection(
                        String.valueOf(data), classOfT);
            } else {
                return data;
            }

        }

        return null;

    }

可以说费劲九牛二虎之力实现一个很原始的网络框架。。。。哈哈

猜你喜欢

转载自blog.csdn.net/atxxiang4/article/details/81290261
今日推荐