学习笔记(六) 网络编程与数据处理
废话不多说啦,我们直接学习Android中最常使用的网络技术。
在请求网络之前,我们需要在AndroidManifest中声明访问网络的权限:
uses-permission android:name="android.permission.INTERNET"/>
-HttpURLConnection
在Android上发送HTTP请求的方式一般有两种,HttpURLConnection和HttpClient,但是老师说HttpClient已经被Google弃用了,而HttpURLConnection能够更好的处理网页数据,并且可以减少耗电量。
- 获得HttpURLConnection的实例
在获取实例之前,我们需要一个URL对象,将目标的网络地址传入,然后调用Url的openConnection()方法。
URL url=new URL("http://www.baidu.com");HttpURLConnection connection=(HttpURLConnection)url.openConnection();
至于问什么要调用url的openConnection()方法,Android源码说是这个方法通过url返回一个指向资源的连接,所以还要进行强制转型;
还要设置HTTP请求所使用的方式,在学习Html时,学到了GET和POST两种方式,其中GET是从服务器端获取数据,POST是从服务器端发送数据,而且GET方式中表单的附加信息会出现在URl上,相比于POST会不安全。
connection.setConnectTimeout(8000);//设置连接超时时间 connection.setReadTimeout(8000); //设置读取超时时间 connection.connect();//开启http连接
下面就是请求baidu数据的实例:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);new Thread(new Runnable() { @Override public void run() { //请求网络数据,需要申请权限 data = requestData(url); }}).start();}private String requestData(String url_String) { //第一种方法 try { String result=null; URL url=new URL(url_String); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET");//设置http请求所使用的方法 connection.setConnectTimeout(8000);//设置连接超时时间 connection.setReadTimeout(8000); //设置读取超时时间 connection.connect();//开启http连接 int response= connection.getResponseCode();//获取响应状态嘛 if(response== HttpURLConnection.HTTP_OK) { InputStream inputStream = connection.getInputStream();//获取服务器返回的输入流 Reader reader = new InputStreamReader(inputStream, "utf-8"); char[] buffer = new char[1024]; reader.read(buffer);//将reader读到的数据放到char数组中 result=new String(buffer); } else if(response== HttpURLConnection.HTTP_NOT_FOUND){ result="304 NOT FOUND!"; } else{ result="Error!!"; } return result; } catch (MalformedURLException e) { e.printStackTrace(); Toast.makeText(MainActivity.this,"非法网址",Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } finally { connection.disconnect();//关闭http连接 } return null; }
因为获取网络数据是一个同步操作,所以我们需要在一个子线程中去完成耗时操作;
除了使用线程,Android还提供一个很好的工具类——AsyncTask,但是它的实现原理还是基于异步消息处理机制。AsyncTask是一个抽象类,所以使用它必须用一个子类去继承,其中必须要重写的三个方法:onPreExecute() ;doInBackground(String[] params);
onPostExecute(String s);
分别对应三个不同的操作,第一个是在子线程之前,即在主线程中的操作;第二个是全部在子线程中执行;第三个是在子线程之后,进行的相关操作;
所以,使用AsyncTask会使我们方便很多,不需要在去考虑异步消息处理机制了。
-解析XML格式数据
通过上面的requestData()方法,我们得到了xml数据,但是只有将数据解析之后才能得到我们想要的数据。
- SAX解析方式
private void parseXML_WithSAX(String xmlData) { //将SAX方式解析XML try { //先创建工程,在创建一个解析器,然后再有一个xml读取器,固定的步骤 SAXParserFactory factory=SAXParserFactory.newInstance(); XMLReader xmlReader=factory.newSAXParser().getXMLReader(); SAX_Handler sax_handler=new SAX_Handler(); //将ContentHandler的实例设置到XMLReader中 xmlReader.setContentHandler(sax_handler); //开始执行解析, xmlReader.parse(new InputSource(new StringReader(xmlData))); } catch (Exception e) { e.printStackTrace(); } }
String xmlData就是requestData()所返回的xml数据。
- Pull解析方式
Pull方法相对与SAX方法有点复杂。
private void requestXML_Pull(String data) { //用Pull方式解析XML try { XmlPullParserFactory factory=XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser=factory.newPullParser(); xmlPullParser.setInput(new StringReader(data)); int eventType=xmlPullParser.getEventType(); String id=""; String item=""; while(eventType!=XmlPullParser.END_DOCUMENT){ String nodename=xmlPullParser.getName(); switch (eventType){ //开始解析某个节点 case XmlPullParser.START_TAG: if("id".equals(nodename)){ id=xmlPullParser.nextText(); }else if("item".equals(nodename)){ item=xmlPullParser.nextText(); } break; case XmlPullParser.END_TAG: if("app".equals(nodename)){ Log.i("TAG","id:"+id); Log.i("TAG","item:"+item); } break; default:break; } eventType=xmlPullParser.next(); } } catch (Exception e) { e.printStackTrace(); } }
setInput()方法是将服务器返回的XML数据传入,并开始解析。通过getEventType()可以得到当前的解析事件,通过while循环进行不断的解析,getItem()方法是得到当前结点的名字,若结点不是结束节点,next()获取下一个节点;若节点满足相应的条件,则调用nextText()方法获取节点中具体的内容。
- 解析JSON格式数据
比起XML,JSON主要优势是在于它的体积更小,在网络上传输的时候可以更省流量。
解析JSON的方法有很多,可以使用官方提供的JSONObject,也可以使用Google的GSON。
private void requestJSON(String xml_json) {//测试JSON try { result=""; JSONArray jsonArray=new JSONArray(xml_json); for(int i=0;i<jsonArray.length();i++){ JSONObject jsonobject=jsonArray.getJSONObject(i); String id=jsonobject.getString("id"); String name=jsonobject.getString("name"); String version=jsonobject.getString("version"); result = "id:"+id+",name:"+name+",version:"+version+result; } } catch (JSONException e) { e.printStackTrace(); } }
这里是解析JSON数据中的id和version,通过requestData()从服务器获得返回的JSON数据,然后数据传入一个JSON数组中,通过JSONObject对象的getString()方法,返回所对应的数据。
GSON解析JSON数据
Google提供了一个非常简单的工具,它可以将一段JSON格式的字符串自动映射成一个对象,从而不需要我们在去解析。
使用GSONFormat工具(大家可以自行百度),将我们的JSON数据可以自动映射成一个对象,通过对象的方法我们可以得到JSON中的任何数据,非常方便。
Gson gson=new Gson(); JSon_Bean jSon_bean=gson.fromJson(result,JSon_Bean.class);
JSON_Bean是json数据所影射的类,通过fromJson()方法可以获得对象,从而可以操作JSON中的所有数据。