Day 28 - WeatherLib

Published on
Android
2014/08/day-28-learn-weatherlib
Discord

สวัสดีครับ บทความนี้เป็นบทความที่ 29 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days

สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ

สำหรับวันนี้ขอนำเสนอเรื่อง 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 จะได้ผลลัพธ์ดังนี้

Result

ส่วนอีกเมธอดนึง เอาไว้สำหรับดึงข้อมูลสภาพอากาศปัจจุบันเลย ด้วยเมธอด 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

Buy Me A Coffee
Authors
Discord