Android使用Http访问并解析服务器XML数据

okhttp

使用前需添加okhttp开源库的依赖,添加方法可参考前面这篇文章

new Thread(() -> {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://127.0.0.1/a.xml")
                .build();
        try {
            Response response = client.newCall(request).execute();
            String responceData = response.body().string();
            showResponce(responceData);
        }
        catch (IOException ioex) {
            ioex.printStackTrace();
        }

    //            RequestBody requestBody = new FormBody.Builder()
    //                    .add("username", "admin")
    //                    .add("password", "123456")
    //                    .build();
    //            Request request1 = new Request.Builder()
    //                    .url("http://www.baidu.com")
    //                    .post(requestBody)
    //                    .build();
    //            try {
    //                Response response = client.newCall(request1).execute();
    //                String responceData = response.body().string();
    //            }
    //            catch (IOException ex) {
    //                ex.printStackTrace();
    //            }
    }).start();

解析XML

假设有XML数据如下

<apps>
    <app>
        <id>1</id>
        <name>Google Maps</name>
        <version>1.0</version>
    </app>
    <app>
        <id>2</id>
        <name>Chrome</name>
        <version>2.1</version>
    </app>

</apps>

Pull

private void parseXMLWithPull(String responceData)
    {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance().newInstance();
            XmlPullParser xmlparser = factory.newPullParser();
            xmlparser.setInput(new StringReader(responceData));
            int eventType = xmlparser.getEventType();
            String id = "";
            String name = "";
            String version = "";
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlparser.getName();
                switch (eventType)
                {
                    case XmlPullParser.START_TAG: {
                        if("id".equals(nodeName)) {
                            id = xmlparser.nextText();
                        }
                        else if("name".equals(nodeName)) {
                            name = xmlparser.nextText();
                        }
                        else if("version".equals(nodeName)) {
                            version = xmlparser.nextText();
                        }
                        break;
                    }
                    case XmlPullParser.END_TAG: {
                        if("app".equals(nodeName)) {
                            Log.d("MainActivity", "id is" + id);
                            Log.d("MainActivity", "name is" + name);
                            Log.d("MainActivity", "version is" + version);
                        }
                        break;
                    }
                    default:
                        break;
                }
                eventType = xmlparser.next();
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

SAX

//创建一个类
    public class MyXMLHandler extends DefaultHandler {


        private String nodeName;
        private  StringBuilder id;
        private  StringBuilder name;
        private StringBuilder version;


        @Override
        public void startDocument() throws SAXException {
            id = new StringBuilder();
            name = new StringBuilder();
            version = new StringBuilder();
        }                          //文本的起始


        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            nodeName = localName;
        }                           //每个节点的起始

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if("id".equals(nodeName)) {
                id.append(ch, start, length);
            }
            else if("name".equals(nodeName)) {
                name.append(ch, start, length);
            }
            else if("version".equals(nodeName)) {
                version.append(ch, start, length);
            }
        }                          //每个节点文本内容的解析


        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if("app".equals(localName)) {
                Log.d("Handler", "id is" + id.toString().trim());
                Log.d("Handler", "name is" + name.toString().trim());
                Log.d("Handler", "version is" + version.toString().trim());
                id.setLength(0);
                name.setLength(0);
                version.setLength(0);
            }
        }                           //每个节点的结束


        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
        }
    }                              //文本的结束


    //类的调用
    private void parseXMLWithHandler(String responce)
    {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            XMLReader xmlreader = factory.newSAXParser().getXMLReader();
            MyXMLHandler handler = new MyXMLHandler();
            xmlreader.setContentHandler(handler);
            xmlreader.parse(new InputSource(new StringReader(responce)));
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

总结

其实,上面建立http连接的写法是有问题的。因为每次建立http连接都要重复以上代码,难免造成不必要的代码重复。我们想要的效果是:

String address = "...";
String responce = HttpUtil.sendRequestAddress(address);

因此我们想到的是把http协议处理的相关方法,包装到一个类中,然后在该sendRequestAddress方法中new一个Thread即可。但是这样就不能把想要的结果返回。因此,我们这里应用一个类okhttp.Callback进行回调。

public class HttpUtil {
        public static void sendHttpRequest(final String address, Callback callback)
        {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(address)
                    .build();
            client.newCall(request).enqueue(callback);
        }
    }

其中okhttp.Callback帮我们另外启动一个子线程处理服务器返回的数据,调用时,应用以下代码即可:

HttpUtil.sendHttpRequest("http://www.baidu.com",
            new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    ...
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String responseData = response.body().string();
                    showResponce(responseData);
                }
            });

一个回调机制的简单例子

 public interface HttpCallbackListener {
        void onFinish(String responce);
        void onError(Exception e);
    }
public class HttpUtil {
        public static void sendHttpRequest(final String add, HttpCallbackListener listener) {
            new Thread(() -> {                        //线程进行处理,处理时间不确定
                ....
                try {
                    if(listener != null) {
     listener.onFinish(responce.body().string());     //调用HttpCallbackListener中的函数
                    }
                }
                catch(Exception e) {
                    if(listener != null) {
                       listener.onError(e);           //调用HttpCallbackListener中的函数
                    }
                }
            }).start();
        }
    }
public class testResponce {

        public static showResponce(String rsponce) {
            ...
        }

        public static showError(Exception e) {
            ...
        }
        public static void main(String[] argv) {
            try{
                HttpUtil.sendHttpRequest(add, new HttpCallbackListener() {
                    @Override
                    void onFinish(String responce) {
                        showResponce(responce);                           //回调testResponce的函数
                    }

                    @Override
                    void onError(Exception e) {
                        showError(e);                                     ////回调testResponce的函数
                    }
                });
            }
            catch(Exception e) {
                ...
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/SarKerson/article/details/77448540