码迷,mamicode.com
首页 > 移动开发 > 详细

Android——网络编程

时间:2015-11-06 20:51:14      阅读:353      评论:0      收藏:0      [点我收藏+]

标签:

WebView简单体验——可内嵌在应用程序的浏览器

WebView是一个封装了网络请求,数据解析的这么一个控件,可作为程序的内置浏览器使用 

注意声明网络访问权限:android.permission.INTERNET

1     <WebView
2         android:id="@+id/webview"
3         android:layout_width="match_parent"
4         android:layout_height="match_parent" />
 1     protected void onCreate(Bundle savedInstanceState) {
 2         super.onCreate(savedInstanceState);
 3         setContentView(R.layout.activity_main);
 4         WebView webView = (WebView) findViewById(R.id.webview);
 5         // step1 设置支持js
 6         webView.getSettings().setJavaScriptEnabled(true);
 7         // step2 设置客户端本页根据传入的url打开网页,不需要调用系统浏览器
 8         webView.setWebViewClient(new WebViewClient() {
 9 
10             @Override
11             public boolean shouldOverrideUrlLoading(WebView view, String url) {
12                 // 根据url访问网络
13                 view.loadUrl(url);
14                 // 设置成true,表示跳转网页时在本页打开
15                 return true;
16             }
17 
18         });
19         // 默认访问百度,测试简写不可用
20         webView.loadUrl("http://www.baidu.com");
21         // 注意访问网络需要权限
22     }

http网络请求

方式一:HttpURLConnection

网络请求是比较耗时的操作,如果直接在主线程中使用的话,可能会出现ANR问题,所以通常是要开启一个子线程进行操作的

下面是常见写法,但是存在着一些弊端=》通常应用程序里面网络请求不止一个,所以应当封装成一个工具类,当需要请求的时候,直接用工具类传入地址进行访问

注:用模拟器调试的话,可以开启本地apache服务器,请求 10.0.2.2/xxx.xml

 1     private void sendRequestWithHttpURLConnection() {
 2         // 发送网络请求,必须开启子线程,否则可能阻塞主线程,ANR
 3         new Thread(new Runnable() {
 4 
 5             @Override
 6             public void run() {
 7                 // 注意别写成HttpsURLConnection
 8                 HttpURLConnection connection = null;
 9                 try {
10                     // 1.得到HttpURLConnection实例——通过url的open..获得
11                     URL url = new URL("http://www.ytslf.com/get_data.xml");
12                     connection = (HttpURLConnection) url.openConnection();
13 
14                     // 2.设置请求方式以及请求延时
15                     connection.setRequestMethod("GET");// GET表示需要从服务器得到数据,POST表示需要向服务器提交数据
16                     connection.setConnectTimeout(8000);
17                     connection.setReadTimeout(8000);
18 
19                     // 3.获取InputStream流,读取服务器返回的数据
20                     InputStream in = connection.getInputStream();
21                     BufferedReader bufr = new BufferedReader(
22                             new InputStreamReader(in));
23                     String line = null;
24                     StringBuilder sb = new StringBuilder();
25                     while ((line = bufr.readLine()) != null) {
26                         sb.append(line);
27                     }
28                     // 4.将获取到的数据交给Handler处理
29                     Message msg = new Message();
30                     msg.what = SHOW_RESPONSE;
31                     msg.obj = sb.toString(); // 可以直接传入StringBuilder,但为了统一,传String
32                     handler.sendMessage(msg);
33                 } catch (IOException e) {
34                     e.printStackTrace();
35                 } finally {
36                     if (connection != null) {
37                         // 关闭连接
38                         connection.disconnect();
39                     }
40                 }
41 
42             }
43         }).start();
44     }

 

 

方式二:HttpClient

