1.this libaray is base on AsyncTask ,AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

2.I encapsulate http request params into Request . you can access the cloud like this:

final Request request = new Request(url);// link url , the default constructor is GET request

request.addHeader("accept", "application/json");    // set request headers

request.addPostParams(key, value); // set post content

request.setRequestListener(new IRequestListener() {// when the AsyncTask execute , it will callback let code to handle something

@Override

public void onProgressUpdate(int status, int curPos, int totalPos) {// callback to update UI progress

@Override

public void onPreExecute() {    // callback , this is in UI thread , you may show progress or do sth prepare

}

@Override

public void onPostExecute() {   // callback , this is in UI thread , you may show the tips that http has done

}

@Override

public void onPrepareParams(OutputStream out) { // callback , you can use OutputStream to push the post content yourself

}

@Override

public void onCancelled() {    // callback , this is in UI thread , you may show that the http connection has been cancelled

}

@Override

public void onBeforeDoingBackground() {  // callback , this is in Sub thread , you may do sth preparation , like query db , prepare the post params.

}

@Override

public Object onAfterDoingBackground(Object object) {  // callback , this is in Sub thread, you may do sth that insert/update db , create files .etc

return null;

}

});

request.setCallback(new JsonCallback<Companies>() {// callback , this is in UI thread , will return the data that http response.

@Override

public void onCallback(Companies callback) {// the callback can be DTOs , path that write data into file , or just String data

for (Company company : callback.companies) {

Trace.d(company.toString());

}

assertTrue(callback.companies.size() > 0);

}

@Override

public void onFailure(Exception e) {// e can be CloudException , AbortException or other RuntimeException

throw new AssertionError(e.toString());

}

}.setReturnType(Companies.class)

.setFilePath(path) // if you want save the data into file first , you can setFilePath(path).

);// setReturnType , if you want callback to return you the exactly DTO , pls set the Class and use JsonCallback , it will deserialize automatically , and return object to you

request.execute();// execute the code to http access. if you just for test ,pls call request.test()  . this method is only for test .

 

首先分析下需求。

在Android里,我们常常要通过网络去获取数据,然后更新UI,网络请求当然要放到子线程里,然后更新UI在主线程,所以基于这样的需求,Android才提供了AsyncTask,所以我们再基于AsyncTask再做一次封装,这样,网络请求就变的方便的多。你再也不用烦躁于线程切换,重复写代码了。一个好车轮能让你省很多时间。

首先定义一个Request类,把所有可能用到的参数define在里面,比如callback(服务器返回的数据),params(push到服务器的data),listener(下载进度,执行过程)。。。

网络请求有Get Post。。为了低耦合,基本都要拆开,比如我会用HttpClient 也可能用HttpUrlConnection.那么写个HttpUtil用来封装http的请求代码。这里定义一个execute()方法,在这个方法里判断是get还是post请求,再去call get() post() 方法,那么post请求需要push data到服务器,所以你要把params设置到Request中,有可能你需要push file到服务器,所以我添加了一个回调方法,把OutputStream传回去,手动的把file flush到Stream中。

在AsyncTask中,在doingBackground()方法中execute http,然后再调用AbstractCallback预先处理服务器返回的InputStream,如果data不大,可以直接写到内存变成String返回,如果data比较大,建议写到tmp文件里,把path返回,在不同的callback里再处理。所以就会有不同的callback,StringCallback PathCallback JsonCallback 你也可以根据你的特殊需求来定义不同的callback,你也可以在callback里将数据deserialize到database中。这样创建一个网络请求代码就会非常轻松。

贴个AbstractCallback处理流的方法,因为我没装代码插件,大家先凑合看,改天我加上了就会好很多了。

public Object handleConnection(HttpURLConnection response,

IProgressListener task) throws Exception {

try {

checkIsCancelled();

int statusCode = response.getResponseCode();

long contentLength = response.getContentLength();

InputStream in = null;

if (statusCode == HttpStatus.SC_OK) {

String encoding = response.getContentEncoding();

if (encoding != null && "gzip".equals(encoding))

in = new GZIPInputStream(response.getInputStream());

else if (encoding != null && "deflate".equals(encoding))

in = new InflaterInputStream(response.getInputStream());

else

in = response.getInputStream();

// if set path , write the data into file

if (!TextUtils.isEmpty(path)) {

FileOutputStream fos = new FileOutputStream(path);

byte[] b = new byte[IO_BUFFER_SIZE];

int curPos = 0;

int read;

while ((read = in.read(b)) != -1) {

checkIsCancelled();

if (task != null) {

curPos += read;

task.onProgressUpdate(

IProgressListener.DOWNLOADING,

curPos / 1000, contentLength == -1 ? -1

: (int) (contentLength / 1000));

}

fos.write(b, 0, read);

}

fos.flush();

fos.close();

in.close();

return bindData(path, task);

} else {

return bindData(

new String(IOUtilities.readStreamToMemory(in)), task);

}

} else {

throw new CloudException(statusCode,

response.getResponseMessage(), new String(

IOUtilities.readStreamToMemory(response

.getErrorStream())));

}

} finally {

if (response != null) {

response.disconnect();

response = null;

}

}

}

写框架,你必须要考虑全面,想所有不同的可能性,但是要有个度,全部想要封装也是很难的,所以基于不同的项目,框架也会发生改变。大家也不要迷信于某个框架能满足你所有的需求。你应该造你需要的轮子,能跑的最快的轮子。

源代码改天再提供。大家可以先自己考虑考虑,搭框架不难,主要是要有个全局观。也就是代码写的多了,烦了,想偷懒了,框架雏形就出来了。

posted on 2012-11-02 13:05  stay  阅读(3693)  评论(3编辑  收藏  举报