0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開發(fā)案例:【新聞數(shù)據(jù)加載】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-22 17:22 ? 次閱讀

介紹

本篇Codelab是基于ArkTS的聲明式開發(fā)范式實現(xiàn)的樣例,主要介紹了數(shù)據(jù)請求和touch事件的使用。包含以下功能:

  1. 數(shù)據(jù)請求。
  2. 列表下拉刷新。
  3. 列表上拉加載。

相關(guān)概念

  • [List組件]:列表包含一系列相同寬度的列表項。
  • [Tabs]:通過頁簽進行內(nèi)容視圖切換。
  • [TabContent]:僅在Tabs中使用,對應(yīng)一個切換頁簽的內(nèi)容視圖。
  • [數(shù)據(jù)請求]:提供HTTP數(shù)據(jù)請求能力。
  • [觸摸事件onTouch]:觸摸動作觸發(fā)調(diào)用該方法。

相關(guān)權(quán)限

添加網(wǎng)絡(luò)權(quán)限:ohos.permission.INTERNET。

使用說明

服務(wù)端搭建流程

  1. 搭建nodejs環(huán)境:本篇Codelab的服務(wù)端是基于nodejs實現(xiàn)的,需要安裝nodejs,如果您本地已有nodejs環(huán)境可以跳過此步驟。
    1. 檢查本地是否安裝nodejs:打開命令行工具(如Windows系統(tǒng)的cmd和Mac電腦的Terminal,這里以Windows為例),輸入node -v,如果可以看到版本信息,說明已經(jīng)安裝nodejs。
    2. 如果本地沒有nodejs環(huán)境,您可以去nodejs官網(wǎng)上下載所需版本進行安裝配置。
    3. 配置完環(huán)境變量后,重新打開命令行工具,輸入node -v,如果可以看到版本信息,說明已安裝成功。
  2. 構(gòu)建局域網(wǎng)環(huán)境:測試本Codelab時要確保運行服務(wù)端代碼的電腦和測試機連接的是同一局域網(wǎng)下的網(wǎng)絡(luò),您可以用您的手機開一個個人熱點,然后將測試機和運行服務(wù)端代碼的電腦都連接您的手機熱點進行測試。
  3. 運行服務(wù)端代碼:在本項目的HttpServerOfNews目錄下打開命令行工具,輸入npm install 安裝服務(wù)端依賴包,安裝成功后輸入npm start點擊回車。看到“服務(wù)器啟動成功!”則表示服務(wù)端已經(jīng)在正常運行。
  4. 連接服務(wù)器地址:打開命令行工具,輸入ipconfig命令查看本地ip,將本地ip地址復(fù)制到src/main/ets/common/constant/CommonConstants.ets文件下的23行,注意只替換ip地址部分,不要修改端口號,保存好ip之后即可運行Codelab進行測試。

前端使用說明

  1. 點擊應(yīng)用進入主頁面,頁面使用tabBar展示新聞分類,tabContent展示新聞列表,新聞分類和新聞列表通過請求nodejs服務(wù)端獲取。
  2. 點擊頁簽或左右滑動頁面,切換標(biāo)簽并展示對應(yīng)新聞類型的數(shù)據(jù)。
  3. 新聞列表頁面,滑動到新聞列表首項數(shù)據(jù),接著往下滑動會觸發(fā)下拉刷新操作,頁面更新初始4條新聞數(shù)據(jù),滑動到新聞列表最后一項數(shù)據(jù),往上拉會觸發(fā)上拉加載操作,新聞列表會在后面加載4條新聞數(shù)據(jù)。

環(huán)境搭建

鴻蒙開發(fā)指導(dǎo)文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開發(fā)板類型:[潤和RK3568開發(fā)板]。
  • OpenHarmony系統(tǒng):3.2 Release。

搜狗高速瀏覽器截圖20240326151547.png

環(huán)境搭建

完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進制)。以3.2Release版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發(fā)板的燒錄]
  3. 搭建開發(fā)環(huán)境。
    1. 開始前請參考[工具準(zhǔn)備],完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
    2. 開發(fā)環(huán)境配置完成后,請參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”)。
    3. 工程創(chuàng)建完成后,選擇使用[真機進行調(diào)測]。

代碼結(jié)構(gòu)解讀

本篇Codelab只對核心代碼進行講解,對于完整代碼,我們會在gitee中提供。

├──entry/src/main/ets                   // ArkTS代碼區(qū)
│  ├──common
│  │  ├──constant
│  │  │  └──CommonConstant.ets          // 公共常量類
│  │  └──utils
│  │     ├──HttpUtil.ets                // 網(wǎng)絡(luò)請求方法
│  │     ├──Logger.ets                  // 日志工具類
│  │     ├──PullDownRefresh.ets         // 下拉刷新方法
│  │     └──PullUpLoadMore.ets          // 上拉加載更多方法
│  ├──entryability
│  │  └──EntryAbility.ts                // 程序入口類
│  ├──pages
│  │  └──Index.ets                      // 主頁面
│  ├──view
│  │  ├──CustomRefreshLoadLayout.ets    // 下拉刷新、上拉加載布局文件
│  │  ├──LoadMoreLayout.ets             // 上拉加載布局封裝
│  │  ├──NewsItem.ets                   // 新聞數(shù)據(jù)
│  │  ├──NewsList.ets                   // 新聞列表
│  │  ├──NoMoreLayout.ets               // 上拉停止布局封裝
│  │  ├──RefreshLayout.ets              // 下拉刷新布局封裝
│  │  └──TabBar.ets                     // 新聞類型頁簽
│  └──viewmodel
│     ├──NewsModel.ets                  // 新聞模型類
│     └──NewsViewModel.ets              // 新聞ViewModel
├──entry/src/main/resources             // 資源文件目錄
└──HttpServerOfNews                     // 服務(wù)端代碼

構(gòu)建主界面

本章節(jié)將介紹新聞列表頁面的實現(xiàn),用tabBar展示新聞分類,tabContent展示新聞列表,效果圖如圖所示:

在TabBar.ets文件中的aboutToAppear()方法里獲取新聞分類。

// TabBar.ets
aboutToAppear() {
  // 請求服務(wù)端新聞類別
  NewsViewModel.getNewsTypeList().then((typeList: NewsTypeBean[]) = > {
    this.tabBarArray = typeList;
  }).catch((typeList: NewsTypeBean[]) = > {
     this.tabBarArray = typeList;
  });
}

在NewsList.ets文件中的aboutToAppear()方法里獲取新聞數(shù)據(jù),將數(shù)據(jù)加載到新聞列表頁面ListLayout布局中。

// NewsList.ets
changeCategory() {
  this.newsModel.currentPage = 1;
  NewsViewModel.getNewsList(this.newsModel.currentPage, this.newsModel.pageSize, Const.GET_NEWS_LIST)
    .then((data: NewsData[]) = > {
      this.newsModel.pageState = PageState.Success;
      if (data.length === this.newsModel.pageSize) {
        this.newsModel.currentPage++;
        this.newsModel.hasMore = true;
      } else {
        this.newsModel.hasMore = false;
      }
      this.newsModel.newsData = data;
    })
    .catch((err: string | Resource) = > {
      promptAction.showToast({
        message: err,
        duration: Const.ANIMATION_DURATION
      });
      this.newsModel.pageState = PageState.Fail;
    });
}

aboutToAppear() {
  // 請求服務(wù)端新聞數(shù)據(jù)
  this.changeCategory();
}
...
@Builder ListLayout() {
  List() {
    ...
    ForEach(this.newsModel.newsData, (item: NewsData) = > {
      ListItem() {
        // 新聞數(shù)據(jù)
        NewsItem({ newsData: item })
      }
      .height($r('app.float.news_list_height'))
      .backgroundColor($r('app.color.white'))
      .margin({ top: $r('app.float.news_list_margin_top') })
      .borderRadius(Const.NewsListConstant_ITEM_BORDER_RADIUS)
    }, (item: NewsData, index?: number) = > JSON.stringify(item) + index)
    ...
  }
  ...
}

數(shù)據(jù)請求

在module.json5文件中配置如下權(quán)限:

// module.json5
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "reason": "$string:dependency_reason",
    "usedScene": {
      "abilities": [
        "EntryAbility"
      ],
      "when": "inuse"
    }
  }
]

這一章節(jié),將基于新聞數(shù)據(jù)請求來介紹如何從服務(wù)端請求數(shù)據(jù)。

導(dǎo)入http模塊,封裝httpRequestGet方法,調(diào)用者傳入url地址和所需參數(shù)發(fā)起網(wǎng)絡(luò)數(shù)據(jù)請求。