HttpClient算是HttpURLConnection的升级版把

 1     private void sendRequestWithHttpClient() {
 2         new Thread(new Runnable() {
 3 
 4             @Override
 5             public void run() {
 6                 try {
 7                     // 1.得到HttpClient实例
 8                     HttpClient httpClient = new DefaultHttpClient();
 9                     // 2.发送一个GET请求
10 //                    HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.xml");
11                     HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.json");
12                     // 通过execute方法执行请求,可以得到服务器反馈的数据,都封装在HttpResponse对象中
13                     HttpResponse httpResponse = httpClient.execute(httpGet);
14 
15                     /*
16                      * 发送Post请求较GET复杂,需要提交参数
17                      * 1.新建一个HttpPost对象 
18                      * HttpPost httpPost = new HttpPost("http://www.baidu.com");
19                      * 2.通过NameValuePair集合存放需要提交的参数
20                      *  List<NameValuePair> params =
21                      * new ArrayList<NameValuePair>(); 
22                      * params.add(newBasicNameValuePair("username", "admin")); 
23                      * params.add(newBasicNameValuePair("password", "123456"));
24                      * UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");
25                      * httpPost.setEntity(entity); 
26                      * // 之后就和GET一样的操作
27                      * httpClient.execute(httpPost);
28                      */
29                     // 3.接下来就是要得到服务器返回的数据了
30                     if (httpResponse.getStatusLine().getStatusCode() == 200) {
31                         // 如果返回的状态码为200,则表示请求和响应都成功了
32                         HttpEntity httpEntity = httpResponse.getEntity();
33                         String response = EntityUtils.toString(httpEntity,
34                                 "utf-8");
35 //                        /*请求测试
36                         // 将数据发送到Message队列中
37                         Message msg = new Message();
38                         msg.what = SHOW_RESPONSE;
39                         msg.obj = response;
40                         handler.sendMessage(msg);
41 //                        */
42                         // 解析测试——Pull方式
43 //                        Log.d("test", "response ok");
44 //                        parseXMLWithPull(response);
45 //                        Log.d("test", "parse over");
46                         
47 
48                     }
49 
50                 } catch (Exception e) {
51                     e.printStackTrace();
52                 }
53             }
54         }).start();
55     }

 

 

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>
  <app>
    <id>3</id>
    <name>Google Play</name>
    <version>2.3</version>
  </app>
</apps>

方式一:Pull解析

 1     private void parseXMLWithPull(String xmdData){
 2         try {
 3             // 1.获取XML的PULL解析工厂实例
 4             XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
 5             // 2.通过工厂获取XML解析器实例
 6             XmlPullParser xmlPullParser = factory.newPullParser();
 7             // 3.XML解析器设置要解析的XML数据
 8             xmlPullParser.setInput(new StringReader(xmdData));
 9             // go go go!
10             int eventType = xmlPullParser.getEventType();
11             String id = "";
12             String name = "";
13             String version = "";
14             
15             // 开始解析
16             while(eventType != XmlPullParser.END_DOCUMENT){
17                 String nodeName = xmlPullParser.getName();
18                 switch (eventType) {
19                 // 开始解析某个节点
20                 case XmlPullParser.START_TAG:
21                     if("id".equals(nodeName)){
22                         id = xmlPullParser.nextText();
23                     }
24                     else if("name".equals(nodeName)){
25                         name = xmlPullParser.nextText();
26                     }
27                     else if ("version".equals(nodeName)) {
28                         version = xmlPullParser.nextText();
29                     }
30                     break;
31                     
32                 // 完成解析某个节点
33                 case XmlPullParser.END_TAG:
34                     if("app".equals(nodeName)){
35                         Log.d("test", "id:"+id);
36                         Log.d("test", "name:"+name);
37                         Log.d("test", "version:"+version);
38                         responseText.append(id+"::"+name+"::"+version+"\n");
39                     }
40                     break;
41 
42                 default:
43                     break;
44                 }
45                 eventType = xmlPullParser.next();// 解析下一个
46             }
47             
48             
49         } catch (Exception e) {
50             e.printStackTrace();
51         }
52     }

 

方式二:SAX解析

 1     // SAX解析XML
 2     private void parseXMLWithSAX(String xmlData){
 3         try {
 4             SAXParserFactory factory = SAXParserFactory.newInstance();
 5             XMLReader xmlReader = factory.newSAXParser().getXMLReader();
 6             // 创建自定义的Handler实例
 7             ContentHandler handler = new ContentHandler();
 8             // 将实例设置到XMLReader中
 9             xmlReader.setContentHandler(handler);
10             // 开始解析
11             xmlReader.parse(new InputSource(new StringReader(xmlData)));
12         } catch (Exception e) {
13             e.printStackTrace();
14         }
15     }

 

技术分享
 1 package com.example.networktest;
 2 
 3 import org.xml.sax.Attributes;
 4 import org.xml.sax.SAXException;
 5 import org.xml.sax.helpers.DefaultHandler;
 6 
 7 import android.util.Log;
 8 
 9 public class ContentHandler extends DefaultHandler {
10 
11     private String nodeName;
12     private StringBuilder id;
13     private StringBuilder name;
14     private StringBuilder version;
15 
16     /**
17      * 开始解析xml时调用
18      */
19     @Override
20     public void startDocument() throws SAXException {
21         id = new StringBuilder();
22         name = new StringBuilder();
23         version = new StringBuilder();
24     }
25 
26     /**
27      * 开始解析某个节点的时候调用
28      */
29     @Override
30     public void startElement(String uri, String localName, String qName,
31             Attributes attributes) throws SAXException {
32         // 记录当前节点的名字
33         nodeName = localName;
34     }
35 
36     /**
37      * 具体解析内容时调用
38      */
39     @Override
40     public void characters(char[] ch, int start, int length)
41             throws SAXException {
42         // TODO Auto-generated method stub
43         if ("id".equals(nodeName)) {
44             id.append(ch, start, length);
45         } else if ("name".equals(nodeName)) {
46             name.append(ch, start, length);
47         } else if ("version".equals(nodeName)) {
48             version.append(ch, start, length);
49         }
50     }
51 
52     /**
53      * 解析完某个节点的时候调用
54      */
55     @Override
56     public void endElement(String uri, String localName, String qName)
57             throws SAXException {
58         if("app".equals(localName)){
59             // StringBuilder读取到的内容可能会有多余的空格或换行符等,通过String的trim()方法去掉
60             Log.d("test", "id:"+id.toString().trim());
61             Log.d("test", "name:"+name.toString().trim());
62             Log.d("test", "version:"+version.toString().trim());
63             
64             // 清空StringBuilder
65             id.setLength(0);
66             name.setLength(0);
67             version.setLength(0);
68         }
69     }
70 
71     /**
72      * xml全部解析完成时调用
73      */
74     @Override
75     public void endDocument() throws SAXException {
76     }
77 
78 }
ContentHandler

 

 

