今天我想展示一下我實作的api並利用前幾篇的內容分享給大家更完整的內容。
首先在檔案這裡我先區分了ui跟專屬api的檔案夾
輸出其實就只有一個畫面
我使用到了一些spinner跟buttun輸入鍵以及顯示的文字
MainActivity
private TextView result;
private Button search;
private Spinner location_spinner,element_spinner,time_spinner;
private String selected_location,selected_element,selected_time;
private String[] location_data,element_data,time_data,tw_element;
以及api的變數
private ApiClient apiClient;
private GetApi getApi;
在oncreate時,先綁定
result = findViewById(R.id.result);
search = findViewById(R.id.search);
location_spinner = findViewById(R.id.locationName);
element_spinner = findViewById(R.id.elementName);
time_spinner = findViewById(R.id.time);
在res/values/string存這筆資料
<string-array name="location_data">
<item>宜蘭縣</item>
<item>花蓮縣</item>
<item>臺東縣</item>
<item>澎湖縣</item>
<item>金門縣</item>
<item>連江縣</item>
<item>台北市</item>
<item>新北市</item>
<item>桃園市</item>
<item>臺中市</item>
<item>臺南市</item>
<item>高雄市</item>
<item>基隆市</item>
<item>新竹縣</item>
<item>新竹市</item>
<item>苗栗縣</item>
<item>彰化縣</item>
<item>南投縣</item>
<item>雲林縣</item>
<item>嘉義縣</item>
<item>嘉義市</item>
<item>屏東縣</item>
</string-array>
<string-array name="element_data">
<item>Wx</item>
<item>PoP</item>
<item>MinT</item>
<item>CI</item>
<item>MaxT</item>
<item>All</item>
</string-array>
<string-array name="time_data">
<item>今天</item>
<item>明天</item>
<item>後天</item>
</string-array>
<string-array name="tw_element">
<item>當日天氣氣象:</item>
<item>當日降雨機率:</item>
<item>當日最低溫度:</item>
<item>當日舒適度:</item>
<item>當日最高溫度:</item>
</string-array>
在MainActivity
利用這些程式抓取上面需要的選項顯示
location_data = getResources().getStringArray(R.array.location_data);
element_data = getResources().getStringArray(R.array.element_data);
time_data = getResources().getStringArray(R.array.time_data);
tw_element = getResources().getStringArray(R.array.tw_element);
apiClient = new ApiClient();這裡我把retrofit放在ApiClient這裡,這段程式就是把retrofit設定在MainActivity的變數內。
我的程式裡寫了getApi = apiClient.myWeatherApi().create(GetApi.class);
但其實可以理解成在apiClient裡的retrofit通過url建立GetApi指定需要抓取的幾筆資料的一個介面存入getApi變數內
接著設定spinner選項列表內被選擇時的功能,這裡spinner+adapter我就跳過了
setSpinner();
search.setOnClickListener(view -> getWeather(selected_location,selected_element,selected_time));
}
private void setSpinner() {
ArrayAdapter location_adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, location_data);
ArrayAdapter element_adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, element_data);
ArrayAdapter time_adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, time_data);
location_spinner.setAdapter(location_adapter);
location_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selected_location = location_spinner.getSelectedItem().toString();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView){}
});
element_spinner.setAdapter(element_adapter);
element_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selected_element = element_spinner.getSelectedItem().toString();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {}
});
time_spinner.setAdapter(time_adapter);
time_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selected_time = time_spinner.getSelectedItem().toString();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {}
});
最後設定retrofit,這裡我做了一點巧思 ,選擇all時,但其實spinner理會認為這是一個選項並不會全選,所以我把all設成Null,當判斷遇到空值時,做遍歷全部選項當做輸出。
private void getWeather(String selectedLocation, String selectedElement, String selectedTime) {
String authorization = "CWA-745454D2-A8B2-41D1-A46D-DB35C98E07F0";
if (selectedElement.equals("All"))
selectedElement = "";
String finalSelectedElement = selectedElement;
getApi.getWeatherApi(authorization,selectedLocation,selectedElement)
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<WeatherResponse>() {
@Override
public void onNext( WeatherResponse weatherResponse) {
result.setText("");
List time_list = Arrays.asList(time_data);
List element_list = Arrays.asList(element_data);
if(weatherResponse.getElementSize() != 1){
for (int i = 0; i < weatherResponse.getElementSize(); i++) {
result.append(tw_element[i] + weatherResponse.getDataByTime(i,time_list.indexOf(selectedTime))+"\n");
}
}
else {
result.setText(tw_element[element_list.indexOf(finalSelectedElement)] + weatherResponse.getDataByTime(0,time_list.indexOf(selectedTime))+"\n");
}
}
@Override
public void onError( Throwable e) {
Log.d("test", "onError: ");
}
@Override
public void onComplete() {
Log.d("test", "onComplete: ");
}
});
}
public class ApiClient {
public Retrofit myWeatherApi(){
return new Retrofit.Builder()
.baseUrl("https://opendata.cwa.gov.tw/api/v1/rest/datastore/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory.create())
.build();
}
}
public class WeatherResponse {
public Records records;
public class Records{
public List<Location> location;
}
public class Location{
public String locationName;
public List<WeatherElement> weatherElement;
}
public class WeatherElement {
public String elementName;
public List<Time> time;
}
public class Time {
public Parameter parameter;
}
public class Parameter{
public String parameterName;
public String parameterUnit;
}
public String getDataByTime(Integer index,Integer day){
return records.location.get(0).weatherElement.get(index).time.get(day).parameter.parameterName;
}
public Integer getElementSize(){
return records.location.get(0).weatherElement.size();
}
}
public interface GetApi {
@GET("F-C0032-001")
Observable<WeatherResponse> getWeatherApi(
@Query("Authorization") String Authorization,
@Query("locationName") String locationName,
@Query("elementName") String elementName
);
}
app/Gradle Scripts/build gradle(app)
dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
//Retrofit
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//RxJava
}