// HttpUtil.ets
import http from '@ohos.net.http';
...
export function httpRequestGet(url: string): Promise< ResponseResult > {
  let httpRequest = http.createHttp();
  // 發(fā)送數(shù)據(jù)請求
  let responseResult = httpRequest.request(url, {
    method: http.RequestMethod.GET,
    readTimeout: Const.HTTP_READ_TIMEOUT,
    header: {
      'Content-Type': ContentType.JSON
    },
    connectTimeout: Const.HTTP_READ_TIMEOUT,
    extraData: {}
  });
  let serverData: ResponseResult = new ResponseResult();
  // 處理數(shù)據(jù),并返回
  return responseResult.then((value: http.HttpResponse) = > {
    Logger.info(`http value ${JSON.stringify(value)}`);
    if (value.responseCode === Const.HTTP_CODE_200) {
      // 獲取返回數(shù)據(jù)
      let result = `${value.result}`;
      let resultJson: ResponseResult = JSON.parse(result);
      if (resultJson.code === Const.SERVER_CODE_SUCCESS) {
        serverData.data = resultJson.data;
      }
      serverData.code = resultJson.code;
      serverData.msg = resultJson.msg;
    } else {
      serverData.msg = `${$r('app.string.http_error_message')}&${value.responseCode}`;
    }
    return serverData;
  }).catch(() = > {
    serverData.msg = $r('app.string.http_error_message');
    return serverData;
  })
}

在NewsViewModel.ets文件中封裝getNewsList方法,調(diào)用httpRequestGet方法請求服務(wù)端,用Promise異步保存返回的新聞數(shù)據(jù)列表。

// NewsViewModel.ets
// 獲取服務(wù)端新聞數(shù)據(jù)列表
getNewsList(currentPage: number, pageSize: number, path: string): Promise< NewsData[] > {
  return new Promise(async (resolve: Function, reject: Function) = > {
    let url = `${Const.SERVER}/${path}`;
    url += '?currentPage=' + currentPage + '&pageSize=' + pageSize;
    httpRequestGet(url).then((data: ResponseResult) = > {
      if (data.code === Const.SERVER_CODE_SUCCESS) {
        resolve(data.data);
      } else {
        Logger.error('getNewsList failed', JSON.stringify(data));
        reject($r('app.string.page_none_msg'));
      }
    }).catch((err: Error) = > {
      Logger.error('getNewsList failed', JSON.stringify(err));
      reject($r('app.string.http_error_message'));
    });
  });
}

下拉刷新

本章節(jié)將以下拉刷新的功能效果來介紹touch事件的使用。效果圖如圖所示:

創(chuàng)建一個下拉刷新布局CustomLayout,動態(tài)傳入刷新圖片和刷新文字描述。

// CustomRefreshLoadLayout.ets
build() {
  Row() {
    // 下拉刷新圖片
    Image(this.customRefreshLoadClass.imageSrc)
      ...
    // 下拉刷新文字
    Text(this.customRefreshLoadClass.textValue)
      ...
  }
  ...
}

將下拉刷新的布局添加到NewsList.ets文件中新聞列表布局ListLayout里面,監(jiān)聽ListLayout組件的onTouch事件實現(xiàn)下拉刷新。

// NewsList.ets
build() {
  Column() {
    if (this.newsModel.pageState === PageState.Success) {
      this.ListLayout()
    }
    ...
  }
  ...
  .onTouch((event: TouchEvent | undefined) = > {
    if (event) {
      if (this.newsModel.pageState === PageState.Success) {
        listTouchEvent(this.newsModel, event);
      }
    }
  })
}
...
@Builder ListLayout() {
  List() {
    ListItem() {
      RefreshLayout({
        refreshLayoutClass: new CustomRefreshLoadLayoutClass(this.newsModel.isVisiblePullDown, this.newsModel.pullDownRefreshImage,
          this.newsModel.pullDownRefreshText, this.newsModel.pullDownRefreshHeight)
      })
      ...
    }
  }
  ...
}
  1. 在onTouch事件中,listTouchEvent方法判斷觸摸事件是否滿足下拉條件。如下listTouchEvent所示:
  2. 在touchMovePullRefresh方法中,我們將對下拉的偏移量與下拉刷新布局的高度進行對比,如果大于布局高度并且在新聞列表的頂部,則表示達到刷新條件。如下touchMovePullRefresh所示:
  3. 在pullRefreshState方法中我們會對下拉刷新布局中的狀態(tài)圖片和描述進行改變,如下pullRefreshState所示:
  4. 當(dāng)手指松開,才執(zhí)行刷新操作。
