Afinal

这是Afinal在github的地址:https://github.com/yangfuhai/afinal

Afinal这个框架主要分4块:

1、FinalDB模块:android中的orm框架,一行代码就可以进行增删改查。支持一对多,多对一等查询。

2、FinalActivity模块:android中的ioc框架,完全注解方式就可以进行UI绑定和事件绑定。无需findViewById和setClickListener等。

3、FinalHttp模块:通过httpclient进行封装http数据请求,支持ajax方式加载。

4、FinalBitmap模块:通过FinalBitmap,imageview加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象。FinalBitmap可以配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等。FinalBitmap的内存管理使用lru算法,没有使用弱引用(android2.3以后google已经不建议使用弱引用,android2.3后强行回收软引用和弱引用,详情查看android官方文档),更好的管理bitmap内存。FinalBitmap可以自定义下载器,用来扩展其他协议显示网络图片,比如ftp等。同时可以自定义bitmap显示器,在imageview显示图片的时候播放动画等(默认是渐变动画显示)。

这里我们先讲FinalHttp模块,这是它的用法:

AjaxParams params = new AjaxParams();  params.put("username", "michael yang");  params.put("password", "123456");  params.put("email", "test@tsz.net");  params.put("profile_picture", new File("/mnt/sdcard/pic.jpg")); // 上传文件  params.put("profile_picture2", inputStream); // 上传数据流  params.put("profile_picture3", new ByteArrayInputStream(bytes)); // 提交字节流  FinalHttp fh = new FinalHttp();  fh.post("http://www.yangfuhai.com", params, new AjaxCallBack(){        @Override        public void onLoading(long count, long current) {                textView.setText(current+"/"+count);        }        @Override        public void onSuccess(String t) {            textView.setText(t==null?"null":t);        }  });

大家看到了吧,fh.get(baseUrl, params, new AjaxCallBack(){});

这句话的底层就是HttpClient执行HttpGet或者HttpPost请求的一个封装,其中baseUrl+params拼凑起来就是url,而后面的AjaxCallBack就是对HttpClient对http请求得到的一个HttpResponse响应结果的分析回调。

我们来看具体的流程步骤:

第一步:初始化FinalHttp,然后执行get()方法

public void get( String url, AjaxParams params, AjaxCallBack<? extends Object> callBack) {        sendRequest(httpClient, httpContext, new HttpGet(getUrlWithQueryString(url, params)), null, callBack);    }

第二步:我们看sendRequest()这个方法,这个方法就是把get方法里的参数传递到这个函数,然后发起http请求。

protected <T> void sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, AjaxCallBack<T> ajaxCallBack) {        if(contentType != null) {            uriRequest.addHeader("Content-Type", contentType);        }        new HttpHandler<T>(client, httpContext, ajaxCallBack,charset)        .executeOnExecutor(executor, uriRequest);    }

这是一个保护级的方法,其实还是一个马甲,正真执行的还是那个HttpHandler里的exe方法。我们看到这个方法的参数有DefaultHttpClient,这个都不用说了大家都很熟悉,HttpContext就是一个上下文,HttpUriRequest就是一个get,put,delete,post等http请求,然后就是添加头部信息,比如要不要进行压缩,这里貌似用了zip压缩使得传输速率更快,再后面就是回调函数接口,判断请求是否成功失败等。

第三步:进入HttpHandler类,这是一个处理http请求的类。这个类是继承AsyncTask,但是这个AsyncTask类并不是原生的,而是经过作者精心修改的。没有深入去看AsyncTask,大略看了一下,貌似doInBackground这个方法是放进一个线程池里去执行的。这个线程池配置的很精细,就像批量加载图片那个例子,可以只想你个完上一个线程,就马上执行下一个任务。

1.这个类还实现了EntityCallBack回调接口,并且接收了AjaxCallBack这个回调实例。我们先看doInBackground方法。

