您的位置:首页 > 理论基础 > 计算机网络

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.根据需求,定义公用接口HttpCallbackListener

public 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) {
// 异常处理,这里就不写了

}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: