网络框架AndNet—解放你的时间

Posted 亓斌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络框架AndNet—解放你的时间相关的知识,希望对你有一定的参考价值。

吐槽

我们做移动开发的,网络操作可以说是最最常用的技术了,而在网络操作中http又是一块最常见的的方式,返回json的http请求可以说是我们日常最长干的活。你一般用什么框架去请求http呢?Volley?OkHttp? 不管哪种方式用起来是不是还是不那么的方便,我们依然要写大量的请求、解析、返回的代码。好,这篇博客,不是让你替换掉你最常用的那个网络框架,而是在你熟悉的框架之上二次封装!目的就是为了解放你的时间,让网络操作更简单、漂亮。

需求

虽然现在我们有诸如Volley、OkHttp等很好的框架使用,但是你是不是还感觉这部分还是那么的麻烦?你是不是想让每次请求到解析出来几行代码就可以搞定?
下面的两种方式你更喜欢哪种?

MultipartBuilder builder = new MultipartBuilder()
        .type(MultipartBuilder.FORM);

...
builder.addPart(Headers.of("Content-Disposition",
        "form-data; name=\\""+ key +"\\""),
        RequestBody.create(null, map.get(key)));
...

Request request = new Request.Builder()
        .url(url).post(builder.build()).build();
call(request, parser, callback);
RequestParams params = new RequestParams("name", "loader");
params.add("age", 18).add("city", "jinan");
Net.post("http://192.168.3.116/", params, new CommParser<User>("user") 
        ,
        new Net.Callback<User>() 
            @Override
            public void callback(Result<User> result) 
                if(result.getStatus() == Result.SUCCESS) 
                    User user = result.getResult();

                    mTextView.setText(user.getName());
                   ...
                else 
                    mTextView.setText(result.getMsg());
                
            
        );

显然第二种方式是我们想要的,有了需求,那我们就得考虑封装了,我在不断尝试以后,终于完成了这种优雅方式的框架的一个小封装,哦,给了它一个特别骚的名字-AndNet,AndNet不仅仅具备上面的便捷功能,它还允许我们随时任意更换我们使用的底层网络请求框架,而不需要改动我们的业务逻辑代码,这一点太棒了!哪天Volley不再适合我们了,我们可以直接切换到OkHttp,而我们的业务代码不需要任何的改变,兴奋ing,下面就让我们开始尝试使用AndNet吧。

准备工作

AndNet默认的网络请求框架是使用的OkHttp,所以你需要在你的项目中添加一下两个依赖:

compile 'com.squareup.okhttp:okhttp:2.0.0'
compile 'com.squareup.okio:okio:1.5.0'

接下来,我们需要自定义一个Application,在它的onCreate中添加一行代码,

Net.init(new OkHttpStack());

现在我们就指定使用默认的网络请求框架OkHttp,当然如果我们想切换框架,也是在这里做。

自定义parser

在我们开始使用之前,还需要做一件事就是根据你们项目使用的json格式,定义需要的json的parser类,parser部分我是很想写到框架里面的,不过那样灵活性就差了,所以这里还是需要我们在自己的项目里写自己的parser。
假如现在我们json的格式如下,


  success: true,
  message: "",
  user: - 
    age: "18",
    name: "loader",
    city: "jinan"
  

这种格式在我们项目中肯定是固定的,所以我们无需担心格式泛滥,json的解析你可以任意写,不过还是推荐使用fastjson来搞,这样太方便了。
来看看根据这种格式写出来的parser什么样吧。

public class CommParser<T> implements Net.Parser<T> 

    private String mKey;

    public CommParser(String key) 
        mKey = key;
    

  @Override
    public Result<T> parse(String response) 
        Result<T> result = new Result<T>();
        try 
            JSONObject baseObject = JSON.parseObject(response);
            if(!baseObject.getBooleanValue("success")) 
                result.setMsg(baseObject.getString("message"));
            else 
                Class<T> klass = Helper.generateType(getClass());
                if(klass == null) throw new Exception();

                T t = baseObject.getObject(mKey, klass);
                result.setStatus(Result.SUCCESS);
                result.setResult(t);
                return result;
            
         catch (Exception e) 
            e.printStackTrace();
            result.setMsg(Net.ERR_PARSE_MSG);
        

        result.setStatus(Result.ERROR);
        return result;
    

