本章主要是要从网络中获得数据,并且解析,在android端渲染出来。
1.权限,获取网络数据需要权限
<uses-permission android:name="android.permission.INTERNET"/>
2.URL 统一资源定位符
URL,统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
我们从网络中获得数据,就需要这个地址,从它获得数据。
容易和URL混淆的概念:
URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。而URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。而URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema必须被指定。
3.从网络URL到本地String
网络请求,获得数据是耗时操作,不要在主线程操作。在异步,非主线程使用该方法。
/**
* 从 网址urlString 到 获得数据
* 中间 URL ,HttpURLConnection,InputStream,InputStreamReader,char[] ,String.
* @param urlString
* @return
*/
private String requestData(String urlString) {
try {
URL url=new URL(urlString);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
// 链接超时时间
connection.setConnectTimeout(30000);
connection.setRequestMethod("GET");
// 开始请求
connection.connect();
// 请求的状态码,200是成功,404等
int responseCode=connection.getResponseCode();
String responseMessage=connection.getResponseMessage();
String result=null;
if(responseCode==HttpURLConnection.HTTP_OK){
InputStream inputStream=connection.getInputStream();
Reader reader=new InputStreamReader(inputStream,"UTF-8");
char[] buffer=new char[1024];
reader.read(buffer);
result=new String(buffer);
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
4.用异步任务来处理耗时操作,网络请求数据。
/**
* 异步任务处理
* AsyncTask<String,Integer,String>
* AsyncTask<Params,Progress,Result>,
* 泛型1,参数就是要操作的数据。你要操作的数据什么数据类型,如String
* 2,进度. 展示进度,一般用Integer,
* 3.结果 .处理完之后数据需要什么数据类型,如String
*/
class RequestNetworkDataTask extends AsyncTask<String,Integer,String>{
// 后台处理之前,主线程中
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* a background thread
* 参数:String... 可变数组。
* @param params
* @return
*/
@Override
protected String doInBackground(String[] params) {
Log.i("xyy",requestData(params[0]));
return requestData(params[0]);
}
/**
* 线程执行之后,主线程中
* 该方法传的参数就是doInBackground方法的返回值。
* 此方法用于处理结果数据的在UI中的显示
* @param s
*/
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mTextView.setText(s);
}
/**
* 线程更新,主线程中
* @param values
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
5.请求到的数据(XML)如何解析
xml相对于json比较耗空间,使用较少。
5.1 SAX解析xml , 复杂
1.建一个处理器,继承DefaultHandler
中间这个WebURL类就是根据xml的元素设计的,用来加载数据的类。
public class SAXParseHandler extends DefaultHandler {
public static final String ITEM = "item";
// 将xml数据装到这个中
private List<WebURL> mWebURLs;
// 一个WebURL对象相当于一个item,一条数据。
private WebURL mWebURL;
int type=1;
boolean mIsItem =false;
/**
* 开始这个文档解析
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
super.startDocument();
mWebURLs=new ArrayList<>();
}
/**
* 结束这个文档解析
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
/**
* 开始这个子节点,元素
* 参数2,标签
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
mWebURL=new WebURL();
if(TextUtils.equals(localName, ITEM)){
for (int i = 0; i < attributes.getLength(); i++) {
if(TextUtils.equals(attributes.getLocalName(i),"id")){
// 将数据装到WebURL中
mWebURL.setID(Integer.valueOf(attributes.getValue(i)));
}
}
mIsItem =true;
}
mIsItem =false;
}
/**
* 结束这个子节点,元素
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(TextUtils.equals(localName,ITEM)) {
mWebURLs.add(mWebURL);
}
}
/**
*
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String content=String.valueOf(ch,start,length);
if(mIsItem){
mWebURL.setContent(content);
mIsItem=false;
}
}
public List<WebURL> getXMLList() {
return mWebURLs;
}
}
2.具体操作,开始解析
/**
* parse xml by sax
* @throws ParserConfigurationException
* @throws SAXException
*/
private void testSAXParse() throws ParserConfigurationException, SAXException, IOException {
// 工厂类
SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
// 解析器
SAXParser saxParser=saxParserFactory.newSAXParser();
// 读取器,XMLReader类,表示提供对 XML 数据进行快速、非缓存、只进访问的读取器。
XMLReader xmlReader=saxParser.getXMLReader();
// 处理器
SAXParseHandler saxParseHandler=new SAXParseHandler();
/**
* Allow an application to register a content event handler
*/
xmlReader.setContentHandler(saxParseHandler);
// 读数据获得输入流
InputStream inputStream=getResources().openRawResource(R.raw.test);
// A single input source for an XML entity
InputSource inputSource=new InputSource(inputStream);
/**
* parsing an XML document from any valid input
* source (a character stream, a byte stream, or a URI)
* 解析一个xml文档通过任何有效的输入资源
*/
xmlReader.parse(inputSource);
// 将文档数据解析装进list中。
List<WebURL> mWebURLs= saxParseHandler.getXMLList();
}
5.2 Pull解析xml,简单
// pull解析,简洁常用
XmlResourceParser xmlResourceParser=getResources().getXml(R.xml.test);
try {
// 不结束一直循环
while(xmlResourceParser.getEventType()!=XmlResourceParser.END_DOCUMENT){
if(xmlResourceParser.getEventType()== XmlPullParser.START_TAG){
String tagName=xmlResourceParser.getName();
if(TextUtils.equals(tagName,"item")){
String id=xmlResourceParser.getAttributeValue(null,"id");
}
}
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
6、解析json 数据
1.系统方法解析json
// 解析json
// 从本地资源json文件到输入流
InputStream is=getResources().openRawResource(R.raw.json);
// 从输入流到String
String jsonString=getStringByInputStream(is);
try {
// 从string 到 JSONObject
JSONObject jsonObject=new JSONObject(jsonString);
// 属性数据
String title=jsonObject.getString("title");
// 类,对象数据
JSONObject userJSONObject=jsonObject.getJSONObject("user");
// 属性数据
userJSONObject.getLong("id");
// 数组数据
JSONArray jsonArray=jsonObject.getJSONArray("images");
} catch (JSONException e) {
e.printStackTrace();
}
从流到String的方法
/**
* 从输入流到String
* @param is
* @return
*/
private String getStringByInputStream(InputStream is) {
String result=null;
Reader reader=new InputStreamReader(is);
char[] buffer=new char[1024];
try {
reader.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
result=new String(buffer);
return result;
}
2.使用GSON解析json, 简便
在build.gradle(Module:app)中的尾行添加,开源库GSON
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.google.code.gson:gson:2.7'
}
建数据类,接收数据
json的三种数据形式,属性,类(大括号{ }),数组(中括号[ ])。
分别对应的是基本数据类型,类,List。
public class UserData {
// 注解 ,转化
// 属性数据
@SerializedName("title")
private String mTitle;
@SerializedName("content")
private String mContent;
// 类数据
@SerializedName("user")
private User mUser;
// 数组数据
@SerializedName("images")
private List<String> mImages;
}
使用GSON
得到这个UserData对象后,再从它获得其内部各种数据。
// 使用GSON开源库
Gson gson=new Gson();
UserData userData=gson.fromJson(jsonString,UserData.class);