基于鸿蒙应用开发:每日新闻头条

本文介绍了在OpenHarmony4.0环境下,使用HttpClient进行每日新闻抓取,并在润和大禹200开发板上构建了一个新闻列表界面,包括下拉刷新、TabBar切换和网络请求限制的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于Http请求开发,每日新闻头条

环境:OpenHarmony 4.0
设备:润和大禹200开发板

1.项目预览图:

IMG_1703467124_000.jpgIMG_1703467975_001.jpgIMG_1703468014_002.jpg

2.底层架构流程图

Created with Raphaël 2.3.0 aboutToApear 调用getNews方法获取首页新闻 build() 界面渲染 向下滑动刷新 切换TabBar,getNews重新获取新闻 List点击事件跳转使用web组件加载网页 Finish

3.代码实现

(1) 主要界面
import http from '@ohos.net.http';
import NewItem from '../Component/NewItem';
import New from '../pojo/New';
import router from '@ohos.router';

@Entry
@Component
struct NewsPage {
  @State news: New[] = []
  @State content: string = ''
  @State flag: boolean = false
  @State types: string[] = ['生活', '明星', 'NBA', '经济', '商业', '趣闻', '游戏', '文学', '专栏']
  token: string = 'PpDpYWLcFLBIwYgu'
  type: number = 1
  page: number = 1
  startIndex: number = 0
  endIndex: number = 0
  downY: number = 0

  // 获取新闻
  async getNews(type: number, page: number) {
    let httpRequest: http.HttpRequest = http.createHttp()
    httpRequest.request('https://v2.alapi.cn/api/new/toutiao', {
      method: http.RequestMethod.POST,
      extraData: `type=${type}&page=${page}&token=${this.token}`

    }).then((res: http.HttpResponse) => {
      let code: string = JSON.parse(`${res.result}`).code
      let msg: string = JSON.parse(`${res.result}`).msg
      if (code == '200') {
        let n: New[] = JSON.parse(`${res.result}`).data
        // if (type == this.type) {
        //   this.news.concat(n)
        // }
        this.news = n
        this.flag = true
        console.log(`[Response SUCCESS] => CODE: ${code} MSG: ${msg}`)
      } else {
        this.content = '<h1 style="text-align: center;">出错了, 找不到资源</h1>'
        this.flag = true
        console.error(`[Response ERROR] => CODE: ${code}  MSG: ${msg}`)
      }
    }).catch((err: Error) => {
      this.content = '<h1 style="text-align: center;">出错了, 找不到资源</h1>'
      this.flag = true
      console.error('[Response ERROR] => CODE: ' + JSON.stringify(err))
    })
  }

  // 下拉刷新 => 获取下一页数据
  refreshNews(event: TouchEvent, index: number) {

    const refreshY = vp2px(100)
    switch(event.type) {
      case TouchType.Down:
        this.downY = event.touches[0].y
        break
      case TouchType.Move:
        if (this.startIndex == 0) {
          let offsetY = event.touches[0].y - this.downY
          if (offsetY > refreshY) {
            this.flag = false
            this.page ++
            this.getNews(index +1, this.page)
          }
        }
        break
    }
  }

  aboutToAppear() {
    this.getNews(1, 1)
  }

  build() {
    Column() {
      Text('今日头条').font({size: 22, weight: FontWeight.Bold}).width(100)
      Tabs() {
        ForEach(this.types, (item: string, index: number) => {
          TabContent() {
            if (this.flag) {
              List() {
                ForEach(this.news, (item: New, index: number) => {
                  ListItem() {
                    NewItem({ new: item })
                  }
                  .margin({top: 5})
                  .onClick(() => {
                    console.log(`EVENT_CLICK ON ${index}`)
                    router.pushUrl({
                      url: 'pages/DetailsPage',
                      params: item
                    })
                  })
                })
              }
              .width('90%')
              .height('90%')
              .onScrollIndex((start, end) => {
                this.startIndex = start
                this.endIndex = end
              })
              .onTouch((event: TouchEvent) => {
                this.refreshNews(event, index)
              })
            } else {
              LoadingProgress().width(100)
            }
          }
          .tabBar(item)
        })
      }.onChange((index: number) => {
        this.flag = false
        this.page = 1
        this.type = index + 1
        this.getNews(index + 1, 1)
      })
    }
    .backgroundImage($r('app.media.background01'))
    .backgroundImageSize({width: '100%', height: '100%'})
    .width('100%')
    .height('100%')
  }
}
(2) ListItem组件
import New from '../pojo/New'

@Preview
@Component
export default struct NewItem {

  new: New = new New('', '', '', '', '', '', '', '', '')


  build() {
    Column() {
      Text(this.new.title)
        .font({size: 20})
        .fontColor('#ff050f6d')
        .maxLines(1)
        .textOverflow({overflow: TextOverflow.Ellipsis})
        .width('100%')
      Row({space: 2}) {
        Text(this.new.digest).maxLines(3).width('80%')
        Image(this.new.imgsrc)
          .width('20%')
          //.alt($r('app.media.icon'))
      }.width('100%').margin({top: 2})
      Row({space: 5}) {
        Text(this.new.source).fontSize(12).fontColor('#ffb7b4b4')
        Text(this.new.time).fontSize(12).fontColor('#ffb7b4b4')
      }.width('95%').justifyContent(FlexAlign.End)
      Divider()
        .strokeWidth(1)
        .lineCap(LineCapStyle.Round)
        .linearGradient({direction: GradientDirection.Right, colors: [['#fff89cff', 0], ['#fff4ff8a', 0.25], ['#ff13f8f1', 0.5], ['#ffff8849', 0.75], ['#ff18a1fd', 1]]})

    }.width('100%')
  }
}         
(3) 实体类
@Observed
export default class New {
  title: string
  type: string
  digest: string
  docid: string
  pc_url: string
  m_url: string
  imgsrc: string
  source: string
  time: string

  constructor(title: string, type: string, digest: string, docid: string, pc_url: string, m_url: string, imgsrc: string, source: string, time: string) {
    this.title = title
    this.type = type
    this.digest = digest
    this.docid = docid
    this.pc_url = pc_url
    this.m_url = m_url
    this.imgsrc = imgsrc
    this.source = source
    this.time = time
  }
}
注意:该代码仅为应用开发示例,功能并不完善。如需运行:请在media目录添加background01背景图片文件,新闻Api为网易头条Api,每日限制请求200次

4.参考文献

鸿蒙应用开发指南

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值