我想要去约会应该选在什么时间呢——天气预报Harmony实现

        前言

        在某个平凡的午后,她收到了他的消息:“想你,一起看雨后的彩虹?”她的心湖泛起了涟漪,就像HarmonyOS中的分布式数据管理,每一次心跳都被精准记录。

        HarmonyOS,这个万物互联的智能操作系统,正悄悄地为他们的爱情加冕。她想,如果HarmonyOS能预测天气,那每一次约会,都将是一场精心策划的浪漫。她想象着,在HarmonyOS的助力下,他们将如何在雨后的街头,寻找最美的彩虹;如何在晴朗的夜晚,数着星星,分享彼此的秘密。

        他,一个科技的信徒,用HarmonyOS,为他们的爱情添加了一抹智能的色彩。在HarmonyOS的指引下,他可以预测天气,选择最佳的约会时间;他可以规划路线,让每一次出行都如诗如画。HarmonyOS,让每一次约会都成为了浪漫的冒险。


        一:效果

        1. 欢迎页面

        2. 主页面

        3. 城市管理和城市添加页面


         二:开发问题和解决方法

        1. 天气信息获取(HTTP请求)

                                        本项目采用和风天气的api获取数据

interface CityCodeResponse {
  location : Array<City<WeatherInformation>>;
}

class HttpModel {
  //基础的网络请求路径
  private WeatherBaseURL: string = 'https://devapi.qweather.com/v7/'
  private CityBaseURL: string = 'https://geoapi.qweather.com/v2/city/lookup?'
  private key: string = '5936dc34239542f099986a0bf48280c4'
   //private key:string='f6b4c31d80db485aabdbea8277545500'


  //获取城市的信息,返回一个 City<WeatherItem> 类型的数组
  async GetCityInformation(CityName: string): Promise<City<WeatherInformation>[]> {
    let httpRequest = http.createHttp() //创建唯一一个http的请求对象
    try {
      let Result = await httpRequest.request(
        // 1. 请求的网址
        this.CityBaseURL,
        // 2. 请求的选择
        {
          method: http.RequestMethod.GET, //数据请求的方式,此处直接为得到数据
          extraData: { location: CityName, key: this.key }, //请求的选项
        }
      )
      // 3.处理相应的结果
      if (Result.responseCode === 200) {
        let resultInformation = JSON.parse(Result.result.toString()) as CityCodeResponse
        console.log('城市搜索成功', JSON.stringify(resultInformation))

        //Array.prototype.map 方法,数组中的每个元素都调用一个提供的函数,这段代码中使用当前的元素,创建一个新的City类型
        //将 responseData.location 中的每个元素转换为 City<WeatherItem> 实例,并将这些实例收集到 CityMessage 数组中。
        let CityMessage: City<WeatherInformation>[] =
          resultInformation.location.map(loc => new City<WeatherInformation>(loc.name, loc.id))
        return CityMessage
      } else {
        console.log('城市搜索失败:错误1', JSON.stringify(Result));
        throw new Error(`服务器响应错误:${Result.responseCode}`);
      }
    } catch (error) {
      console.log('城市搜索失败:错误2', JSON.stringify(error));
      if (error instanceof Error) {
        if (error.message.includes("Couldn't resolve host name")) {
          throw new Error('网络连接失败,请检查您的网络设置');
        } else if (error.message.includes("Timeout was reached")) {
          throw new Error('网络请求超时,请检查您的网络连接并重试');
        } else {
          throw new Error('搜索失败:' + error.message);
        }
      } else {
        throw new Error('未知错误发生,请稍后重试');
      }
    } finally {
      httpRequest.destroy();
    }
  }

  //可以返回任意类型的数据,params:一个可选的字符串类型参数,代表额外的请求参数
  GetWeatherInformation<T>(type: string, cityId: string | undefined, time: string, params?: string): Promise<T> {
    return new Promise(async (resolve, reject) => {
      let httpRequest = http.createHttp()
      let resp = httpRequest.request(
        `${this.WeatherBaseURL}/${type}/${time}`,
        {
          method: http.RequestMethod.GET,
          extraData: { type: params, location: cityId, key: this.key }
        }
      )
      await resp.then(resp => {
        if (resp.responseCode === 200) {
          let data: T = JSON.parse(resp.result.toString()) as T
          resolve(data)
        } else {
          console.log('获取信息失败 error:', JSON.stringify(resp))
          reject(`获取${time}天气失败`)
        }
      })
    })
  }
}

//作为唯一的实例对象进行导出
let httpModel = new HttpModel()
export default httpModel as HttpModel

        request接口开发步骤 :

  1.  调用createHttp()方法,创建一个HttpRequest对象。
  2.  调用该对象的request()方法,传入http请求的url地址和可选参数,发起网络请求。
  3.  按照实际业务需要,解析返回结果。

         在主页面中对于异步处理后获取数据(异步处理)