// PullDownRefresh.ets
export function listTouchEvent(newsModel: NewsModel, event: TouchEvent) {
  switch (event.type) {
    ...
    case TouchType.Move:
      if ((newsModel.isRefreshing === true) || (newsModel.isLoading === true)) {
        return;
      }
      let isDownPull = event.touches[0].y - newsModel.lastMoveY > 0;
      if (((isDownPull === true) || (newsModel.isPullRefreshOperation === true)) && (newsModel.isCanLoadMore === false))
      {
        // 手指移動,處理下拉刷新
        touchMovePullRefresh(newsModel, event);
      }
      ...
      break;
  }
}

export function touchMovePullRefresh(newsModel: NewsModel, event: TouchEvent) {
  if (newsModel.startIndex === 0) {
    newsModel.isPullRefreshOperation = true;
    let height = vp2px(newsModel.pullDownRefreshHeight);
    newsModel.offsetY = event.touches[0].y - newsModel.downY;
    // 滑動偏移量大于下拉刷新布局高度,滿足刷新條件。
    if (newsModel.offsetY >= height) {
      pullRefreshState(newsModel, RefreshState.Release);
      newsModel.offsetY = height + newsModel.offsetY * Const.Y_OFF_SET_COEFFICIENT;
    } else {
      pullRefreshState(newsModel, RefreshState.DropDown);
    }
    if (newsModel.offsetY < 0) {
      newsModel.offsetY = 0;
      newsModel.isPullRefreshOperation = false;
    }
  }
}

export function pullRefreshState(newsModel: NewsModel, state: number) {
  switch (state) {
    ...
    case RefreshState.Release:
      newsModel.pullDownRefreshText = $r('app.string.release_refresh_text');
      newsModel.pullDownRefreshImage = $r('app.media.ic_pull_up_refresh');
      newsModel.isCanRefresh = true;
      newsModel.isRefreshing = false;
      break;
    case RefreshState.Refreshing:
      newsModel.offsetY = vp2px(newsModel.pullDownRefreshHeight);
      newsModel.pullDownRefreshText = $r('app.string.refreshing_text');
      newsModel.pullDownRefreshImage = $r('app.media.ic_pull_up_load');
      newsModel.isCanRefresh = true;
      newsModel.isRefreshing = true;
      break;
    case RefreshState.Success:
      newsModel.pullDownRefreshText = $r('app.string.refresh_success_text');
      newsModel.pullDownRefreshImage = $r('app.media.ic_succeed_refresh');
      newsModel.isCanRefresh = true;
      newsModel.isRefreshing = true;
      break;
    ...
    default:
      break;
  }
}

上拉加載也是通過touch事件來實現(xiàn)的。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 鴻蒙
    +關(guān)注

    關(guān)注

    56

    文章

    2267

    瀏覽量

    42492
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1946

    瀏覽量

    29740
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3548

    瀏覽量

    15743