JSON解析

json格式如:[{"id":"5","name":"hh","version":"2.1"},{……}]

方式一:JSONObject解析

 1     // JSONObject解析json
 2     private void parseJSONWithJSONObject(String jsonData){
 3         try {
 4             JSONArray jsonArray = new JSONArray(jsonData);
 5             for(int i=0;i<jsonArray.length();i++){
 6                 JSONObject jsonObject = jsonArray.getJSONObject(i);
 7                 String id = jsonObject.getString("id");
 8                 String name = jsonObject.getString("name");
 9                 String version = jsonObject.getString("version");
10                 Log.d("test", "id:"+id);
11                 Log.d("test", "name:"+name);
12                 Log.d("test", "version:"+version);
13                 responseText.append(id+"::"+name+"::"+version+"\n");
14             }
15         } catch (Exception e) {
16             e.printStackTrace();
17         }
18     }

 

方式二:GSON解析

利用GSON解析,需要用到GSON的jar包,将jar包拷贝至项目的libs文件夹即可

利用GSON,可以将json数据直接解析成一个对象,利用该对象就能的到相应的数据,这一点是极好的

例如:要解析{"name":"Tom","age":"20"}

可以定义一个具有name和age字段的Person类,解析如下

Gson gson = new Gson();
Person person = gson.fromJson(jsonData,Person.class);

 如果解析的是json数组,则需要用到TypeToken,将期望解析成的数据类型传入到fromJson的参数当中

List<Person> people = gson.fromJson(jsonData,new TypeToken<List<Person>>(){}.getType());

 

解析:

[{"id":"5","version":"5.5","name":"Angry Birds"},
{"id":"6","version":"7.0","name":"Clash of Clans"},
{"id":"7","version":"3.5","name":"Hey Day"}]

技术分享
 1 package com.example.networktest;
 2 
 3 public class App {
 4     private String id;
 5     private String name;
 6     private String version;
 7 
 8     public String getId() {
 9         return id;
10     }
11 
12     public void setId(String id) {
13         this.id = id;
14     }
15 
16     public String getName() {
17         return name;
18     }
19 
20     public void setName(String name) {
21         this.name = name;
22     }
23 
24     public String getVersion() {
25         return version;
26     }
27 
28     public void setVersion(String version) {
29         this.version = version;
30     }
31 
32 }
App.java
 1     // GSON第三方jar包解析json
 2     private void parseJSONWithGSON(String jsonData){
 3         try {
 4             Gson gson = new Gson();
 5             List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {}.getType());
 6             for(App app : appList){
 7                 String id = app.getId();
 8                 String name = app.getName();
 9                 String version = app.getVersion();
10                 Log.d("test", "id:"+id);
11                 Log.d("test", "name:"+name);
12                 Log.d("test", "version:"+version);
13 //                responseText.append(id+"::"+name+"::"+version+"\n");
14             }
15         } catch (Exception e) {
16             e.printStackTrace();
17         }
18     }

 

 

Http请求的最佳写法:封装为工具类+利用Java回调监听机制

1.封装,定义一个HttpUtil工具类,将请求的代码封装成静态方法,且需要传入网络地址作为参数

 1 public class HttpUtil {
 2     public static String sendHttpRequest(String address) {
 3         HttpURLConnection connection = null;
 4         try {
 5             return null;
 6         } catch (Exception e) {
 7             // TODO: handle exception
 8             return null;
 9         } finally {
10             if (connection != null) {
11                 connection.disconnect();
12             }
13         }
14     }
15 }

 

细节暂时不写……

这样封装了之后,就可以愉快的调用了

String response = HttpUtil.sendHttpRequest("http://www.baidu.com");

 

但是仍然存在问题:

1.没有开启线程,则仍然默认是在主线程中执行网络请求,可能导致主线程阻塞

2.如果开启线程,

 

Android——网络编程

标签:

原文地址:http://www.cnblogs.com/erhai/p/4943570.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!