首先这个Parser要知道我们关心哪个部分内容,所以我们需要在构造里传递一个key,对应上面的json格式就是user啦,接下来我们重写parse方法,使用fastjson将我们需要的数据解析出来了,这里面我们使用了Helper.generateType方法,这个方法是AndNet提供的一个方法,目的就是获取泛型的类型,我们CommParser的是泛型的。在你的项目中,你完全可以copy一下这个parser,然后改成你的逻辑。

ok, 既然parser我们定义好了,那我们接下来就进入AndNet的使用吧。

使用AndNet做get请求

get请求很简单,不需要任何参数,我们直接使用

Net.get(final String url, final Parser<T> parser, final Callback<T> callback);

就可以了

Net.get("http://192.168.3.116/?name=loader&age=18&city=jinan",
        new CommParser<User>("user") , new Net.Callback<User>() 
    @Override
    public void callback(Result<User> result) 
        if(result.getStatus() == Result.SUCCESS) 
            User user = result.getResult();

            mTextView.setText(user.getName());
            mTextView.append("\\n" + user.getAge());
            mTextView.append("\\n" + user.getCity());
        else 
            mTextView.setText(result.getMsg());
        
    
);

调用一个方法,我们就搞定了从请求到解析的操作,是不是很方便!

使用AndNet做post请求

post请求估计是使用Net.post了,它的原型是:

Net.post(final String url, final RequestParams params, final Parser<T> parser, final Callback<T> callback);

仅仅多了一个RequestParams的参数,这个参数就是我们需要post的参数了,下面来看看post怎么使用,

RequestParams params = new RequestParams("name", "loader");
params.add("age", 18).add("city", "jinan");
Net.post("http://192.168.3.116/", params, new CommParser<User>("user") 
        ,
        new Net.Callback<User>() 
            @Override
            public void callback(Result<User> result) 
                if(result.getStatus() == Result.SUCCESS) 
                    User user = result.getResult();

                    mTextView.setText(user.getName());
                    mTextView.append("\\n" + user.getAge());
                    mTextView.append("\\n" + user.getCity());
                else 
                    mTextView.setText(result.getMsg());
                
            
        );

和get一样简单,只不过是RequestParams构造出来的参数。另外AndNet还提供了另外一种post的方式,使用起来也特别爽-直接传递一个java bean!
首先我们定义一个参数的javabean,我们提交的参数有:name、age、city。

public class User implements IBaseBean 
    @Annotation(key = "name")
    private String name;
    @Annotation(key = "age")
    private int age;
    @Annotation(key = "city")
    private String city;

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getCity() 
        return city;
    

    public void setCity(String city) 
        this.city = city;
    

    public int getAge() 
        return age;
    

    public void setAge(int age) 
        this.age = age;
    

    @Override
    public String toString() 
        return "name=" + name + ",age=" + age + ",city=" + city;
    

User实现了IBaseBean接口,这个接口是一个空接口,仅仅代表它是一个可以作为参数的类,User里的字段我们使用了Annotation注解来标记它所对应的参数的key。
定义完bean后,我们接下来就是提交它的操作了。

User user = new User();
user.setName("qibin");
user.setCity("shandong");
user.setAge(18);

Net.post("http://192.168.3.116/", user, new CommParser<User>("user") 
        , new Net.Callback<User>() 
            @Override
            public void callback(Result<User> result) 
                if(result.getStatus() == Result.SUCCESS) 
                    mTextView.setText(result.getResult().toString());
                else 
                    mTextView.setText(result.getMsg());
                
            
        );

和上面普通的post一样,这里我们仅仅是将RequestParams替换成了User的对象。这种方式是不是看起来更加清爽呢!

文件上传

AndNet支持文件上传,不过这里的支持还是得依靠我们的HttpStack的实现,默认提供了OkHttpStack就支持文件上传操作,文件上传操作和我们上面说的post操作没有任何区别,只需要给RequestParams一个File类型的值就ok。

RequestParams params = new RequestParams("name", "qibin");
params.add("file", new File(Environment.getExternalStorageDirectory()
        + "/demo.doc"));
Net.post("http://192.168.3.116/upload.php", params, new Net.NoParser(),
        new Net.Callback<String>() 
    @Override
    public void callback(Result<String> result) 
        mTextView.setText(result.getResult() + "");
    
);

