Android——网络编程
2015-11-06 20:29
627 查看
WebView简单体验——可内嵌在应用程序的浏览器
WebView是一个封装了网络请求,数据解析的这么一个控件,可作为程序的内置浏览器使用注意声明网络访问权限:android.permission.INTERNET
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView webView = (WebView) findViewById(R.id.webview); // step1 设置支持js webView.getSettings().setJavaScriptEnabled(true); // step2 设置客户端本页根据传入的url打开网页,不需要调用系统浏览器 webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // 根据url访问网络 view.loadUrl(url); // 设置成true,表示跳转网页时在本页打开 return true; } }); // 默认访问百度,测试简写不可用 webView.loadUrl("http://www.baidu.com"); // 注意访问网络需要权限 }
http网络请求
方式一:HttpURLConnection
网络请求是比较耗时的操作,如果直接在主线程中使用的话,可能会出现ANR问题,所以通常是要开启一个子线程进行操作的下面是常见写法,但是存在着一些弊端=》通常应用程序里面网络请求不止一个,所以应当封装成一个工具类,当需要请求的时候,直接用工具类传入地址进行访问
注:用模拟器调试的话,可以开启本地apache服务器,请求 10.0.2.2/xxx.xml
private void sendRequestWithHttpURLConnection() { // 发送网络请求,必须开启子线程,否则可能阻塞主线程,ANR new Thread(new Runnable() { @Override public void run() { // 注意别写成HttpsURLConnection HttpURLConnection connection = null; try { // 1.得到HttpURLConnection实例——通过url的open..获得 URL url = new URL("http://www.ytslf.com/get_data.xml"); connection = (HttpURLConnection) url.openConnection(); // 2.设置请求方式以及请求延时 connection.setRequestMethod("GET");// GET表示需要从服务器得到数据,POST表示需要向服务器提交数据 connection.setConnectTimeout(8000); connection.setReadTimeout(8000); // 3.获取InputStream流,读取服务器返回的数据 InputStream in = connection.getInputStream(); BufferedReader bufr = new BufferedReader( new InputStreamReader(in)); String line = null; StringBuilder sb = new StringBuilder(); while ((line = bufr.readLine()) != null) { sb.append(line); } // 4.将获取到的数据交给Handler处理 Message msg = new Message(); msg.what = SHOW_RESPONSE; msg.obj = sb.toString(); // 可以直接传入StringBuilder,但为了统一,传String handler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } finally { if (connection != null) { // 关闭连接 connection.disconnect(); } } } }).start(); }
方式二:HttpClient
HttpClient算是HttpURLConnection的升级版把private void sendRequestWithHttpClient() { new Thread(new Runnable() { @Override public void run() { try { // 1.得到HttpClient实例 HttpClient httpClient = new DefaultHttpClient(); // 2.发送一个GET请求 // HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.xml"); HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.json"); // 通过execute方法执行请求,可以得到服务器反馈的数据,都封装在HttpResponse对象中 HttpResponse httpResponse = httpClient.execute(httpGet); /* * 发送Post请求较GET复杂,需要提交参数 * 1.新建一个HttpPost对象 * HttpPost httpPost = new HttpPost("http://www.baidu.com"); * 2.通过NameValuePair集合存放需要提交的参数 * List<NameValuePair> params = * new ArrayList<NameValuePair>(); * params.add(newBasicNameValuePair("username", "admin")); * params.add(newBasicNameValuePair("password", "123456")); * UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8"); * httpPost.setEntity(entity); * // 之后就和GET一样的操作 * httpClient.execute(httpPost); */ // 3.接下来就是要得到服务器返回的数据了 if (httpResponse.getStatusLine().getStatusCode() == 200) { // 如果返回的状态码为200,则表示请求和响应都成功了 HttpEntity httpEntity = httpResponse.getEntity(); String response = EntityUtils.toString(httpEntity, "utf-8"); // /*请求测试 // 将数据发送到Message队列中 Message msg = new Message(); msg.what = SHOW_RESPONSE; msg.obj = response; handler.sendMessage(msg); // */ // 解析测试——Pull方式 // Log.d("test", "response ok"); // parseXMLWithPull(response); // Log.d("test", "parse over"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); }
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解析
private void parseXMLWithPull(String xmdData){ try { // 1.获取XML的PULL解析工厂实例 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); // 2.通过工厂获取XML解析器实例 XmlPullParser xmlPullParser = factory.newPullParser(); // 3.XML解析器设置要解析的XML数据 xmlPullParser.setInput(new StringReader(xmdData)); // go go go! int eventType = xmlPullParser.getEventType(); String id = ""; String name = ""; String version = ""; // 开始解析 while(eventType != XmlPullParser.END_DOCUMENT){ String nodeName = xmlPullParser.getName(); switch (eventType) { // 开始解析某个节点 case XmlPullParser.START_TAG: if("id".equals(nodeName)){ id = xmlPullParser.nextText(); } else if("name".equals(nodeName)){ name = xmlPullParser.nextText(); } else if ("version".equals(nodeName)) { version = xmlPullParser.nextText(); } break; // 完成解析某个节点 case XmlPullParser.END_TAG: if("app".equals(nodeName)){ Log.d("test", "id:"+id); Log.d("test", "name:"+name); Log.d("test", "version:"+version); responseText.append(id+"::"+name+"::"+version+"\n"); } break; default: break; } eventType = xmlPullParser.next();// 解析下一个 } } catch (Exception e) { e.printStackTrace(); } }
方式二:SAX解析
// SAX解析XML private void parseXMLWithSAX(String xmlData){ try { SAXParserFactory factory = SAXParserFactory.newInstance(); XMLReader xmlReader = factory.newSAXParser().getXMLReader(); // 创建自定义的Handler实例 ContentHandler handler = new ContentHandler(); // 将实例设置到XMLReader中 xmlReader.setContentHandler(handler); // 开始解析 xmlReader.parse(new InputSource(new StringReader(xmlData))); } catch (Exception e) { e.printStackTrace(); } }
package com.example.networktest; public class App { private String id; private String name; private String version; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } }
App.java
// GSON第三方jar包解析json private void parseJSONWithGSON(String jsonData){ try { Gson gson = new Gson(); List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {}.getType()); for(App app : appList){ String id = app.getId(); String name = app.getName(); String version = app.getVersion(); Log.d("test", "id:"+id); Log.d("test", "name:"+name); Log.d("test", "version:"+version); // responseText.append(id+"::"+name+"::"+version+"\n"); } } catch (Exception e) { e.printStackTrace(); } }
Http请求的最佳写法:封装为工具类+利用Java回调监听机制
1.封装,定义一个HttpUtil工具类,将请求的代码封装成静态方法,且需要传入网络地址作为参数
public class HttpUtil { public static String sendHttpRequest(String address) { HttpURLConnection connection = null; try { return null; } catch (Exception e) { // TODO: handle exception return null; } finally { if (connection != null) { connection.disconnect(); } } } }
细节暂时不写……
这样封装了之后,就可以愉快的调用了
String response = HttpUtil.sendHttpRequest("http://www.baidu.com");
但是仍然存在问题:
1.没有开启线程,则仍然默认是在主线程中执行网络请求,可能导致主线程阻塞
2.如果开启线程,如何能够让子线程执行完之后返回数据?这确实是一个问题!!!
解决方法:利用Java的回调机制
回调机制概述最佳写法
1.根据需求,定义公用接口HttpCallbackListenerpublic interface HttpCallbackListener { public abstract void onFinish(String response); public abstract void onError(Exception e); }
2.在工具类中转入这个接口参数,在得到需要异步处理的结果后,执行接口中的方法,从而实现数据返回
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpUtil { public static void sendHttpRequest(final String address , final HttpCallbackListener listener) { new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { // 获取实例 URL url = new URL(address); connection = (HttpURLConnection) url.openConnection(); // 设置访问方式和网络延迟 connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setReadTimeout(8000); // 设置是否URLConnection是否允许输入输出 connection.setDoInput(true); connection.setDoOutput(true); // 获取服务器输入流 InputStream in = connection.getInputStream(); // 疯狂的读 StringBuilder response = new StringBuilder(); BufferedReader bufr = new BufferedReader(new InputStreamReader(in)); String line = null; while((line = bufr.readLine())!=null){ response.append(line); } // 利用回调,异步返回数据 if(listener!=null){ // 回调onFinish listener.onFinish(response.toString()); } } catch (Exception e) { if(listener!=null){ // 回调onError listener.onError(e); } } finally { if (connection != null) { connection.disconnect(); } } } }).start(); } }
3.使用下这个工具类~~
String address = "http://www.ytslf.com/get_data.json"; HttpUtil.sendHttpRequest(address, new HttpCallbackListener() { @Override public void onFinish(String response) { // 根据放回的数据,执行具体的逻辑处理,这里是交给handler,然后让handler解析json Message msg = new Message(); msg.what = SHOW_RESPONSE; msg.obj = response; handler.sendMessage(msg); } @Override public void onError(Exception e) { // 异常处理,这里就不写了 } });
相关文章推荐
- StarUML官网地址 http://staruml.io/
- 网络相关问题(上)
- 寻找http://localhost/phpmyadmin出现的问题:HTTP 错误 404.0 - Not Found 您要找的资源已被删除、已更名或暂时不可用
- 如何使用socket进行java网络编程(三)
- Java系列: 关于HttpSessionListener的sessionDestroyed什么时候触发
- 使用AsyncHttpClient所需jar包
- 使用Apache HttpClient访问网络(实现手机端注册,服务器返回信息)
- 如何获取网络时间
- Git https 保存密码
- 发送http请求获取响应
- Activity业务层与网络层之间处理
- iOS网络笔记--文件下载练习2
- pp Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure.
- Retrofit 2.0使用详解,配合OkHttp、Gson,Android最强网络请求框架
- httpclient中文乱码问题
- DeepLearning (六) 学习笔记整理:神经网络以及卷积神经网络
- 网络请求参数为json形式
- Android上用tcpdump抓包(转)
- 一文读懂卷积神经网络
- HTTP中Get与Post的区别