●補充說明
(一)用volley來寫網路的存取程式
=>volley是google官方作的,且為google官方推薦的第三方元件,已經把抓資料的細節都包好了
=>使用volley有四個步驟
1.建立queue(佇列)=>排隊
2.建立request(要求)=>去存取一個網路資源的要求,執行第二個步驟時,要丟三個參數
=>
a.url
b.成功了要做甚麼=>這是在主執行緒上做,所以可以動到ui
c.失敗了要做甚麼
3.把2加入1(讓request排隊)
4. 1.start();(叫隊伍開始動)
=>做之前要先設定權限
<uses-permission android:name="android.permission.INTERNET"/>
=>在build.gradle(android建置系統的設定檔)的dependencies中加入下面內容
dependencies {
....
compile 'com.android.volley:volley:1.0.0'
}
**說明:
這個做法就可以直接外掛這個library進來,完成後點上面的sync now,此時網路不能斷,因為會去抓library
(二)openData的概念:政府利用人民的稅金收集到很多資料,應該要去識別化(和隱私脫鉤),讓人民能夠很方便的使用這些資料
(三)使用openData做的app可以賣錢也可以掛廣告,行政院的態度是不能賣raw data,但是可以加值資料(ex變成圖片),就可以賣錢,但部分下屬單位如高公局的即時車速就規定不能賣錢
(四)JSON:javascript轉出來的物件標註格式
=>這邊以新北市政府動物之家的資料為例,做json之前要先看資料格式
=>[]代表陣列,{}代表物件
=>可以看到這個資料是一整個陣列,裡面包了很多物件
=>district、address這些是屬性,八里、八里區長坑里...這些是內容


●程式說明
(ㄧ)Volley的部分
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue queue= Volley.newRequestQueue(MainActivity.this);
StringRequest request=new StringRequest("http://google.com.tw", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("Net",response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("NET",error.toString());
}
});
queue.add(request);
//queue.start();
}
}
**說明:
1.因為queue只能有一個,所以不能new一個RequestQueu,而是透過 Volley.newRequestQueue來取得queue
=>這是一個Singleton/single pattern的作法:當有一些系統上的資源,你希望那個物件在系統上只有一份,唯一的一份不要有第二份,就不能讓它new,要做一個static method,利用這個靜態method傳回你要傳回的物件
2. StringRequest我們這邊用三個參數的版本(還有四個參數的版本),上網抓到的字串就會放在 String response中
3.如果要抓圖片可以用ImageRequest
4.要注意的是,最後不需要使用queue.start(),因為Volley在初始化RequestQueu時已經call過start()了,如果在呼叫一次會出現錯誤訊息:com.android.volley.NoConnectionError: java.io.InterruptedIOException
(二)Json的部分可以分為兩種做法
作法一:使用JSONArray和JSONObject
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue queue= Volley.newRequestQueue(MainActivity.this);
StringRequest request=new StringRequest("http://data.ntpc.gov.tw/od/data/api/BF90FA7E-C358-4CDA-B579-B6C84ADC96A1?$format=json", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONArray array=new JSONArray(response);
for (int i=0;i<array.length();i++){
JSONObject obj=array.getJSONObject(i);
Log.d("Net","district:"+obj.getString("district"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("NET",error.toString());
}
});
queue.add(request);
}
}
**說明
1.把抓下來的jSON資料放在response中,就可以轉出來變成json陣列
2.用迴圈去跑每一個array的物件取出來,然後用log顯示該署性的內容(因為要用getString,所以不能用foreach)
3.因為這份資料是用array包裹物件,所以是用JSONArray 去轉,如果是用物件包裹array,就要用 JSONObject去轉(依資料格式來決定)
作法二:利用gson函式庫(https://github.com/google/gson) 也是google的
=>一樣要在build.gradle中掛library
compile 'com.google.code.gson:gson:2.8.2'
=>看raw data的資料有四個屬性,要先寫一個類別加上四個屬性,內容必須和資料中完全一樣
自建類別:AnimalHome.java
public class AnimalHome {
public String district;
public String address;
public String tel;
public String opening_hours;
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue queue= Volley.newRequestQueue(MainActivity.this);
StringRequest request=new StringRequest("http://data.ntpc.gov.tw/od/data/api/BF90FA7E-C358-4CDA-B579-B6C84ADC96A1?$format=json", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Gson gson=new Gson();
AnimalHome[] ah;
ah=gson.fromJson(response,AnimalHome[].class);
for(AnimalHome a:ah){
Log.d("net",a.district);
Log.d("net",a.address);
}
String str = gson.toJson(ah);
Log.d("NET", str);
ArrayList<AnimalHome> list1 = new ArrayList<>();
for (AnimalHome a : ah)
{
list1.add(a);
}
String str2 = gson.toJson(list1);
Log.d("NET", str2);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("NET",error.toString());
}
});
queue.add(request);
}
}
**說明:
1.起一個gson物件
2.因為要用泛型,所以先建立我們自訂類別AnimalHome的陣列
3.用fromJson方法看下圖,第一個參數是json的字串內容,第二個參數是泛型類別(T就是Type),也就是要轉出來的型別,這邊我們要轉成我們自訂的類別,寫法為
AnimalHome[].class,把json的每一個屬性放進class中(即把json字串內容--resopnse轉成自訂的類別的陣列)


4.透過foreach迴圈,抓陣列每個屬性的值
5.如果要把陣列或arraylist或是string再轉回jason,就用 gson.toJson
6.測試,建立一個新的arraylist <AnimalHome>,把ah中的每一筆資料透過foreach迴圈放到新建的arraylist中,再用 gson.toJson轉成JSON
=>當資料大概幾百筆,且不需要很多搜尋和篩選,就可以用此做法把ArrayList存成JSON格式(文字檔),隨時可以讀出來再轉成Arrayloist(非常簡單的存檔作法,修改刪除只需要用add和remove就可以,不需要動用到資料庫)
=>當資料量大且需要很多搜尋和篩選時,才需要使用資料庫
●用volley抓網路資料可能會遇到的問題(以抓聯合新聞的rss為例)
1.先授權<uses-permission android:name="android.permission.INTERNET"/>
2.build.gradle加入compile 'com.android.volley:volley:1.0.0'
3. 如果直接用之前的做法會發現抓回來的資料都是亂碼
RequestQueue queue= Volley.newRequestQueue(MainActivity.this);
StringRequest request=new StringRequest("https://udn.com/rssfeed/news/2/6638?ch=news",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("NET", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(request);


=>這是因為聯合新聞網沒有在xml的開頭準確的標示編碼要用utf8,所以volley不知道要用utf8編碼去處理
=>有些網站有這個問題還不會出現亂碼,而是直接沒有反應,這樣就會很難查
=>做法:自己寫一個utf8StringRequest class繼承StringRequest
public class UTF8StringRequest extends StringRequest {
public UTF8StringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(method, url, listener, errorListener);
}
public UTF8StringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(url, listener, errorListener);
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String utf8String = null;
try {
utf8String = new String(response.data, "UTF-8");
return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
}
**說明:
1.utf8String = new String(response.data, "UTF-8");
這邊的response.data是一個byte array,要用UTF-8的方法轉成字串
2.再把MainActivity.java的
StringRequest request=new StringRequest 改成 StringRequest request=new UTF8StringRequest
●程式參考(GitHub):
實作透過Volley、JSONArray、JSONObject、GSON取得Open Data資料
文章標籤
全站熱搜