Android 元件 Retrofit、JSON
Step1. Android Studio→先進行環境設定 加入網路權限第三方程式庫
詳細位置:Android Manifest
程式碼:<uses-permission android:name="android.permission.INTERNET" />
詳細位置:如下圖
程式碼: compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Step2. Android Studio→加入第三方外掛程式
詳細位置:設定→Plugins→搜尋"gsonformat"
Step3.網頁→使用Google的外掛程式,格式化JSON網頁
詳細位置:google頁面→設定→擴充功能→搜尋"Jsonformat"
Step4. Android Studio→自動生成 所要對應JSON格式的類別
詳細位置:創造一個類別,名稱=Bean
設定 Alt + Insert→GsonFormat→複製網頁內容→貼上→勾選→完成
注意事項:只要截取一個片段,但是需要完整的包覆程式碼
常用技巧:更改變數名稱→ @SerializedNmae("原本的名子")
範例: @SerializedName("CAT2")
private String category;
Step5. Android Studio→創造出一個retrofit
詳細位置:產生一個介面,名稱=InterfaceName
注意事項:Call<介面的類別名稱 > 後面產生的方法名稱可以自定義。
介面中:宣告的變數都是 public、static、final
方法()都是 public、static、abstrack
程式碼:
1. public static final Retrofit retrofit = new Retrofit.Builder()
.baseUrl("主網址")
.addConverterFactory(要轉碼的工廠.create())
.build();
2. @GET("副網址") Call < Bean > getData ();
//使用Call這個類別 做一個方法出來,<>型別就是對應到JSON格式的類別
3. InterfaceName apiService = retrofit .create (InterfaceName.class);
Step6.→開始下載JSON的資料
詳細位置:→產生一個類別,名稱=DataUtil
→類別中建立一個靜態方法(),名稱=loadUtil()
程 式 碼:
public class DataUtil {
public static void loadUtil () {
Call<Bean> call =InterfaceName.apiService.getData ();
call.enqueue(new Callback<Bean>() {
@Override
public void onResponse(Call<Bean> call, Response<Bean> response) {}
@Override
public void onFailure(Call<Bean> call, Throwable t) {}
});
}
Step7.詳細的介紹、使用Callback<Bean>(),要實現2個抽象的方法
詳細位置:類別 DataUtil
程 式 碼:
public class DataUtil {
public static void loadUtil () {
//apiservice = 我們create後 打造出的retrofit,
//apiService.getData () = apiservice去讀取資料 (讀取的型別是Call<Bean>)
Call<Bean> call =InterfaceName.apiService.getData ();
//由call.,equene=建立一個執行緒,讓app再下載同時還能做其他事情
//要做什麼事情? 我們就要new一個Callback(Bean)的事件
call.enqueue(new Callback<Bean>() {
@Override //成功連線到網路後 我要做什麼?
public void onResponse( Call<Bean> call , Response<Bean> response) {
//連線到網路,但資料取得失敗
if (!response.isSuccessful()) {
//建立一個日誌
String message = "資料取得失敗";
Log.d(TAG, message);
return; }
//連線到網路,成功取得資料
//我們要把資料取出,並由一個變數參考到這麼物件
Bean bean = response.body();
Log.d(TAG, "資料取得成功");
//做一個日誌,並且Log出 Count的訊息(由此可知)
Log.d(TAG, "count = " + bean.getResult().getCount()); }
@Override //尚未連線到網路後 我要做什麼?
public void onFailure(Call<Bean> call, Throwable t) {
Log.d(TAG, "沒有連線到網路");
}
});
}
Step8.下載完成後,如何取得更多的資料
重點摘要:類別內 創建一個方法
詳細位置:在DataUtil這個類別內部建立一個方法,方法名稱=testlogMessage();
注意事項:避免程式碼過於肥大,所以我們新建一個方法,方便使用。
程 式 碼:
//由步驟7可得知 我們已經連線到網路,成功取得資料,
//TaipeiAttractionBean bean = response.body();
//所以我們要把接收到資料的bean導入這方法,方便使用
public static void testlogMessage(Bean bean) {
//由JOSN格式我們可以得知每個景點都存在於陣列中
//而每個景點中都有很多getter方法來取得內部的資料(看bean的類別) 
//我們先做一個迴圈 (i從0開始 ; getCount=取得總共幾個景點 ; i++)
for (int i = 0; i < bean.getResult().getCount(); i++) {
//取得第 i 個景點(會比較複雜 因為是一個巢狀的類別)
TaipeiAttractionBean.ResultBean.ResultsBean attraction = bean.getResult().getAttractions().get(i);
//取得第i項景點後,我就getter它裡面的內容
//Log 很重要的是 你要加一個 "" 讓輸出的資訊轉換成為文字
Log.d(TAG, "----------------------" + i + "----------------------");
Log.d(TAG, attraction.getAddress()+"");
Log.d(TAG, attraction.getCategory()+"");
Log.d(TAG,attraction.getMRT()+"");
Log.d(TAG, attraction.getImagesURLs());
}
}
Step9.如何讀取每個景點中的各項資料
詳細位置:類別 DataUtil
注意事項:類別 DataUtil 使用 testlogMessage();這個方法
程 式 碼:
public class DataUtil {
public static void loadUtil () {
Call<Bean> call =InterfaceName.apiService.getData ();
call.enqueue(new Callback<Bean>() {
@Override
public void onResponse( Call<Bean> call , Response<Bean> response) {
if (!response.isSuccessful()) {
String message = "資料取得失敗";
Log.d(TAG, message);
return; }
//這邊很重要 我把response響應的資料 存到bean中
TaipeiAttractionBean bean = response.body();
Log.d(TAG, "資料取得成功");
//再把bean導入這一個方法
testlogMessage(bean);
Log.d(TAG, "count = " + bean.getResult().getCount()); }
@Override
public void onFailure(Call<Bean> call, Throwable t) {
Log.d(TAG, "沒有連線到網路");
}
});
}
Step10.解析、分割資訊
詳細位置:在DataUtil這個類別內部建立一個方法,方法名稱=split(String urls);
注意事項:類別內 創建一個方法
避免程式碼過於肥大,所以我們新建一個方法,方便使用。
如果你發現 資訊是一大串的程式碼,我們可以自己寫程式解析它,並放入一個陣列管理
程 式 碼 :
// 輸入"String" 返回一個陣列<String>
public static List<String> split(String urls) {
//封裝:如果得到的String是空值 我就return空值
if (urls == null || urls.length() == 0) {
return null;}
//創造陣列=待會要放字串進去
List<String> list = new ArrayList<>();
//startString = 找出"http並回傳位置,找不到則回傳-1
int startString = urls.indexOf("http");
//先宣endString 型別為int
int endString;
//迴圈開始= 如果startString有找到"http"迴圈就開始,如果找不到迴圈就結束(因為startString=-1)
while (startString >= 0) {
//endString=找到下一個"http"的位置,找不到則回傳-1
endString = urls.indexOf("http", startString + 1);
//如果endString < 0,代表找不到"http"
if (endString < 0) {
list.add(urls.substring(startString, urls.length()));
break;
}
//把字串+到陣列,substring(開始的位置,最後的位置-但不包含)
list.add(urls.substring(startString, endString));
//開始的位置=最後的位置
startString = endString;
}
//返回一個字串
return list;
}
|
Step10.讀取已剖析URL網址的資料
重點摘要:在 testlogMessage();內加入split(String urls);,並寫一個迴圈Log出剖析後的資訊
詳細位置:在DataUtil這個類別內的方法(),方法名稱=testlogMessage();
程 式 碼 :
public static void testlogMessage(Bean bean) {
//List<TaipeiAttractionBean.ResultBean.ResultsBean> test_test =bean.getResult().getAttractions();
//原本景點都存在於陣列中,而現在又要做一個陣列存在於陣列中,所以會比較複雜
//我們需要把第i項景點 裡面的陣列 給紀錄,故在欄位這邊宣告使用。
List<List<String>> imageUrlsList= new ArrayList<>();
for (int i = 0; i < bean.getResult().getCount(); i++) {
//取得第 i 個景點(會比較複雜 因為是一個巢狀的類別)
TaipeiAttractionBean.ResultBean.ResultsBean attraction = bean.getResult().getAttractions().get(i);
Log.d(TAG, "----------------------" + i + "----------------------");
Log.d(TAG, attraction.getAddress()+"");
Log.d(TAG, attraction.getCategory()+"");
Log.d(TAG,attraction.getMRT()+"");
Log.d(TAG, attraction.getImagesURLs());
//步驟1:剖析第i個景點中的網址,並存放在陣列中,並由list參考
List<String> list = split(attraction.getImagesURLs());
//步驟2:再把list放到一個陣列中
imageUrlsList.add(list);
for (int j =0; j<list.size();j++){
//log出陣列中第j個網址,直到j++<陣列的大小
Log.d(TAG,list.get(j).toString());
}
}}
|
Step11完整的程式碼
package com.example.andy.lab14_opendata.util;
import android.util.Log;
import com.example.andy.lab14_opendata.beans.TaipeiAttractionBean;
import com.example.andy.lab14_opendata.model.TaipeiAttractions;
import com.example.andy.lab14_opendata.myapp.MyApp;
import com.example.andy.lab14_opendata.observer.Observer;
import com.example.andy.lab14_opendata.service.TaipeiAttractionService;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class DataUtil {
public static final String TAG = "LoadOpenData";
public static void loadTaipeiAttractions( ) {
Call<Bean> call = TaipeiAttractionService.apiService.getData();
//產生執行緒,並響應一個Callback的事件
call.enqueue(new Callback<TaipeiAttractionBean>() {
@Override
public void onResponse(Call<Bean> call, Response<Bean> response) {
if (!response.isSuccessful()) {
String message = "response is unSuccessful " + response.code();
Log.d(TAG, message);
return;
}
//下載完成 把response的資源丟入到bean
Bean bean = response.body();
Log.d(TAG, "response.isSuccessful()");
Log.d(TAG, "count = " + bean.getResult().getCount());
testlogAttraction(bean);
}
@Override
public void onFailure(Call<TaipeiAttractionBean> call, Throwable t) {
Log.d(TAG, "沒有連線到網路");
}
});
}
public static List<String> split(String urls) {
if (urls == null || urls.length() == 0) {return null;}
List<String> list = new ArrayList<>();
int startString = urls.indexOf("http");
int endString;
while (startString >= 0) {
endString = urls.indexOf("http", startString + 1);
if (endString < 0) {
list.add(urls.substring(startString, urls.length()));
break;
}
list.add(urls.substring(startString, endString));
startString = endString;
}
return list;
}
//輸入"陣列" 我就執行內容中的程式
public static void testlogAttraction(Bean bean) {
List<List<String>> imageUrlsList= new ArrayList<>();
for (int i = 0; i < bean.getResult().getCount(); i++) {
TaipeiAttractionBean.ResultBean.ResultsBean attraction = bean.getResult().getAttractions().get(i);
List<TaipeiAttractionBean.ResultBean.ResultsBean> test_test = bean.getResult().getAttractions();
Log.d(TAG, "----------------------" + i + "----------------------");
Log.d(TAG, attraction.getAddress()+"");
Log.d(TAG, attraction.getCategory()+"");
Log.d(TAG,attraction.getMRT()+"");
Log.d(TAG, attraction.getImagesURLs());
List<String> list = split(attraction.getImagesURLs());
imageUrlsList.add(list);
for (int j =0; j<list.size();j++){
Log.d(TAG,list.get(j).toString());
}
}
}
}
沒有留言:
張貼留言