async aboutToAppear(): Promise<void> {

    this.city = this.CityInformation[this.index]

    await httpModel.GetWeatherInformation<WeatherInformation>('weather', this.city.id, '24h').then((result) => {
      if (result.hourly) {
        this.hourWeather =
          new WeatherInformation(result.code, result.updateTime, result.fxLink, undefined, result.hourly,
            undefined,result.refer)
        console.log('天气信息小时成功' + JSON.stringify(this.hourWeather))
      }
    })

    await httpModel.GetWeatherInformation<WeatherInformation>('weather', this.city.id, '7d').then((result) => {
      if (result.daily) {
        this.daysWeather = new WeatherInformation(result.code, result.updateTime, result.fxLink, undefined,
          this.hourWeather.hourly, result.daily, result.refer)
        console.log('天气信息7天成功' + JSON.stringify(this.daysWeather))
      }
    })


    await httpModel.GetWeatherInformation<ConditionInformation>('indices', this.city.id, '1d',
      '1,2,3,4,6,8,9,15,16').then((result) => {
      if (result.daily) {
        this.lifeIndexCondition =
          new ConditionInformation(result.code, result.updateTime, result.fxLink, undefined, undefined,
            result.daily, result.refer)
        console.log('天气信息生活指数成功' + JSON.stringify(this.lifeIndexCondition))
      }
    })

    await httpModel.GetWeatherInformation<ConditionInformation>('warning', this.city.id, 'now').then((result) => {
      if (result.warning) {
        this.warningCondition =
          new ConditionInformation(result.code, result.updateTime, result.fxLink, result.warning, undefined, undefined,
            result.refer)
        console.log('天气信息预警成功' + JSON.stringify(this.warningCondition))
      }
    })

    await httpModel.GetWeatherInformation<ConditionInformation>('air', this.city.id, 'now').then((result) => {
      if (result.now) {
        this.airCondition =
          new ConditionInformation(result.code, result.updateTime, result.fxLink, this.warningCondition.warning,
            result.now, this.lifeIndexCondition.daily, result.refer)
        console.log('空气质量的天气信息成功' + JSON.stringify(this.airCondition))
      }
    })

    this.isLoading = true
    this.updateBackground()
  }

         2. 全局变量的存储(AppStorage)

        AppStorage是鸿蒙操作系统中用于管理应用全局UI状态的存储机制。它是在应用启动时由UI框架创建的单例,为应用程序的UI状态属性提供中央存储。AppStorage中的属性可以在应用的主线程内多个UIAbility实例间共享,支持双向同步,这意味着数据可以存在于本地或远程设备上,并具有不同的功能,如数据持久化。

//@Watch应用于对状态变量的监听。如果需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
  @State @Watch('updateBackground') myBackgroundImage: Resource = $r("app.media.background_loading")
  @StorageLink('CityInformation') CityInformation: City<WeatherInformation>[] = [] //城市的代码集合
  @StorageLink('CurrentCityIndex') CurrentCityIndex: number = 0
  @State judge: boolean = true
  private swiperController: SwiperController = new SwiperController()

  async onPageShow(): Promise<void> {
    if (this.judge) {
      await this.loadCityInformation()
      this.judge = false
      AppStorage.setOrCreate('CityInformation', this.CityInformation)
    }
    this.updateBackground()
  }

        @StorageLink装饰器使数据在AppStorage中持久化,实现跨页面的数据共享。

        3. 监听状态变量(@Watch) 

        @Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当在严格相等为false的情况下,就会触发@Watch的回调。

        观察变化和行为表现:

  1. 当观察到状态变量的变化(包括双向绑定的AppStorageLocalStorage中对应的key发生的变化)的时候,对应的@Watch的回调方法将被触发;

  2. @Watch方法在自定义组件的属性变更之后同步执行;

  3. 如果在@Watch的方法里改变了其他的状态变量,也会引起状态变更和@Watch的执行;

  4. 在第一次初始化的时候,@Watch装饰的方法不会被调用,即认为初始化不是状态变量的改变。只有在后续状态改变时,才会调用@Watch回调方法。

@Prop @Watch('onDaysWeatherChange') daysWeather: WeatherInformation

  onDaysWeatherChange(newVal: WeatherInformation) {
    if (newVal) {
      this.drawLineChart1(); // 调用第一个方法
      this.drawLineChart2(); // 调用第二个方法
    }
  }

        因为天气信息获取是通过异步方法进行实现的,导致获取数据前就应绘制空图像,达不到理想的效果。

   对于 @Watch('onDaysWeatherChange') 装饰器被用来监听 daysWeather 属性的任何变化。当 daysWeather 的值被更新时,onDaysWeatherChange 方法会被自动调用。方法内部的逻辑会检查传入的新值 newVal 是否存在(即是否非空),再调用 drawLineChart1 和 drawLineChart2 方法。意味着 daysWeather 属性可能包含需要用绘制图表的天气信息,而 onDaysWeatherChange 方法被设计为在接收到新数据时调用绘制图表的逻辑,以更新或重新渲染图表。


        三 :GitHub 

        GitHub库 : rainandline/weather_forecast (github.com)


         尾言

        选择最佳约会时间,更重要的是,通过科技的力量,让每一次约会都充满了惊喜与浪漫。HarmonyOS,让爱,无界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值