收藏 人收藏

    評論

    相關(guān)推薦

    TL3588-NPU開發(fā)案

    TL3588-NPU開發(fā)案
    的頭像 發(fā)表于 01-24 15:22 ?496次閱讀
    TL3588-NPU<b class='flag-5'>開發(fā)案</b>例

    TL3588-視頻開發(fā)案

    TL3588-視頻開發(fā)案
    的頭像 發(fā)表于 01-24 16:29 ?569次閱讀
    TL3588-視頻<b class='flag-5'>開發(fā)案</b>例

    TLT507-Linux-RT應(yīng)用開發(fā)案

    TLT507-Linux-RT應(yīng)用開發(fā)案
    的頭像 發(fā)表于 01-26 09:46 ?579次閱讀
    TLT507-Linux-RT應(yīng)用<b class='flag-5'>開發(fā)案</b>例

    TLT507-視頻開發(fā)案

    TLT507-視頻開發(fā)案
    的頭像 發(fā)表于 01-26 10:50 ?905次閱讀
    TLT507-視頻<b class='flag-5'>開發(fā)案</b>例

    3568F-視頻開發(fā)案

    3568F-視頻開發(fā)案
    的頭像 發(fā)表于 04-12 13:51 ?750次閱讀
    3568F-視頻<b class='flag-5'>開發(fā)案</b>例

    HarmonyOS開發(fā)案例:【W(wǎng)eb組件實現(xiàn)抽獎】

    基于ArkTS的聲明式開發(fā)范式的樣例,主要介紹了Web組件如何加載本地和云端H5小程序。
    的頭像 發(fā)表于 05-09 18:31 ?1205次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【W(wǎng)eb組件實現(xiàn)抽獎】

    HarmonyOS IoT 硬件開發(fā)案例分享

    ``許思維老師HiSpark Wi-Fi IoT 開發(fā)案例分享:案例一:AHT20溫濕度傳感器開發(fā)、調(diào)試;案例二:oled屏驅(qū)動庫移植,調(diào)試;案例三:用OLED屏播放視頻,Wi-Fi 和 TCP/IP 綜合應(yīng)用。 ``
    發(fā)表于 10-27 17:30

    【潤和直播課預(yù)告@華為開發(fā)者學(xué)院】HarmonyOS設(shè)備開發(fā)基礎(chǔ)課程|HiSpark WiFi-IoT 智能小車套件開發(fā)案

    `【潤和直播課預(yù)告@華為開發(fā)者學(xué)院】HarmonyOS設(shè)備開發(fā)基礎(chǔ)課程|HiSparkWiFi-IoT 智能小車套件開發(fā)案例,3月18日(周四) 19:00-21:00,讓你的
    發(fā)表于 03-16 15:01

    Linux應(yīng)用開發(fā)手冊之Python開發(fā)案

    本文檔涉及的開發(fā)案例位于產(chǎn)品資料“4-軟件資料\Demo\”路徑下的base-demos和python-demos目錄。base-demos目錄存放Linux常用開發(fā)案例,案例bin目錄存放
    發(fā)表于 05-11 10:21

    許思維老師HarmonyOS IoT硬件開發(fā)案例分享

    許思維老師HiSpark Wi-Fi IoT 開發(fā)案例分享:案例一:AHT20溫濕度傳感器開發(fā)、調(diào)試;案例二:oled屏驅(qū)動庫移植,調(diào)試;案例三:用OLED屏播放視頻,Wi-Fi 和 TCP/IP 綜合應(yīng)用。
    發(fā)表于 10-29 10:39 ?39次下載
    許思維老師<b class='flag-5'>HarmonyOS</b> IoT硬件<b class='flag-5'>開發(fā)案</b>例分享

    華為開發(fā)HarmonyOS零基礎(chǔ)入門:UI組件設(shè)計開發(fā)實踐

    華為開發(fā)HarmonyOS零基礎(chǔ)入門:UI組件設(shè)計開發(fā)實踐之圖庫應(yīng)用介紹,應(yīng)用數(shù)據(jù)加載顯示模型圖片加載
    的頭像 發(fā)表于 10-23 10:58 ?1584次閱讀
    華為<b class='flag-5'>開發(fā)</b>者<b class='flag-5'>HarmonyOS</b>零基礎(chǔ)入門:UI組件設(shè)計<b class='flag-5'>開發(fā)</b>實踐

    華為開發(fā)HarmonyOS零基礎(chǔ)入門:應(yīng)用數(shù)據(jù)加載顯示模型

    華為開發(fā)HarmonyOS零基礎(chǔ)入門:應(yīng)用數(shù)據(jù)加載顯示模型,對模型進行優(yōu)化與解碼進行競爭,預(yù)加載提升體驗。
    的頭像 發(fā)表于 10-23 11:05 ?1198次閱讀
    華為<b class='flag-5'>開發(fā)</b>者<b class='flag-5'>HarmonyOS</b>零基礎(chǔ)入門:應(yīng)用<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>加載</b>顯示模型

    零基礎(chǔ)入門HarmonyOS-應(yīng)用數(shù)據(jù)按需加載顯示模型

    HDC 2021華為開發(fā)者大會分論壇零基礎(chǔ)入門HarmonyOS-應(yīng)用數(shù)據(jù)按需加載顯示模型
    的頭像 發(fā)表于 10-23 13:21 ?1336次閱讀
    零基礎(chǔ)入門<b class='flag-5'>HarmonyOS</b>-應(yīng)用<b class='flag-5'>數(shù)據(jù)</b>按需<b class='flag-5'>加載</b>顯示模型

    華為開發(fā)者分論壇HarmonyOS學(xué)生公開課-OpenHarmony Codelabs開發(fā)案

    2021華為開發(fā)者分論壇HarmonyOS學(xué)生公開課-OpenHarmony Codelabs開發(fā)案
    的頭像 發(fā)表于 10-24 11:25 ?1811次閱讀
    華為<b class='flag-5'>開發(fā)</b>者分論壇<b class='flag-5'>HarmonyOS</b>學(xué)生公開課-OpenHarmony Codelabs<b class='flag-5'>開發(fā)案</b>例

    RK3568---NPU開發(fā)案

    RK3568---NPU開發(fā)案
    的頭像 發(fā)表于 01-19 13:50 ?672次閱讀
    RK3568---NPU<b class='flag-5'>開發(fā)案</b>例