其他任何特殊的代码都没有,这样我们就完成了上传功能。

AndNet的高级使用-自定义HttpStack

上面提到过,AndNet支持切换使用的网络框架,这就需要我们自定义HttpStack来实现,自定义HttpStack我们需要继承AbsHttpStack,下面我们就以自定义VolleyStack为例,替换默认的OkHttp,

public class VolleyStack<T> extends AbsHttpStack<T> 

    private Application mContext;

    public VolleyStack(Application context) 
        mContext = context;
    

    /**
     * get请求
     *
     * @param url      网址
     * @param parser   解析器
     * @param callback 回调
     */
    @Override
    public void get(String url, Net.Parser<T> parser,
                    Net.Callback<T> callback, final Object tag) 
        invoke(Request.Method.GET, url, null, parser, callback, tag);
    

    /**
     * post请求
     *
     * @param url      访问的url
     * @param params   post参数
     * @param parser   解析器
     * @param callback 回调
     */
    @Override
    public void post(String url, RequestParams params,
                     Net.Parser<T> parser,
                     Net.Callback<T> callback,
                     final Object tag) 
        invoke(Request.Method.POST, url, params, parser, callback, tag);
    

    /**
     * 执行网络请求
     *
     * @param url
     * @param params   post时请求的参数 get时为null
     * @param parser
     * @param callback
     * @param method
     */
    private void invoke(final int method, final String url,
                        final RequestParams params,
                        final Net.Parser<T> parser,
                        final Net.Callback<T> callback,
                        final Object tag) 
        StringRequest request = new StringRequest(method, url,
                new Response.Listener<String>() 
                    public void onResponse(String response) 
                        onNetResponse(parser, callback, response);
                    
                , new Response.ErrorListener() 
            public void onErrorResponse(VolleyError error) 
                error.printStackTrace();
                onError(callback, Net.DEF_ERR_MSG);
            
        ) 
            @Override
            protected Map<String, String> getParams()
                    throws AuthFailureError 
                if (params != null) return params.get();
                return super.getParams();
            
        ;

        VolleyManager.getInstance(mContext).add(request, tag);
    

    @Override
    public void cancel(Object tag) 
        VolleyManager.getInstance(mContext).cancel(tag);
    

这里重写了AbsHttpStack的getpost方法,这里面都调用了我们自定义的invoke方法,在invoke中我们使用Volley进行网络请求,在请求成功后调用了onNetResponse(parser, callback, response)方法,
在请求失败后调用了onError(callback, Net.DEF_ERR_MSG)方法,这两个方法在AbsHttpStack已经实现,我们无需关心。
好了,新的HttpStack定义好了,那我们就来切换一下吧。

public class App extends Application 

    @Override
    public void onCreate() 
        super.onCreate();
        Net.init(new VolleyStack(this));
//        Net.init(new OkHttpStack());
    

修改一行代码,就完成了网络框架的切换,而我们的业务代码无需任何变动,是不是很爽?

AndNet的高级使用-添加header

有时候我们的项目需要一些自定义的header,我们完全可以通过扩展OkHttpStack来完成这个功能。

public class OkHttpHeaderStack<T> extends OkHttpStack<T> 

    @Override
    public LinkedHashMap<String, String> headers() 
        LinkedHashMap<String, String> headers = new LinkedHashMap<>();
        headers.put("name", "header");
        return headers;
    

我们继承了OkHttpStack类,并重写了headers方法,将我们需要的header放到一个map里返回,再次替换我们使用的HttpStack

public class App extends Application 

    @Override
    public void onCreate() 
        super.onCreate();
//        Net.init(new VolleyStack(this));
//        Net.init(new OkHttpStack());
        Net.init(new OkHttpHeaderStack());
    

完美解决! 好了,这样AndNet的功能我们就学习完了,最后是AndNet的下载地址,包含了源码、jar包和实例代码,欢迎各方star。

https://github.com/qibin0506/AndNet

以上是关于网络框架AndNet—解放你的时间的主要内容,如果未能解决你的问题,请参考以下文章

近日使用Taro框架的一点小心得

开源中国社区开源项目排行榜

开源中国社区开源项目排行榜

开源中国社区开源项目排行榜

网页前端常用的库或框架都有哪些

被解放的姜戈01 初试天涯