Android开源框架android-async-http的学习

来源:互联网 发布:天狼星期货软件 编辑:程序博客网 时间:2024/04/30 11:01

Android-async-http的地址

http://loopj.com/android-async-http/

官方的解释是这样的:

An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries. All requests are made outside of your app’s main UI thread, but any callback logic will be executed on the same thread as the callback was created using Android’s Handler message passing. You can also use it in Service or background thread, library will automatically recognize in which context is ran.

它是一个专门针对Android在Apache的HttpClient库基础上构建的异步的回调。他的所有的请求都在app的主线程之外。但是任何callback洛奇将会在它被创建的那个线程中执行通过使用Android的Hnadler message机制传递。你也可以使用他在后台线程的服务上,这个库将会自动识别他在哪种context上运行。

Android-async-http的特征

这里写图片描述

主要特性是

  1. 发送异步的HTTP请求,使用匿名回调处理responses
  2. HTTP请求发生在主线程之外
  3. 内部采用线程池来处理并发请求
  4. 通过RequestParams类构造GET/POST
  5. 内置多部分文件上传,不需要第三方库支持
  6. 流式Json上传,不需要额外的库
  7. 能处理环形和相对重定向
  8. 占用空间很小相对于你的应用,所有的东西大于只有90kb
  9. 在各种各样的移动连接环境中具备自动智能请求重试机制
  10. 自动的gzip响应解码
  11. 内置多种形式的响应解析,(Binary、JSON、File) HttpResponseHandler
  12. 永久的cookie保存,内部实现用的是Android的SharedPreferences
  13. 通过BaseJsonHttpResponseHandler和各种json库集成
  14. 支持SAX解析器
  15. 支持各种语言和content编码,不仅仅是UTF-8

如何使用

eclipse需要将jar包导入,官方链接有下载

新建一个AsyncHttpClient实例,并发送请求,官方是这样的:

