Volley框架的使用--自定义数据的请求方式

来源:http://blog.csdn.net/guolin_blog/article/details/17612763

经过前面的学习,我们已经掌握了Volley各种Request的使用方法,包括StringRequest、JsonRequest、ImageRequest等。其中StringRequest用于请求一条普通的文本数据,JsonRequest(JsonObjectRequest、JsonArrayRequest)用于请求一条JSON格式的数据,ImageRequest则是用于请求网络上的一张图片。

可是Volley提供给我们的Request类型就只有这么多,而我们都知道,在网络上传输的数据通常有两种格式,JSON和XML,那么如果想要请求一条XML格式的数据该怎么办呢?其实很简单,Volley提供了非常强的扩展机制,使得我们可以很轻松地定制出任意类型的Request,这也就是本篇文章的主题了。

1. 自定义XMLRequest

/**
 * 定义自己的XMLRequest请求方式
 */
public class MainActivity extends Activity {
    /**
     * 请求队列,RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象
     * 基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。
     */
    private RequestQueue requestQueue;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.imageView);
        //第一步:创建网络请求队列
        requestQueue = Volley.newRequestQueue(this);
        String url="http://wthrcdn.etouch.cn/WeatherApi?city=%E5%8C%97%E4%BA%AC";

        XMLRequest xmlRequest = new XMLRequest(Request.Method.GET, url, new Response.Listener<XmlPullParser>() {
            @Override
            public void onResponse(XmlPullParser xmlPullParser) {
                //XMLRequest类里方法的回调
                try {
                    int code=xmlPullParser.getEventType();
                    while(code!=1){
                        String name = xmlPullParser.getName();
                        switch (code){
                            case 2:
                                if("date".equals(name)){
                                    Log.i("tag",xmlPullParser.nextText());
                                }
                                break;
                        }
                        code=xmlPullParser.next();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.i("tag","下载失败"+volleyError.getMessage());
            }
        });
        requestQueue.add(xmlRequest);
    }

    /**
     * 模仿字符串请求,自定义Xml请求的方式:
     * 其实就是将网址传过来下载了数据后在Response方法中将数据添加到解析器,然后用接口回调把解析器传出去
     */
    class XMLRequest extends Request<XmlPullParser> {
        private Response.Listener<XmlPullParser> mListener;

        public XMLRequest(int method, String url, Response.Listener<XmlPullParser> listener,
                          Response.ErrorListener errorListener) {
            super(method, url, errorListener);
            mListener = listener;
        }

        /**
         * 对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponse的data变量中的,
         * 这里将数据取出然后组装成一个String,并传入Response的success()方法中即可
         */
        @Override
        protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse networkResponse) {
            try {
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                XmlPullParser xmlPullParser = factory.newPullParser();
                //得到连接网络下载的数据,指定了编码格式
                String xmlData=new String(networkResponse.data,"utf-8");//不然会乱码
                //设置Pull解析的数据源
                xmlPullParser.setInput(new StringReader(xmlData));
                return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(networkResponse));
            } catch (XmlPullParserException e) {
                e.printStackTrace();
                return Response.error(new ParseError(e));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return Response.error(new ParseError(e));
            }
        }

        @Override
        protected void deliverResponse(XmlPullParser xmlPullParser) {
            //将携带了数据的解析器传出去(接口回调)
            mListener.onResponse(xmlPullParser);
        }
    }
}
/*字符串请求方式的源码:
public class StringRequest extends Request<String> {
     protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));//这里编码为"ISO-8859-1"
        } catch (UnsupportedEncodingException var4) {
            parsed = new String(response.data);
        }

        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }
}
 */

 自定义字符串的请求方式,其实上面也可以直接得到从网络上获取的数据,然后在回调方法里进行数据解析就行了

2.获取字符串数据,保证不乱码:

public class MainActivity extends Activity {
    /**
     * 请求队列,RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象
     * 基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。
     */
    private RequestQueue requestQueue;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.imageView);
        //第一步:创建网络请求队列
        requestQueue = Volley.newRequestQueue(getApplicationContext());
        String url="http://www.baidu.com";
        //String url="http://wthrcdn.etouch.cn/WeatherApi?city=%E5%8C%97%E4%BA%AC";

        XMLRequest xmlRequest = new XMLRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                //这样就能得到任意网址的字符串数据了,而且还不会乱码, 在这里再进行数据解析也是一样的
                Log.i("tag", "下载成功,s=" + s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.i("tag", "下载失败");
            }
        });
        requestQueue.add(xmlRequest);
    }

    /**
     * 模仿字符串请求,自定义请求的方式:
     */
    class XMLRequest extends Request<String> {

        private Response.Listener<String> mlistener;

        public XMLRequest(int method, String url, Response.Listener<String> succedlistener, Response.ErrorListener listener) {
            super(method, url, listener);
            mlistener=succedlistener;
        }

        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
            String parsed;
            try {
                parsed = new String(networkResponse.data, "utf-8");//这里源码的编码为"ISO-8859-1"
                Log.i("tag","parsed="+parsed);
            } catch (UnsupportedEncodingException var4) {
                parsed = new String(networkResponse.data);
            }
            return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(networkResponse));
        }

        @Override
        protected void deliverResponse(String s) {
            mlistener.onResponse(s);
        }
    }
}

3. 自定义Json数据的请求(这里利用Gson解析的),实体类利用工具自动生成的,就不码出来了

public class MainActivity extends AppCompatActivity {

    private RequestQueue requestQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        requestQueue = Volley.newRequestQueue(this);//创建网络请求队列(执行网络连接的)
        //json数据的网址
        String s = "http://zhushouapi.gamedog.cn/index.php?umengchannel=baidu&m=Android&a=lists&channel=youxi&order=down&page=1&pagesize=8";

        GameDog dog = new GameDog(Request.Method.GET, s, new Response.Listener<GameDogBean>() {
            @Override
            public void onResponse(GameDogBean response) {
                //第三步:主线程运行的,得到传过来的结果
                Log.i("tag", "解析出来的对象:" + response.getData().get(0).getRemark());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.i("tag", "解析出错");
            }
        });
        requestQueue.add(dog);//执行任务
    }

    /**
     * 定义自己的解析方式
     */
    class GameDog extends Request<GameDogBean>{

        private Response.Listener<GameDogBean> mListener;//请求成功的回调对象

        public GameDog(int method, String url, Response.Listener<GameDogBean> listener1, Response.ErrorListener listener) {
            super(method, url, listener);
            mListener = listener1;
        }

        @Override
        protected Response<GameDogBean> parseNetworkResponse(NetworkResponse response) {
            //第一步:子线程运行
            String jsonData;
            try {
                //将下载下来的字节数组,转换为字符串,   第二个参数为编码格式
                jsonData = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            } catch (Exception e) {
                jsonData = new String(response.data);
            }
            //得到数据后解析数据
            Gson gson = new Gson();
            GameDogBean bean = gson.fromJson(jsonData, GameDogBean.class);//GameDogBean为用工具生成的json数据实体类
            return Response.success(bean, HttpHeaderParser.parseCacheHeaders(response));//将调用deliverResponse()
        }

        @Override
        protected void deliverResponse(GameDogBean response) {
            //第二步:主线程运行的,将结果回调出去
            mListener.onResponse(response);
        }
    }

}

这样就把具体的解析过程放到内部子线程里了,外面只需要得到传回来的json对象获取数据就行

posted @ 2016-09-02 16:10  ts-android  阅读(289)  评论(0编辑  收藏  举报