protected Object doInBackground(Object... params) {        if(params!=null && params.length == 3){            targetUrl = String.valueOf(params[1]);            isResume = (Boolean) params[2];        }        try {            publishProgress(UPDATE_START); // 开始            makeRequestWithRetries((HttpUriRequest)params[0]);                    } catch (IOException e) {            publishProgress(UPDATE_FAILURE,e,e.getMessage()); // 结束        }        return null;    }

2.可以看到真正执行的方法是makeRequestWithRetries(HttpUriRequest *)方法,进去看看先

private void makeRequestWithRetries(HttpUriRequest request) throws IOException {        if(isResume && targetUrl!= null){            File downloadFile = new File(targetUrl);            long fileLen = 0;            if(downloadFile.isFile() && downloadFile.exists()){                fileLen = downloadFile.length();            }            if(fileLen > 0)                request.setHeader("RANGE", "bytes="+fileLen+"-");        }                boolean retry = true;        IOException cause = null;        HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();        while (retry) {            try {                if (!isCancelled()) {                    HttpResponse response = client.execute(request, context);                    if (!isCancelled()) {                        handleResponse(response);                    }                 }                return;            } catch (UnknownHostException e) {                publishProgress(UPDATE_FAILURE, e,"unknownHostException:can't resolve host");                return;            } catch (IOException e) {                cause = e;                retry = retryHandler.retryRequest(cause, ++executionCount,context);            } catch (NullPointerException e) {                // HttpClient 4.0.x 之前的一个bug                // http://code.google.com/p/android/issues/detail?id=5255                cause = new IOException("NPE in HttpClient" + e.getMessage());                retry = retryHandler.retryRequest(cause, ++executionCount,context);            }catch (Exception e) {                cause = new IOException("Exception" + e.getMessage());                retry = retryHandler.retryRequest(cause, ++executionCount,context);            }        }        if(cause!=null)            throw cause;        else            throw new IOException("未知网络错误");    }

其中isResume是断点续传标志,targetUrl判断是文件的话就添加文件大小头部信息。retry是遇到错误是否要重试标志,FinalHttp有这个参数配置,可以设置重试次数。然后就是HttpClient执行Http请求获取响应的操作,如果这个过程中UI上的交互有取消操作的话。可以通过isCancelled()这个方法得知从而取消请求。如果请求顺利会得到一个HttpResponse,而处理这个响应结果是handleResponse()方法。

3.这是专门处理响应结果的方法

private void handleResponse(HttpResponse response) {        StatusLine status = response.getStatusLine();        if (status.getStatusCode() >= 300) {            String errorMsg = "response status error code:"+status.getStatusCode();            if(status.getStatusCode() == 416 && isResume){                errorMsg += " \n maybe you have download complete.";            }            publishProgress(UPDATE_FAILURE,new HttpResponseException(status.getStatusCode(), status.getReasonPhrase()),errorMsg);        } else {            try {                HttpEntity entity = response.getEntity();                Object responseBody = null;                if (entity != null) {                    time = SystemClock.uptimeMillis();                    if(targetUrl!=null){                        responseBody = mFileEntityHandler.handleEntity(entity,this,targetUrl,isResume);                    }                    else{                        responseBody = mStrEntityHandler.handleEntity(entity,this,charset);                    }                                        }                publishProgress(UPDATE_SUCCESS,responseBody);                            } catch (IOException e) {                publishProgress(UPDATE_FAILURE,e,e.getMessage());            }                    }    }

通过状态码,判断成功后处理得到的HttpEntity。如果这个response是字符串就由StringEntityHandler这个类去解析,如果是文件就是FileEntityHandler解析。得到结果后,就是publishProgress去推送了,这个方法在前面的方法中都看到有被调用。稍微对AsyncTask熟悉的人就知道这个方法将可以触发onProgressUpdate(* value).这个方法就是告诉你执行的进度,AfinalHttp中AjaxCallback中的onSuccess,onFailure等方法就是根据这个来触发的。

   private final static int UPDATE_START = 1;    private final static int UPDATE_LOADING = 2;    private final static int UPDATE_FAILURE = 3;    private final static int UPDATE_SUCCESS = 4;

到这里这个过程就完成了。

看到这么多的处理,会觉得这样是不是会更慢。一个网络请求处理的极其复杂,想FinalHttp很多默认的配置和繁杂的处理响应并通知处理进程,其实这样多多少少拖慢了请求的速度。在实际应用尤其感受深切,一遇到网络慢,跨地域幅度大等教为恶劣的网络环境,AFinal就有点显得捉襟见肘了。

由于篇幅限制,这次就讲这么多了。

更多相关文章

  1. Android ViewPager 取消预加载
  2. androidの自定义控件View在Activity中使用findByViewId得到结果
  3. Android 获取蓝牙Mac地址的正确方法
  4. 提高android文档加载速度
  5. 分析方法论探讨
  6. android中的多线程基础问题
  7. android 程序开发的插件化 模块化方法 之二
  8. 从源码分析RxJava在Android里线程切换的实现
  9. Android UI 的更新及其线程模型

随机推荐

  1. Android中检测更新、通知、下载等
  2. 在 Android* 平台上设置原生 OpenGL ES*
  3. android studio2.0出现的gradle问题,inst
  4. Android CRT Screen 电视效果
  5. 【Android】Android Market 链接的生成与
  6. Android核心基础(三)
  7. Java/Android(安卓)Annotation processor
  8. Android Dalvik虚拟机初识
  9. Android(安卓)开发环境下载地址
  10. android 在listview上的 gallery 禁止上