AsyncHttpClient client = new AsyncHttpClient();client.get("https://www.google.com", new AsyncHttpResponseHandler() {    @Override    public void onStart() {        // called before request is started    }    @Override    public void onSuccess(int statusCode, Header[] headers, byte[] response) {        // called when response HTTP status is "200 OK"    }    @Override    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {        // called when response HTTP status is "4XX" (eg. 401, 403, 404)    }    @Override    public void onRetry(int retryNo) {        // called when request is retried    }});

然后还说了,推荐使用封装一个抽象工具类

Recommended Usage: Make a Static Http Client,给出了一个封装的例子对推特的访问

import com.loopj.android.http.*;public class TwitterRestClient {  private static final String BASE_URL = "https://api.twitter.com/1/";  private static AsyncHttpClient client = new AsyncHttpClient();  public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {      client.get(getAbsoluteUrl(url), params, responseHandler);  }  public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {      client.post(getAbsoluteUrl(url), params, responseHandler);  }  private static String getAbsoluteUrl(String relativeUrl) {      return BASE_URL + relativeUrl;  }}
import org.json.*;import com.loopj.android.http.*;class TwitterRestClientUsage {    public void getPublicTimeline() throws JSONException {        TwitterRestClient.get("statuses/public_timeline.json", null, new JsonHttpResponseHandler() {            @Override            public void onSuccess(int statusCode, Header[] headers, JSONObject response) {                // If the response is JSONObject instead of expected JSONArray            }            @Override            public void onSuccess(int statusCode, Header[] headers, JSONArray timeline) {                // Pull out the first event on the public timeline                JSONObject firstEvent = timeline.get(0);                String tweetText = firstEvent.getString("text");                // Do something with the response                System.out.println(tweetText);            }        });    }}

可以看到,使用非常简单。

添加GET/POST请求

Create empty RequestParams and immediately add some parameters:

RequestParams params = new RequestParams();params.put("key", "value");params.put("more", "data");

Create RequestParams for a single parameter:

RequestParams params = new RequestParams("single", "value");

Create RequestParams from an existing Map of key/value strings:

HashMap<String, String> paramMap = new HashMap<String, String>();paramMap.put("key", "value");RequestParams params = new RequestParams(paramMap);

Add an InputStream to the RequestParams to upload:

InputStream myInputStream = blah;RequestParams params = new RequestParams();params.put("secret_passwords", myInputStream, "passwords.txt");

Add a File object to the RequestParams to upload:

File myFile = new File("/path/to/file.png");RequestParams params = new RequestParams();try {    params.put("profile_picture", myFile);} catch(FileNotFoundException e) {}

Add a byte array to the RequestParams to upload:

byte[] myByteArray = blah;RequestParams params = new RequestParams();params.put("soundtrack", new ByteArrayInputStream(myByteArray), "she-wolf.mp3");

Downloading Binary Data with FileAsyncHttpResponseHandler

AsyncHttpClient client = new AsyncHttpClient();client.get("https://example.com/file.png", new FileAsyncHttpResponseHandler(/* Context */ this) {    @Override    public void onSuccess(int statusCode, Header[] headers, File response) {        // Do something with the file `response`    }});

BinaryHttpResponseHandler下载文件

client.get("http://download/file/test.java", new BinaryHttpResponseHandler() {    @Override    public void onSuccess(byte[] arg0) {        super.onSuccess(arg0);        File file = Environment.getExternalStorageDirectory();        File file2 = new File(file, "down");        file2.mkdir();        file2 = new File(file2, "down_file.jpg");        try {            FileOutputStream oStream = new FileOutputStream(file2);            oStream.write(arg0);            oStream.flush();            oStream.close();        } catch (Exception e) {            e.printStackTrace();            Log.i(null, e.toString());        }    }});

总结

  1. AsyncHttpResponseHandler是一个请求返回处理、成功、失败、开始、完成等自定义的消息的类
  2. BinaryHttpResponseHandler是继承AsyncHttpResponseHandler的子类,这是一个字节流返回处理的类,用于处理图片等类。
  3. JsonHttpResponseHandler是继承AsyncHttpResponseHandler的子类,这是一个json请求返回处理服务器与客户端用json交流时使用的类。
  4. AsyncHttpRequest继承自Runnable,是基于线程的子类,用于异步请求类, 通过AsyncHttpResponseHandler回调。

使用实例

该例子主要封装了对知乎日报API的请求,使用获取图片的API,将图片保存至手机上,程序进入时将保存的图片显示出来。
知乎日报API地址:
https://github.com/iKrelve/KuaiHu/blob/master/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5API.md

发送获取图片的请求

这里写图片描述

首先要将知乎日报的API请求封装起来

public class Constant {    public static final String BASEURL = "http://news-at.zhihu.com/api/4/";    public static final String START = "start-image/1080*1776";    public static final String THEMES = "themes";    public static final String LATESTNEWS = "news/latest";    public static final String BEFORE = "news/before/";    public static final String THEMENEWS = "theme/";    public static final String CONTENT = "news/";    public static final int TOPIC = 131;    public static final String START_LOCATION = "start_location";    public static final String CACHE = "cache";    public static final int LATEST_COLUMN = Integer.MAX_VALUE;    public static final int BASE_COLUMN = 100000000;}

封装的HttpUtil

import android.content.Context;import android.net.ConnectivityManager;import android.net.NetworkInfo;import com.loopj.android.http.AsyncHttpClient;import com.loopj.android.http.AsyncHttpResponseHandler;public class HttpUtil {    private static AsyncHttpClient client = new AsyncHttpClient(true,80,443);    public static void get(String url, AsyncHttpResponseHandler responseHandler) {        client.get(Constant.BASEURL + url, responseHandler);    }    public static void getImage(String url,AsyncHttpResponseHandler responseHandler){        client.get(url, responseHandler);    }    public static boolean getNetworkConneced(Context context) {        if (context != null) {            ConnectivityManager manager = (ConnectivityManager) context                    .getSystemService(Context.CONNECTIVITY_SERVICE);            NetworkInfo networkInfo = manager.getActiveNetworkInfo();            if(networkInfo!=null){            return networkInfo.isAvailable();            }else{                return false;            }        }        return false;    }}

主要提供了三个静态方法,一个是get里面将参数的url加上baseurl,第二个是getImage,第三个是判断网络是否链接的方法

主界面是一个ImageView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="${relativePackage}.${activityClass}" >    <ImageView         android:id="@+id/main_show_ImageView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scaleType="fitXY"        android:adjustViewBounds="true"        /></RelativeLayout>

Activity的方法

public class SplashActivity extends Activity {    private static final String TAG = "MainActivity";    private ImageView mShowImageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_splash);        mShowImageView = (ImageView) findViewById(R.id.main_show_ImageView);        initImage();    }    private void initImage() {        File dir = getFilesDir();        final File imgFile = new File(dir, "start.jpg");        //如果照片存在的话,就使用下载的图片,不存在的话就使用mipmap中的start图片        if (imgFile.exists()) {            mShowImageView.setImageBitmap(BitmapFactory.decodeFile(imgFile                    .getAbsolutePath()));        } else {            mShowImageView.setImageResource(R.mipmap.start);        }        //判断网络是否可用        if (HttpUtil.getNetworkConneced(SplashActivity.this)) {            //使用HttpUtil发送获取图片的请求            HttpUtil.get(Constant.START, new AsyncHttpResponseHandler() {                @Override                public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {                    JSONObject object;                    //将返回的JSON数据解析,得到img的地址                    try {                        object = new JSONObject(new String(arg2));                        String url = object.getString("img");                        //通过HttpUtil将图片的地址请求过去,并使用BinaryHttpResponseHandler处理图片                        HttpUtil.getImage(url, new BinaryHttpResponseHandler() {                            @Override                            public void onSuccess(int arg0, Header[] arg1,                                    byte[] arg2) {                                saveImage(imgFile, arg2);                            }                            @Override                            public void onFailure(int arg0, Header[] arg1,                                    byte[] arg2, Throwable arg3) {                            }                        });                    } catch (JSONException e) {                        e.printStackTrace();                    }                }                @Override                public void onFailure(int arg0, Header[] arg1, byte[] arg2,                        Throwable arg3) {                }            });        } else {            Toast.makeText(SplashActivity.this, "没有网络连接", Toast.LENGTH_LONG)                    .show();        }    }    //保存图片    public void saveImage(File path, byte[] bytes) {        if (path.exists()) {            path.delete();        }        try {            FileOutputStream out = new FileOutputStream(path);            out.write(bytes);            out.flush();            out.close();        } catch (Exception e) {            e.printStackTrace();        }    }}

首次启动应用

这里写图片描述

再次启动

这里写图片描述

注意权限,加上网络连接以及访问存储设备和查看网络状态的权限。

0 0
原创粉丝点击