راهنمای عملی برای تهیه یک برنامه خبری بر اساس Harmonyos Next

1. بررسی اجمالی پروژه و تنظیم محیط
با انتشار Harmonyos Next ، توسعه دهندگان می توانند از قابلیت های توزیع شده پیشرفته خود و پیشرفت ابزار بهبود یافته برای ایجاد تجربیات کاربردی بین دستگاه استفاده کنند. این آموزش شما را از طریق تهیه یک برنامه خبری ، پوشش ماژول های اصلی مانند لیست اخبار ، مشاهده دقیق و عملکرد نشانک ، راهنمایی می کند.
ابتدا اطمینان حاصل کنید که محیط توسعه شما آماده است:
- آخرین نسخه استودیوی Deveco (توصیه شده 4.1 یا بالاتر) را نصب کنید.
- هنگام ایجاد یک پروژه ، “برنامه” → “توانایی خالی” را انتخاب کنید.
- پیکربندی خدمات اتصال AppGallery (جزئیات بعداً پوشش داده می شود).
ساختار پروژه در درجه اول از مؤلفه های اصلی زیر تشکیل شده است:
-
pages
: حاوی کد صفحه است. -
resources
: پرونده های منابع برنامه را ذخیره می کند. -
entryability
: نقطه ورود برنامه. -
model
: لایه مدل داده.
2. ادغام سرویس AppGallery Connect
AppGallery Connect خدمات پشتیبان قوی را برای برنامه های Harmonyos ارائه می دهد. ابتدا تنظیمات زیر را تکمیل کنید:
- یک پروژه در کنسول AppGallery Connect ایجاد کنید.
- سرویس احراز هویت (سرویس AUTH) و پایگاه داده ابری (Cloud DB) را فعال کنید.
- پرونده پیکربندی را بارگیری کنید
agconnect-services.json
و آن را در پروژه قرار دهیدentry
دایرکتوری
وابستگی ها را اضافه کنید build.gradle
:
// entry/build.gradle
dependencies {
implementation 'io.agconnect.agconnect-core-harmony:agconnect-core:1.6.0.300'
implementation 'io.agconnect.agconnect-auth-harmony:agconnect-auth:1.6.0.300'
implementation 'io.agconnect.agconnect-clouddb-harmony:agconnect-clouddb:1.6.0.300'
}
کد اولیه سازی:
// entryability/EntryAbility.ts
import agconnect from '@hw-agconnect/api-ohos';
import '@hw-agconnect/core-ohos';
import '@hw-agconnect/auth-ohos';
import '@hw-agconnect/clouddb-ohos';
onCreate() {
agconnect.instance().init(this.context);
// Initialize Cloud Database
this.initCloudDB();
}
async initCloudDB() {
try {
const cloudDBZoneConfig = new cloud.CloudDBZoneConfig('NewsDB');
this.cloudDBZone = await cloud.CloudDBZone.open(cloudDBZoneConfig);
} catch (err) {
console.error('CloudDB init failed: ' + JSON.stringify(err));
}
}
3. طراحی مدل داده های خبری
نوع شیء اخبار را برای ذخیره سازی محلی و ابری تعریف کنید. ایجاد کردن News.ts
در model
دایرکتوری:
// model/News.ts
import { cloud } from '@hw-agconnect/clouddb-ohos';
export class News {
// Use decorators to define Cloud DB fields
@cloud.Field()
id: string = '';
@cloud.Field()
title: string = '';
@cloud.Field()
content: string = '';
@cloud.Field()
author: string = '';
@cloud.Field()
publishTime: number = 0;
@cloud.Field()
category: string = '';
@cloud.Field()
imageUrl: string = '';
@cloud.Field()
isFavorite: boolean = false;
constructor() {
// Set object type name (must match the Cloud DB object type)
cloud.ObjectType.register(this, 'News');
}
}
پس از ایجاد نوع شیء مربوطه در کنسول Cloud DB ، می توانید عملیات CRUD را روی داده ها انجام دهید.
4. توسعه صفحه لیست اخبار
لیست اخبار صفحه اصلی برنامه است. ما از List
مؤلفه برای نمایش داده های خبری با عملکرد پیمایش به Re-Refresh و Infinite.
// pages/NewsListPage.ets
import { News } from '../model/News';
import { cloud } from '@hw-agconnect/clouddb-ohos';
@Entry
@Component
struct NewsListPage {
@State newsList: Array<News> = [];
@State isLoading: boolean = false;
@State isRefreshing: boolean = false;
private pageSize: number = 10;
private pageIndex: number = 0;
build() {
Column() {
// Header
Row() {
Text('Top News')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Blank()
Image($r('app.media.ic_search'))
.width(30)
.height(30)
.margin({ right: 15 })
}
.width('100%')
.padding(15)
.backgroundColor('#FF4D4F')
// News list
List({ space: 10 }) {
ForEach(this.newsList, (item: News) => {
ListItem() {
NewsItem({ news: item })
}
}, (item: News) => item.id)
}
.width('100%')
.layoutWeight(1)
.onScrollIndex((start: number) => {
// Load more when scrolling to the bottom
if (start >= this.newsList.length - 3 && !this.isLoading) {
this.loadMoreNews();
}
})
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
.onAppear(() => {
this.refreshNews();
})
}
// Pull-to-refresh
async refreshNews() {
this.isRefreshing = true;
this.pageIndex = 0;
try {
const query = cloud.CloudDBZoneQuery.where(News).orderByDesc('publishTime').limit(this.pageSize);
const result = await this.cloudDBZone.executeQuery(query, News);
this.newsList = result;
} catch (err) {
console.error('Refresh news failed: ' + JSON.stringify(err));
}
this.isRefreshing = false;
}
// Load more
async loadMoreNews() {
this.isLoading = true;
this.pageIndex++;
try {
const query = cloud.CloudDBZoneQuery.where(News)
.orderByDesc('publishTime')
.limit(this.pageSize)
.offset(this.pageIndex * this.pageSize);
const result = await this.cloudDBZone.executeQuery(query, News);
this.newsList = this.newsList.concat(result);
} catch (err) {
console.error('Load more news failed: ' + JSON.stringify(err));
}
this.isLoading = false;
}
}
// News item component
@Component
struct NewsItem {
@Prop news: News;
build() {
Column() {
// News image
Image(this.news.imageUrl)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(8)
// Title and summary
Column() {
Text(this.news.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Text(this.news.content.substring(0, 50) + '...')
.fontSize(14)
.fontColor('#666')
}
.padding(10)
// Footer info
Row() {
Text(this.news.author)
.fontSize(12)
.fontColor('#999')
Blank()
Text(this.formatTime(this.news.publishTime))
.fontSize(12)
.fontColor('#999')
Image(this.news.isFavorite ? $r('app.media.ic_favorite') : $r('app.media.ic_favorite_border'))
.width(20)
.height(20)
.margin({ left: 10 })
.onClick(() => {
this.toggleFavorite();
})
}
.width('100%')
.padding({ left: 10, right: 10, bottom: 10 })
}
.width('95%')
.margin({ top: 5, bottom: 5 })
.backgroundColor('#FFF')
.borderRadius(8)
.shadow({ radius: 4, color: '#10000000', offsetX: 0, offsetY: 2 })
.onClick(() => {
router.pushUrl({ url: 'pages/NewsDetailPage', params: { newsId: this.news.id } });
})
}
// Format timestamp
private formatTime(timestamp: number): string {
const date = new Date(timestamp);
return `${date.getMonth() + 1}/${date.getDate()}`;
}
// Toggle bookmark
private async toggleFavorite() {
try {
this.news.isFavorite = !this.news.isFavorite;
await this.cloudDBZone.executeUpsert([this.news]);
} catch (err) {
console.error('Toggle favorite failed: ' + JSON.stringify(err));
}
}
}
5. اجرای صفحه جزئیات
صفحه جزئیات اخبار مطالب کامل را نشان می دهد و از نشانه گذاری پشتیبانی می کند.
// pages/NewsDetailPage.ets
import { News } from '../model/News';
@Entry
@Component
struct NewsDetailPage {
@State news: News = new News();
private newsId: string = '';
onPageShow() {
this.newsId = router.getParams()?.newsId;
this.loadNewsDetail();
}
build() {
Column() {
// Back button and title
Row() {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.onClick(() => {
router.back();
})
Text('News Detail')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ left: 15 })
Blank()
Image(this.news.isFavorite ? $r('app.media.ic_favorite') : $r('app.media.ic_favorite_border'))
.width(24)
.height(24)
.onClick(() => {
this.toggleFavorite();
})
}
.width('100%')
.padding(15)
.backgroundColor('#FF4D4F')
// Content area
Scroll() {
Column() {
// Title and author info
Text(this.news.title)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Row() {
Text(`Author: ${this.news.author}`)
.fontSize(14)
.fontColor('#666')
Text(`Published: ${this.formatTime(this.news.publishTime)}`)
.fontSize(14)
.fontColor('#666')
.margin({ left: 15 })
}
.margin({ bottom: 15 })
// News image
Image(this.news.imageUrl)
.width('100%')
.height(250)
.objectFit(ImageFit.Cover)
.margin({ bottom: 20 })
// News content
Text(this.news.content)
.fontSize(16)
.lineHeight(26)
}
.padding(20)
}
.scrollBar(BarState.Off)
.layoutWeight(1)
}
.width('100%')
.height('100%')
}
// Load news details
private async loadNewsDetail() {
try {
const query = cloud.CloudDBZoneQuery.where(News).equalTo('id', this.newsId);
const result = await this.cloudDBZone.executeQuery(query, News);
if (result && result.length > 0) {
this.news = result[0];
}
} catch (err) {
console.error('Load news detail failed: ' + JSON.stringify(err));
}
}
// Toggle bookmark
private async toggleFavorite() {
try {
this.news.isFavorite = !this.news.isFavorite;
await this.cloudDBZone.executeUpsert([this.news]);
} catch (err) {
console.error('Toggle favorite failed: ' + JSON.stringify(err));
}
}
// Format timestamp
private formatTime(timestamp: number): string {
const date = new Date(timestamp);
return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
}
}
6. احراز هویت و نشانک کاربر
برای فعال کردن نشانه گذاری ، تأیید هویت کاربر با استفاده از سرویس AppGallery Connect Auth.
// utils/AuthUtil.ts
import { agconnect } from '@hw-agconnect/api-ohos';
import '@hw-agconnect/auth-ohos';
export class AuthUtil {
// Anonymous login
static async anonymousLogin(): Promise<boolean> {
try {
const user = await agconnect.auth().signInAnonymously();
return user != null;
} catch (err) {
console.error('Anonymous login failed: ' + JSON.stringify(err));
return false;
}
}
// Get current user ID
static getCurrentUserId(): string | null {
const user = agconnect.auth().currentUser;
return user ? user.uid : null;
}
// Logout
static async logout(): Promise<void> {
try {
await agconnect.auth().signOut();
} catch (err) {
console.error('Logout failed: ' + JSON.stringify(err));
}
}
}
اصلاح News
مدل شامل انجمن کاربر:
// model/News.ts
export class News {
// ...existing fields
@cloud.Field()
userId: string = ''; // Associated user ID
// ...other code
}
برای بررسی وضعیت ورود به سیستم ، نشانک را به روز کنید:
// In NewsItem component, modify toggleFavorite
private async toggleFavorite() {
if (!AuthUtil.getCurrentUserId()) {
const isLogin = await AuthUtil.anonymousLogin();
if (!isLogin) {
prompt.showToast({ message: 'Please log in first' });
return;
}
}
try {
this.news.isFavorite = !this.news.isFavorite;
this.news.userId = AuthUtil.getCurrentUserId() || '';
await this.cloudDBZone.executeUpsert([this.news]);
} catch (err) {
console.error('Toggle favorite failed: ' + JSON.stringify(err));
}
}
7. بسته بندی برنامه و انتشار
پس از توسعه ، برنامه را به AppGallery بسته و منتشر کنید:
- در استودیوی Deveco ، Build را انتخاب کنید → تولید کلید و CSR برای ایجاد گواهی امضای.
- پیکربندی اطلاعات امضا در
build-profile.json5
بشر - Build → Build HAP (ها)/برنامه (ها) را انتخاب کنید → برنامه ساخت برای تولید بسته نسخه.
- وارد کنسول AppGallery Connect شوید ، به “برنامه های من” بروید و یک برنامه جدید ایجاد کنید.
- پرونده برنامه تولید شده را بارگذاری کنید ، جزئیات برنامه را پر کنید و برای بررسی ارسال کنید.
8. پیشنهادات پیشرفته ویژگی
پس از اتمام اصول اولیه ، اضافه کردن را در نظر بگیرید:
- فیلتر دسته بندی: برای فیلتر کردن اخبار ، زبانه های دسته را اضافه کنید.
- نظرات: عملکرد نظر را با استفاده از Cloud DB پیاده سازی کنید.
- خواندن آفلاین: برای دسترسی آفلاین از فضای محلی استفاده کنید.
- اعلان ها را فشار دهید: ادغام کیت فشار AppGallery Connect برای شکستن هشدارهای خبری.
- همگام سازی چند دستگاهی: اهرم هارمونیوس قابلیت های توزیع شده برای تعویض دستگاه یکپارچه.
این آموزش یک راهنمای کامل برای تهیه یک برنامه خبری مبتنی بر Harmonyos ، از راه اندازی تا اجرای ارائه می دهد. از آن به عنوان پایه ای برای ساختن برنامه های پیشرفته تر استفاده کنید.