先來看一下效果
本項(xiàng)目界面搭建基于ArkUI中TS擴(kuò)展的聲明式開發(fā)范式,
數(shù)據(jù)接口是[和風(fēng)(天氣預(yù)報(bào))],
使用ArkUI自帶的網(wǎng)絡(luò)請求調(diào)用接口。
我想要實(shí)現(xiàn)的一個功能是,查詢當(dāng)前城市的實(shí)時天氣,
目前已實(shí)現(xiàn)的功能有:
- 默認(rèn)查詢北京的天氣預(yù)報(bào)
- 查看當(dāng)前的天氣
- 查看未來七天的天氣
通過本項(xiàng)目,你能學(xué)到的知識有:
- 網(wǎng)絡(luò)請求
- 條件渲染
- 狀態(tài)管理
先來看一下
接下來開始正文,
我們先分析一下結(jié)構(gòu):
我們可以分為三塊
第一部分為實(shí)時天氣信息欄
代碼如下
// @ts-nocheck
/**
* 該組件為實(shí)時天氣預(yù)報(bào)組件
*
* powered by 堅(jiān)果
* 2022/7/20
*/
@Entry
@Component
export struct RealtimeWeather{
@State temp: string = "9"
@State text: string = "堅(jiān)果"
@State isRequestSucceed: boolean = true
build(){
Column() {
Text($r("app.string.city"))
.fontSize(30)
Row() {
Text(this.temp)
.fontSize(100)
Text('℃')
.fontSize(30)
.margin({ top: 10 })
}
.alignItems(VerticalAlign.Top)
.margin({ top: 5 })
Text(this.text)
.fontSize(36)
.margin({ top: 5 })
}.margin({ top: 50 })
}
}
第二部分為
this.WeatherText("日期")
this.WeatherText("天氣")
this.WeatherText("日出")
this.WeatherText("日落")
第三部分為:
Scroll(){
Column(){
ForEach(this.future, (item: WeatherWeekData) = > {
Row() {
this.WeatherText(item.fxDate)
this.WeatherText(item.textDay)
this.WeatherText(item.sunrise)
this.WeatherText(item.sunset)
}.margin({left:10})
}, item = > item.fxDate)
}
}
最后用Column包裹
完整的代碼如下:
Main.ets
// @ts-nocheck
/*
* Copyright (c) 2021 JianGuo Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { WeatherModel, WeatherData, WeatherWeekData, } from '../model/weatherModel';
import { RealtimeWeather } from '../common/RealtimeWeather'
import { getWeekTest } from '../data/get_week_test'
import { getTest } from '../data/get_test'
import prompt from '@system.prompt';
import http from '@ohos.net.http';
@Entry
@Component
struct Main {
aboutToAppear() {
this.getRequest()
this.getWeekRequest()
}
@State realtime: WeatherData = getTest()
@State future: Array< WeatherWeekData > = getWeekTest()
@State isRequestSucceed: boolean = true
@Builder WeatherText(text: string) {
Text(text)
.fontSize(14)
.layoutWeight(1)
.textAlign(TextAlign.Center)
.margin({ top: 10, bottom: 10 })
}
build() {
Column() {
if (this.isRequestSucceed) {
// 當(dāng)前天氣
RealtimeWeather({ temp: this.realtime.temp, text: this.realtime.text })
Row() {
this.WeatherText("日期")
this.WeatherText("天氣")
this.WeatherText("日出")
this.WeatherText("日落")
}.margin({top:20})
Scroll(){
Column(){
ForEach(this.future, (item: WeatherWeekData) = > {
Row() {
this.WeatherText(item.fxDate)
this.WeatherText(item.textDay)
this.WeatherText(item.sunrise)
this.WeatherText(item.sunset)
}.margin({left:10})
}, item = > item.fxDate)
}
}
Text("數(shù)據(jù)來自和風(fēng)天氣")
.fontSize(14)
.margin({ bottom: 30 })
}
}.width("100%").height("100%")
}
// 請求方式:GET 獲取一周天氣預(yù)報(bào)
getWeekRequest() {
// 每一個httpRequest對應(yīng)一個http請求任務(wù),不可復(fù)用
let httpRequest = http.createHttp()
let url = 'https://devapi.qweather.com/v7/weather/7d?location=101010100&key=48fbadf80bbc43ce853ab9a92408373e'
httpRequest.request(url, (err, data) = > {
if (!err) {
if (data.responseCode == 200) {
console.info('=====data.result=====' + data.result)
// 解析數(shù)據(jù)
var weatherModel: WeatherModel = JSON.parse(data.result.toString())
// 判斷接口返回碼,0成功
if (weatherModel.code == 200) {
// 設(shè)置數(shù)據(jù)
this.future = weatherModel.daily
this.isRequestSucceed = true;
ForEach(weatherModel.daily, (item: WeatherWeekData) = > {
console.log(console.info('=====data.result+item.fxDate=====' + item.fxDate))
}, item = > item.date)
console.info('=====data.result===' + weatherModel.daily)
} else {
// 接口異常,彈出提示
prompt.showToast({ message: "數(shù)據(jù)請求失敗" })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: '網(wǎng)絡(luò)異常' })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: err.message })
}
})
}
// 請求方式:GET
getRequest() {
// 每一個httpRequest對應(yīng)一個http請求任務(wù),不可復(fù)用
let httpRequest = http.createHttp()
let url = 'https://devapi.qweather.com/v7/weather/now?location=101010100&key=48fbadf80bbc43ce853ab9a92408373e'
httpRequest.request(url, (err, data) = > {
if (!err) {
if (data.responseCode == 200) {
console.info('=====data.result=====' + data.result)
// 解析數(shù)據(jù)
//this.content= data.result;
// 解析數(shù)據(jù)
var weatherModel: WeatherModel = JSON.parse(data.result.toString())
// 判斷接口返回碼,0成功
if (weatherModel.code == 200) {
// 設(shè)置數(shù)據(jù)
this.realtime = weatherModel.now
this.isRequestSucceed = true;
console.info('=====data.result===this.content==' + weatherModel.now)
} else {
// 接口異常,彈出提示
prompt.showToast({ message: "數(shù)據(jù)請求失敗" })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: '網(wǎng)絡(luò)異常' })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: err.message })
}
})
}
}
里面用到了網(wǎng)絡(luò)請求
網(wǎng)絡(luò)請求的步驟
1、聲明網(wǎng)絡(luò)請求權(quán)限
在entry下的config.json中module字段下配置權(quán)限
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
2、支持http明文請求
默認(rèn)支持https,如果要支持http,在entry下的config.json中deviceConfig字段下配置
"default": {
"network": {
"cleartextTraffic": true
}
}
3、創(chuàng)建HttpRequest
// 導(dǎo)入模塊
import http from '@ohos.net.http';
// 創(chuàng)建HttpRequest對象
let httpRequest = http.createHttp();
4、發(fā)起請求
GET請求( 默認(rèn)為GET請求 )
// 請求方式:GET
getRequest() {
// 每一個httpRequest對應(yīng)一個http請求任務(wù),不可復(fù)用
let httpRequest = http.createHttp()
let url = 'https://devapi.qweather.com/v7/weather/now?location=101010100&key=48fbadf80bbc43ce853ab9a92408373e'
httpRequest.request(url, (err, data) = > {
if (!err) {
if (data.responseCode == 200) {
console.info('=====data.result=====' + data.result)
// 解析數(shù)據(jù)
//this.content= data.result;
// 解析數(shù)據(jù)
var weatherModel: WeatherModel = JSON.parse(data.result.toString())
// 判斷接口返回碼,0成功
if (weatherModel.code == 200) {
// 設(shè)置數(shù)據(jù)
this.realtime = weatherModel.now
this.isRequestSucceed = true;
console.info('=====data.result===this.content==' + weatherModel.now)
} else {
// 接口異常,彈出提示
prompt.showToast({ message: "數(shù)據(jù)請求失敗" })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: '網(wǎng)絡(luò)異常' })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: err.message })
}
})}
5、解析數(shù)據(jù)(簡單示例)
1.網(wǎng)絡(luò)請求到的json字符串
export function getTest() {
return [
{
"obsTime": "2022-07-20T09:24+08:00",
"temp": "28",
"feelsLike": "29",
"icon": "101",
"text": "多云",
"wind360": "225",
"windDir": "西南風(fēng)",
"windScale": "3",
"windSpeed": "17",
"humidity": "71",
"precip": "0.0",
"pressure": "1000",
"vis": "8",
"cloud": "91",
"dew": "21"
},
]
}
2.創(chuàng)建相應(yīng)的對象
export class WeatherWeekData {
fxDate: string //
sunrise: string //
sunset: string //
moonrise: string //
moonset: string //
moonPhase: string //
moonPhaseIcon: string //
tempMax: string //
tempMin: string //
iconDay: string //
textDay: string
textNight: string //
wind360Day: string //
windDirDay: string //
windScaleDay: string //
windSpeedDay: string //
wind360Night: string //
windDirNight: string //
dew: string //
windScaleNight: string // ,
windSpeedNight: string //
humidity: string //
precip: string //
pressure: string //
vis: string //
cloud: string //
uvIndex: string //
}
實(shí)況天氣
目前支持全國4000+個市縣區(qū)和海外15萬個城市實(shí)時天氣數(shù)據(jù),包括實(shí)時溫度、體感溫度、風(fēng)力風(fēng)向、相對濕度、大氣壓強(qiáng)、降水量、能見度、露點(diǎn)溫度、云量等數(shù)據(jù)。
)請求URL
// 北京實(shí)況天氣
https://devapi.qweather.com/v7/weather/now?location=101010100&key=你的KEY
請求參數(shù)
請求參數(shù)包括必選和可選參數(shù),如不填寫可選參數(shù)將使用其默認(rèn)值,參數(shù)之間使用&
進(jìn)行分隔。
key
用戶認(rèn)證key。如何獲取KRY可前往我之前的文章。例如 key=123456789ABC
location
需要查詢地區(qū)的LocationID或以英文逗號分隔的經(jīng)度,緯度坐標(biāo)十進(jìn)制,最多支持小數(shù)點(diǎn)后兩位),LocationID可通過[城市搜索]服務(wù)獲取。例如 location=101010100
或 location=116.41,39.92
返回?cái)?shù)據(jù)格式
// 北京實(shí)況天氣
// https://devapi.qweather.com/v7/weather/now?location=101010100&key=你的KEY
{
"code": "200",
"updateTime": "2020-06-30T22:00+08:00",
"fxLink": "http://hfx.link/2ax1",
"now": {
"obsTime": "2020-06-30T21:40+08:00",
"temp": "24",
"feelsLike": "26",
"icon": "101",
"text": "多云",
"wind360": "123",
"windDir": "東南風(fēng)",
"windScale": "1",
"windSpeed": "3",
"humidity": "72",
"precip": "0.0",
"pressure": "1003",
"vis": "16",
"cloud": "10",
"dew": "21"
},
"refer": {
"sources": [
"QWeather",
"NMC",
"ECMWF"
],
"license": [
"commercial license"
]
}
}
// 請求方式:GET
getRequest() {
// 每一個httpRequest對應(yīng)一個http請求任務(wù),不可復(fù)用
let httpRequest = http.createHttp()
let url = 'https://devapi.qweather.com/v7/weather/now?location=101010100&key=48fbadf80bbc43ce853ab9a92408373e'
httpRequest.request(url, (err, data) = > {
if (!err) {
if (data.responseCode == 200) {
console.info('=====data.result=====' + data.result)
// 解析數(shù)據(jù)
//this.content= data.result;
// 解析數(shù)據(jù)
var weatherModel: WeatherModel = JSON.parse(data.result.toString())
// 判斷接口返回碼,0成功
if (weatherModel.code == 200) {
// 設(shè)置數(shù)據(jù)
this.realtime = weatherModel.now
this.isRequestSucceed = true;
console.info('=====data.result===this.content==' + weatherModel.now)
} else {
// 接口異常,彈出提示
prompt.showToast({ message: "數(shù)據(jù)請求失敗" })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: '網(wǎng)絡(luò)異常' })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: err.message })
}
})
}
七天天氣預(yù)報(bào)
接口
// 北京7天預(yù)報(bào)
// https://devapi.qweather.com/v7/weather/7d?location=101010100&key=你的KEY
返回?cái)?shù)據(jù)
// 北京3天預(yù)報(bào)
// 商業(yè)版 https://api.qweather.com/v7/weather/3d?location=101010100&key=你的KEY
// 開發(fā)版 https://devapi.qweather.com/v7/weather/3d?location=101010100&key=你的KEY
{
"code": "200",
"updateTime": "2021-11-15T16:35+08:00",
"fxLink": "http://hfx.link/2ax1",
"daily": [
{
"fxDate": "2021-11-15",
"sunrise": "06:58",
"sunset": "16:59",
"moonrise": "15:16",
"moonset": "03:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "12",
"tempMin": "-1",
"iconDay": "101",
"textDay": "多云",
"iconNight": "150",
"textNight": "晴",
"wind360Day": "45",
"windDirDay": "東北風(fēng)",
"windScaleDay": "1-2",
"windSpeedDay": "3",
"wind360Night": "0",
"windDirNight": "北風(fēng)",
"windScaleNight": "1-2",
"windSpeedNight": "3",
"humidity": "65",
"precip": "0.0",
"pressure": "1020",
"vis": "25",
"cloud": "4",
"uvIndex": "3"
},
{
"fxDate": "2021-11-16",
"sunrise": "07:00",
"sunset": "16:58",
"moonrise": "15:38",
"moonset": "04:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "13",
"tempMin": "0",
"iconDay": "100",
"textDay": "晴",
"iconNight": "101",
"textNight": "多云",
"wind360Day": "225",
"windDirDay": "西南風(fēng)",
"windScaleDay": "1-2",
"windSpeedDay": "3",
"wind360Night": "225",
"windDirNight": "西南風(fēng)",
"windScaleNight": "1-2",
"windSpeedNight": "3",
"humidity": "74",
"precip": "0.0",
"pressure": "1016",
"vis": "25",
"cloud": "1",
"uvIndex": "3"
},
{
"fxDate": "2021-11-17",
"sunrise": "07:01",
"sunset": "16:57",
"moonrise": "16:01",
"moonset": "05:41",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "13",
"tempMin": "0",
"iconDay": "100",
"textDay": "晴",
"iconNight": "150",
"textNight": "晴",
"wind360Day": "225",
"windDirDay": "西南風(fēng)",
"windScaleDay": "1-2",
"windSpeedDay": "3",
"wind360Night": "225",
"windDirNight": "西南風(fēng)",
"windScaleNight": "1-2",
"windSpeedNight": "3",
"humidity": "56",
"precip": "0.0",
"pressure": "1009",
"vis": "25",
"cloud": "0",
"uvIndex": "3"
}
],
"refer": {
"sources": [
"QWeather",
"NMC",
"ECMWF"
],
"license": [
"commercial license"
]
}
}
代碼
// 請求方式:GET 獲取一周天氣預(yù)報(bào)
getWeekRequest() {
// 每一個httpRequest對應(yīng)一個http請求任務(wù),不可復(fù)用
let httpRequest = http.createHttp()
let url = 'https://devapi.qweather.com/v7/weather/7d?location=101010100&key=48fbadf80bbc43ce853ab9a92408373e'
httpRequest.request(url, (err, data) = > {
if (!err) {
if (data.responseCode == 200) {
console.info('=====data.result=====' + data.result)
// 解析數(shù)據(jù)
var weatherModel: WeatherModel = JSON.parse(data.result.toString())
// 判斷接口返回碼,0成功
if (weatherModel.code == 200) {
// 設(shè)置數(shù)據(jù)
this.future = weatherModel.daily
this.isRequestSucceed = true;
ForEach(weatherModel.daily, (item: WeatherWeekData) = > {
console.log(console.info('=====data.result+item.fxDate=====' + item.fxDate))
}, item = > item.date)
console.info('=====data.result===' + weatherModel.daily)
} else {
// 接口異常,彈出提示
prompt.showToast({ message: "數(shù)據(jù)請求失敗" })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: '網(wǎng)絡(luò)異常' })
}
} else {
// 請求失敗,彈出提示
prompt.showToast({ message: err.message })
}
})
}
更多鴻蒙開發(fā)知識更新在[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]參考學(xué)習(xí)。
城市搜索
調(diào)用接口(Get方式)
請求URL
# 搜索關(guān)鍵字beij
// https://geoapi.qweather.com/v2/city/lookup?location=beij&key=你的KEY
location
需要查詢地區(qū)的名稱,支持文字、以英文逗號分隔的經(jīng)度,緯度坐標(biāo)(十進(jìn)制,最多支持小數(shù)點(diǎn)后兩位)、LocationID或Adcode(僅限中國城市)。例如 location=北京 或 location=116.41,39.92
模糊搜索,當(dāng)location傳遞的為文字時,支持模糊搜索,即用戶可以只輸入城市名稱一部分進(jìn)行搜索,最少一個漢字或2個字符,結(jié)果將按照相關(guān)性和Rank值進(jìn)行排列,便于開發(fā)或用戶進(jìn)行選擇他們需要查看哪個城市的天氣。例如location=bei,將返回與bei相關(guān)性最強(qiáng)的若干結(jié)果,包括黎巴嫩的貝魯特和中國的北京市
重名,當(dāng)location傳遞的為文字時,可能會出現(xiàn)重名的城市,例如陜西省西安市、吉林省遼源市下轄的西安區(qū)和黑龍江省牡丹江市下轄的西安區(qū),此時會根據(jù)Rank值排序返回所有結(jié)果。在這種情況下,可以通過adm參數(shù)的方式進(jìn)一步確定需要查詢的城市或地區(qū),例如location=西安&adm=黑龍江
名詞解釋
Rank值
Rank值是表明一個城市或地區(qū)排名的數(shù)字,基于多種因素綜合計(jì)算而來,例如:人口、面積、GDP、搜索熱度等。取值范圍為1-10,在定位搜索服務(wù)中,返回的結(jié)果除了關(guān)鍵字的相關(guān)性以外,也會參考該城市的Rank值。數(shù)值越大代表該城市或地區(qū)的人口越多、面積更大或更加熱門。例如陜西省西安市的Rank值就要比黑龍江省牡丹江市西安區(qū)更高,當(dāng)使用“西安”作為關(guān)鍵字定位的時候,西安市的排名要高于西安區(qū)。
LocationID
LocationID或locid,是城市、地區(qū)或POI點(diǎn)的ID,一般由數(shù)字或字母+數(shù)字組成,是一個地點(diǎn)的唯一標(biāo)識。LocationID可以通過定位搜索服務(wù)獲取,中國地區(qū)、熱門海外城市、一些POI點(diǎn)的LocationID還可以通過[城市列表]下載。
審核編輯 黃宇
-
接口
+關(guān)注
關(guān)注
33文章
8718瀏覽量
152021 -
鴻蒙
+關(guān)注
關(guān)注
57文章
2397瀏覽量
43092
發(fā)布評論請先 登錄
相關(guān)推薦
基于ESP32 WiFi連接天氣預(yù)報(bào)機(jī)的設(shè)計(jì)方案
【Banana PI Leaf S3開發(fā)板試用體驗(yàn)】基于Banana PI Leaf S3的天氣預(yù)報(bào)系統(tǒng)
Android智能手機(jī)天氣預(yù)報(bào)系統(tǒng)設(shè)計(jì)及實(shí)現(xiàn)
人工智能將應(yīng)用于日常的天氣預(yù)報(bào)
基于天氣預(yù)報(bào)的自動灌溉系統(tǒng)
![基于<b class='flag-5'>天氣預(yù)報(bào)</b>的自動灌溉系統(tǒng)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Zambreti天氣預(yù)報(bào)器開源分享
![Zambreti<b class='flag-5'>天氣預(yù)報(bào)</b>器開源分享](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用ESP32進(jìn)行溫度、濕度和天氣預(yù)報(bào)
![使用ESP32進(jìn)行溫度、濕度和<b class='flag-5'>天氣預(yù)報(bào)</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于ESP8266-01的天氣預(yù)報(bào)
![基于ESP8266-01的<b class='flag-5'>天氣預(yù)報(bào)</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Arduino天氣預(yù)報(bào)小矮人
![Arduino<b class='flag-5'>天氣預(yù)報(bào)</b>小矮人](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
天氣預(yù)報(bào)顯示開源項(xiàng)目
![<b class='flag-5'>天氣預(yù)報(bào)</b>顯示開源項(xiàng)目](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
自動播放器播放天氣預(yù)報(bào)
![自動播放器播放<b class='flag-5'>天氣預(yù)報(bào)</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
DIY簡單的天氣預(yù)報(bào)裝置
![DIY簡單的<b class='flag-5'>天氣預(yù)報(bào)</b>裝置](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
物聯(lián)網(wǎng)迷你天氣預(yù)報(bào)開源分享
![物聯(lián)網(wǎng)迷你<b class='flag-5'>天氣預(yù)報(bào)</b>開源分享](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
AWTK 開源串口屏開發(fā)(11) - 天氣預(yù)報(bào)
![AWTK 開源串口屏<b class='flag-5'>開發(fā)</b>(11) - <b class='flag-5'>天氣預(yù)報(bào)</b>](https://file.elecfans.com/web2/M00/50/DA/pYYBAGLH6TyAB71EAAAPQ7KgtYA038.png)
評論