Day 28 - WeatherLib

สวัสดีครับ บทความนี้เป็นบทความที่ 29 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days
สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ
- Day 1 : AndroidStaggered Grid
- Day 2 : Paralloid
- Day 3 : Retrofit
- Day 4 : SwipeRefreshLayout
- Day 5 : Android GraphView
- Day 6 : Holo Color Picker
- Day 7 : Android Async Http
- Day 8 : Crashlytics
- Day 9 : Butter Knife
- Day 10 : Android Annotations
- Day 11 : DateTimePicker
- Day 12 : Circular Progress Button
- Day 13 : ViewPager
- Day 14 : ViewPagerIndicator
- Day 15 : FadingActionBar
- Day 16 : AutofitTextView
- Day 17 : SwipeListView
- Day 18 : ShowcaseView
- Day 19 : GreenDAO
- Day 20 : AndroidViewAnimation
- Day 21 : ActiveAndroid
- Day 22 : Twitter4J
- Day 23 : ListViewAnimations
- Day 24 : AndEngine
- Day 25 : EazeGraph
- Day 26 : Cardslib
- Day 27 : AdapterKit
- Day 28 : WeatherLib
- Day 29 : FlatUI
- Day 30 : Android Firebase
สำหรับวันนี้ขอนำเสนอเรื่อง WeatherLib
WeatherLib เป็น Library ที่เอาไว้ช่วยทำแอพ Weather เหมาะกับคนต้องการนำไปพัฒนาเพื่อตรวจสอบสภาพอากาศ แค่ใช้ Library ตัวนี้ เราไม่ต้องไปกังวลเรื่อง request/response หรือว่า API จาก server จากผู้ให้บริการ เราสามารถโฟกัสแค่โค๊ดของเรา ส่วนผู้ให้บริการเรื่องสภาพอากาศ ใน WeatherLib ประกอบไปด้วย
ปกติเวลาเราต้องใช้งานพวก API จากด้านบน เราต้องขอ API แล้วดู Docs ของแต่ละเจ้า แต่ถ้าใช้ Weatherlib เราใช้โค๊ดเดียวกัน โครงสร้างเดียวกัน ใช้ได้ทุก Server เลย
จุดเด่นของ WeatherLib อย่างเช่น
- HTTP Request/response จะทำคนละ thread กับ Main UI Thread
- ค้นหาสภาพอากาศตามชื่อเมือง ชื่อประเทศได้
- ค้นหาสภาพอากาศตาม Latitude, Longitude
- ค้นหาสภาพอากาศปัจจุบัน/ สภาพอากาศย้อนหลัง
Installation
ขั้นตอนการติดตั้ง เปิดไฟล์ build.gradle
ขึ้นมา แล้วเพิ่ม dependencies ลงไปดังนี้
dependencies { compile 'com.survivingwithandroid:weatherlib:1.5.2' compile 'com.survivingwithandroid:weatherlib_volleyclient:1.5.2' compile 'com.mcxiaoke.volley:library:1.0.6@aar'}
กด Sync Gradle เป็นอันเรียบร้อย
Usage
การใช้งาน WeatherLib มีคลาสที่จำเป็นดังนี้
WeatherClient.ClientBuilder
: เป็นเหมือนตัว Builder เอาไว้สร้าง instance ของ WeatherLib ที่ใช้ภายในแอพWeatherConfig
: ตัว config เช่น พวก API_KEY (บาง Provider จะต้องทำการขอ API ด้วย)WeatherClient
: เป็นเหมือนคลาสหลัก ที่เอาไวจัดการทุกๆอย่างของ WeatherLib เช่นค้นหาสภาพอากาศปัจจุบัน ค้นหาเมือง ดูสภาพอากาศย้อนหลัง
สเตปการสร้าง เริ่มต้นด้วยการสร้าง
WeatherClient.ClientBuilder builder = new WeatherClient.ClientBuilder();
WeatherClient mClient = new WeatherClient.ClientBuilder() .attach(this) .provider(new OpenweathermapProviderType()) .httpClient(WeatherClientDefault.class) .config(new WeatherConfig()) .build();
ทำการสร้าง WeatherClient
จากตัว ClientBuilder
ส่วน pamameter แต่ละตัวมีดังนี้ครับ ตัวที่ 1 : .attach()
คือ Context ตัวที่ 2 provider()
คือชื่อของ Provider ที่ให้บริการ มีทั้งหมด 4 ชนิด
- Openweathermap -> OpenweathermapProviderType
- Yahoo! Weather -> YahooWeatherProviderType
- Weatherundergroung -> WeatherundergroundProviderType
- Forecast.io -> ForecastIOProviderType
ตัวที่ 3 httpClient()
เป็น HTTP Client ที่ WeatherLibs ใช้ระหว่าง Volley กับ OkHttp แต่ว่าตอนแรก เราใส่ dependencies ของ Volley ไป ฉะนั้นตัวนี้ก็จะใช้ WeatherDefaultClient ของ Volley ตัวที่ 4 เป็น WeatherConfig()
ส่วนเมธอดภายใน WeatherClient
ที่สามารถใช้ได้มีดังนี้
getCurrentCondition()
getForecastWeather()
getHistoricalWeather()
getHourForecastWeather()
getDefaultProviderImage()
getWeatherImage()
มาลองสร้างโปรเจ็คลองดูดีกว่าครับ
Create Project
เริ่มแรกผมทำการสร้างคลาส Activity ขึ้นมา 1 คลาส ทำการ extends ListActivity
เพื่อจะใช้ built-in ListView เลย ฉะนั้น ก็ไม่จำเป็นต้องใช้ Layout ตัวคลาสมีดังนี้
package com.devahoy.learn30androidlibraries.day28;
import android.app.ListActivity;import android.os.Bundle;import android.util.Log;import android.widget.ArrayAdapter;
import com.survivingwithandroid.weather.lib.WeatherClient;import com.survivingwithandroid.weather.lib.WeatherConfig;import com.survivingwithandroid.weather.lib.client.volley.WeatherClientDefault;import com.survivingwithandroid.weather.lib.provider.openweathermap.OpenweathermapProviderType;import com.survivingwithandroid.weather.lib.request.WeatherRequest;
public class WeatherActivity extends ListActivity {
private String TAG = WeatherActivity.class.getSimpleName();
private WeatherClient mClient; private ArrayAdapter<String> mAdapter;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
/* WeatherConfig config = new WeatherConfig();// config.ApiKey = "YOUR_API_KEY";*/
try { mClient = new WeatherClient.ClientBuilder() .attach(this) .provider(new OpenweathermapProviderType()) .httpClient(WeatherClientDefault.class) .config(new WeatherConfig()) .build();
} catch (Exception e) { // Some error Log.i(TAG, e.getMessage()); }
// YAHOO : Bangkok = 1225448 // OpenWeatherMap : Bangkok = 1609350 final WeatherRequest request = new WeatherRequest("1609350"); }}
โค๊ดด้านบนเป็นการสร้าง WeatherClient
ขึ้นมา โดยขั้นแรก ผมจะทำการดึงข้อมูล พยากรณ์อากาศล่วงหน้า ในกรุงเทพ ฉะนั้นก็จะใช้เมธอด getForecastWeather()
โดยมีโครงสร้างการใช้ดังนี้
mClient.getForecastWeather(WeatherRequest, ForecastWeatherEventListener);
ตัวแรกคือ WeatherRequest
ระบุ cityId ของเมืองนั้นๆ ในส่วนนี้หาได้จากเมธอด searchCity
หรือ searchCityByLocation
ส่วนอีกอันคือ Listener ที่จะส่งค่ากลับมา เมื่อมีการทำงานเสร็จสิ้น สุดท้าย จะได้โครงสร้างสมบูรณ์แบบนี้
mClient.getForecastWeather(request, new WeatherClient.ForecastWeatherEventListener() { @Override public void onWeatherRetrieved(WeatherForecast weatherForecast) { List<String> dataset = new ArrayList<String>(); List<DayForecast> forecases = weatherForecast.getForecast(); for (DayForecast forecast : forecases) { String result = forecast.weather.location.getCity() + " : Max: " + Math.round(forecast.forecastTemp.max) + " Min: " + Math.round(forecast.forecastTemp.min) + " Detail: " + forecast.weather.currentCondition.getDescr(); dataset.add(result); } getListView().setBackgroundColor(Color.parseColor("#26B895")); getListView().setDividerHeight(2); mAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, dataset); setListAdapter(mAdapter);
}
@Override public void onWeatherError(WeatherLibException e) { Log.e(TAG, e.getMessage()); }
@Override public void onConnectionError(Throwable throwable) {
}});
โค๊ดด้านบน เมื่อ เรารีเควสขอ สภาพอากาศของกรุงเทพไป ก็จะได้ผลลัพธ์กลับมาเป็น WeatherForecast
จากนั้นก็ นำข้อมูล City และ อุณหภูมิ ใส่ใน ListView จะได้ผลลัพธ์ดังนี้
ส่วนอีกเมธอดนึง เอาไว้สำหรับดึงข้อมูลสภาพอากาศปัจจุบันเลย ด้วยเมธอด getCurrentCondition()
mClient.getCurrentCondition(request, new WeatherClient.WeatherEventListener() { @Override public void onWeatherRetrieved(CurrentWeather cWeather) { Weather weather = cWeather.weather;
Location location = weather.location; Weather.Temperature temperature = weather.temperature;
Log.i(TAG, "City : " + location.getCity() + " Country : " + location.getCountry()); Log.i(TAG, "Temp : " + temperature.getTemp());
}
@Override public void onWeatherError(WeatherLibException t) {
}
@Override public void onConnectionError(Throwable t) {
}});
จะเห็นว่าใช้ WeatherRequest
เหมือนกับแบบแรก แต่ว่า Listener จะเปลี่ยนเป็น WeatherEventListener()
แทน ส่วนเมื่อได้ข้อมูลมาแล้ว เราจะเอาไปทำอะไรก็แล้วแต่เราเลยครับ เนื่องจากว่า WeatherLib มันเตรียมพวกคลาส Model ต่างๆมาให้เราแล้ว เช่นคลาส Weather
, Location
, Temperature
เราสามารถเข้าถึงข้อมูลพวกนี้ได้หมด สุดท้าย ก็เหลือแค่จะเอาไปใส่ในเลเอาท์ยังไง อยู่ที่การออกแบบหน้าตาเลเอาท์แล้วครับ
สำหรับบทความนี้ก็ขอจบแค่นะครับ หากสนใจอ่านรายละเอียดเพิ่มเติม หรือดูโค๊ดตัวอย่าง ก็อ่านเพิ่มได้จากต้นฉบับเลยครับ และ Tutorial เพิ่มเติม
Reference
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust