Mobile Development 44 min read

Building a Cross-Device Health Diet App with HarmonyOS 6: Declarative UI, State Management & Performance Optimization

A developer shares technical insights from building 'Light Meal,' a cross-device health diet app on HarmonyOS 6, covering declarative UI with ArkUI, @ComponentV2 state management, performance optimizations cutting startup time 40%, service cards boosting daily active users 20%, and fine-grained permissions raising consent rates to 85%.

51CTO HarmonyOS Developer Community
51CTO HarmonyOS Developer Community
51CTO HarmonyOS Developer Community
Building a Cross-Device Health Diet App with HarmonyOS 6: Declarative UI, State Management & Performance Optimization

Introduction: From Idea to Implementation

The author noticed many friends attempting intermittent fasting and healthy eating but lacking scientific guidance tools. Existing apps were either single-function, poor UX, paywalled before use, or ad-heavy. Research showed users needed personalized diet plans, scientific fasting guidance, and intuitive data feedback. The author chose HarmonyOS 6 for its distributed device capability, declarative UI (ArkUI), security/privacy model, performance improvements, and ecosystem potential.

Technology Selection: Why HarmonyOS 6

Cross-device adaptation : Health data sync across phone, tablet, watch — HarmonyOS distributed capability fits perfectly.

Declarative UI : Familiar from Compose/Flutter; ArkUI enabled fast onboarding.

Security & privacy : Fine-grained permission management for sensitive health data.

Performance optimization : Rendering and resource management upgrades critical for smooth health app experience.

Ecosystem outlook : Huawei's strategic OS with long-term potential.

Core Sharing: How HarmonyOS 6 Features Empower Light Meal

(1) Declarative UI Simplifies Complex Layouts

Challenge : Health dashboard needed many data metrics; traditional layouts produced verbose, nested code (300+ lines, 5 nesting levels).

Solution : ArkUI flex and grid layouts.

Result : Code reduced by 50%, layout clearer and maintainable; development time from 1 day to half day.

(2) Improved State Management Boosts Performance

Challenge : Complex app state, difficult inter-component communication, frequent state inconsistency.

Solution : @ComponentV2 decorator for state synchronization.

Result : State update response speed improved 30%, smoother UX, no more inconsistency bugs.

(3) Safeguarding User Data Security

Challenge : Sensitive health data (weight, diet logs, fasting plans) requires privacy protection with good permission UX.

Solution : HarmonyOS 6 fine-grained permission management, request-on-demand.

Result : Permission grant rate rose from 65% to 85%, user trust increased.

App Overview

Positioning & Core Features

Healthy Fasting Recommendations : Personalized fasting plans based on body data, habits, goals.

Recording & Analysis : Quick logging of weight, water, exercise, sleep, bowel movements with scientific suggestions.

Light Fasting Knowledge Base : Tips for fasting, eating, and guides.

Target Users

Urban professionals 25–40, health-conscious but time-poor.

Weight management seekers preferring science over starvation.

Users interested in fasting wanting professional guidance.

Technical Architecture

UI Layer : ArkUI declarative framework, UX-focused.

Business Logic Layer : Core rules — fasting plan generation, nutrition analysis.

Data Access Layer : Local storage + cloud sync.

Service Layer : Encapsulated services — health analysis, push notifications.

Distributed capability enables consistent experience: plan on phone, detailed analysis on tablet, fasting reminders on watch.

Development Challenges & Solutions

1. Data Security

Health apps handle sensitive data. A news story about a health app leak reinforced the priority. Implemented validation, pre-import backup, just-in-time permission requests, transparent progress/result feedback.

2. Performance Optimization

App grew bloated; users reported slow startup, janky transitions, especially loading large history datasets.

Code: Lazy Loading Component

@ComponentV2
struct LazyLoadComponent<T> {
  @Prop item: T;
  @Prop index: number;
  @Prop renderItem: (item: T, index: number) => void;
  @Local isVisible: boolean = false;

  build() {
    View() {
      if (this.isVisible) {
        this.renderItem(this.item, this.index);
      } else {
        Text('Loading...')
          .fontSize(14)
          .fontColor($r('app.color.text_secondary'))
          .padding(20)
      }
    }
    .visibility(this.isVisible ? Visibility.Visible : Visibility.Hidden)
    .onAppear(() => { this.isVisible = true; })
    .onDisappear(() => { this.isVisible = false; })
  }
}

Code: Data Cache Service with TTL

export class DataCacheService {
  private static instance: DataCacheService;
  private cache: Map<string, { data: any; timestamp: number; ttl: number }> = new Map();
  private readonly DEFAULT_TTL: number = 5 * 60 * 1000;

  static getInstance(): DataCacheService { ... }
  get(key: string): any | null { ... }
  set(key: string, data: any, ttl: number = this.DEFAULT_TTL): void { ... }
}

Code: Paginated Health Record Loading

export class HealthRecordService {
  private dataCacheService: DataCacheService = DataCacheService.getInstance();

  async getHealthRecords(page: number = 1, pageSize: number = 20): Promise<HealthRecord[]> {
    const cacheKey = `health_records_${page}_${pageSize}`;
    const cachedData = this.dataCacheService.get(cacheKey);
    if (cachedData) return cachedData;

    const records = await this.healthRecordDao.queryRecords(page, pageSize);
    this.dataCacheService.set(cacheKey, records);
    return records;
  }
}

List Performance Optimization

// Before: new component each scroll
List() {
  ForEach(this.records, (record) => {
    HealthRecordCard({ record });
  });
}

// After: stableId + reuse
List() {
  ForEach(
    this.records,
    (record) => { HealthRecordCard({ record }); },
    (record) => record.id
  );
}
.size(100, 100)
.edgeEffect(EdgeEffect.None)
.shadow(false)

3. Complex Layout Implementation

Home page TimerPage combines Stack, Grid, Column/Row flex layouts. Key components: buildFastingWidget(): Stack of circles (background, gradient progress, white overlay, Canvas progress ring, ripple effect) with centered Column of countdown, status, progress text. Gesture handling: double-tap, long-press, pan. buildWeightManagementModule(): Row/Column flex layout with ForEach for dynamic weekly bar chart; animated bars with gradient, scale, opacity, shadow, staggered delay. buildHealthManagementModule(): Composed of independent item components (Water, Exercise, EarlyRise, EarlySleep, Toilet). buildQdsCard(): Nested Column/Row with three tip cards (fasting principle, refeeding advice, precautions) each with icon, title, content, distinct background color.

Custom Circular Progress Layout

@ComponentV2
struct CircularProgressLayout {
  @Prop value: number;
  @Prop maxValue: number = 100;
  @Prop color: ResourceColor = $r('app.color.primary');
  @Prop title: string;
  @Prop icon: string;

  build() {
    Stack() {
      Circle().width(120).height(120).fill(Color.Transparent).stroke({ width: 12, color: $r('app.color.divider') })
      Circle()
        .width(120).height(120).fill(Color.Transparent)
        .stroke({ width: 12, color: this.color,
          strokeDashArray: [2 * Math.PI * 54 * (this.value / this.maxValue), 2 * Math.PI * 54] })
        .rotation(-90)
      Column() {
        Text(this.icon).fontSize(32)
        Text(this.title).fontSize(14).fontColor($r('app.color.text_secondary'))
        Text(`${this.value}/${this.maxValue}`).fontSize(24).fontWeight(FontWeight.Bold).fontColor(this.color)
      }
    }
    .width(150).height(150).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
  }
}

4. State Management Chaos

Many states (user data, health metrics, fasting status). Initial simple management led to sync issues as components grew. Event bus became unwieldy; event ordering bugs caused missed updates.

Solution: @ComponentV2 + Local Decorator

@Entry
@ComponentV2
struct NewDashboardPage {
  private userProfileService: UserProfileService = UserProfileService.getInstance();
  private healthDataService: HealthDataService = HealthDataService.getInstance();

  @Local isLoading: boolean = true;
  @Local selectedTimeRange: TimeRange = TimeRange.WEEK;
  @Local healthScore: number = 0;
  @Local fastingProgress: number = 0;
  @Local waterIntake: number = 0;
  @Local exerciseMinutes: number = 0;

  aboutToAppear(): void { this.loadHealthData(); }

  private async loadHealthData(): Promise<void> {
    this.isLoading = true;
    try {
      const [healthScore, fastingData, waterData, exerciseData] = await Promise.all([
        this.healthDataService.getHealthScore(this.selectedTimeRange),
        this.healthDataService.getFastingProgress(),
        this.healthDataService.getWaterIntake(),
        this.healthDataService.getExerciseMinutes()
      ]);
      this.healthScore = healthScore;
      this.fastingProgress = fastingData.progress;
      this.waterIntake = waterData.total;
      this.exerciseMinutes = exerciseData.total;
    } catch (error) {
      hilog.error(0x0001, 'DashboardPage', `Failed to load health data: ${JSON.stringify(error)}`);
    } finally { this.isLoading = false; }
  }

  private onMetricChange(metric: HealthMetricType): void { this.selectedMetric = metric; }
  build() { ... }
}

Global State Service (Singleton + Listener Pattern)

export class AppStateService {
  private static instance: AppStateService;
  private userProfile: UserProfile | null = null;
  private isLoggedIn: boolean = false;
  private themeMode: ThemeMode = ThemeMode.LIGHT;
  private language: string = 'zh-CN';
  private listeners: Map<string, Array<() => void>> = new Map();

  static getInstance(): AppStateService { ... }
  updateUserProfile(profile: UserProfile): void { ... }
  updateThemeMode(theme: ThemeMode): void { ... }
  registerListener(key: string, callback: () => void): void { ... }
  unregisterListener(key: string, callback: () => void): void { ... }
  private notifyListeners(key: string): void { ... }
}

Event Bus for Cross-Component Communication

export class EventBus {
  private static instance: EventBus;
  private eventListeners: Map<string, Array<(data?: any) => void>> = new Map();

  static getInstance(): EventBus { ... }
  subscribe(eventName: string, callback: (data?: any) => void): void { ... }
  publish(eventName: string, data?: any): void { ... }
  unsubscribe(eventName: string, callback: (data?: any) => void): void { ... }
  unsubscribeAll(eventName?: string): void { ... }
}

export enum AppEvents {
  USER_LOGGED_IN = 'user_logged_in',
  HEALTH_DATA_UPDATED = 'health_data_updated',
  THEME_CHANGED = 'theme_changed',
  LANGUAGE_CHANGED = 'language_changed'
}

HarmonyOS 6 New Features in Practice

1. Declarative UI Enhancements: ArkUI New Components & APIs

Problem : Dashboard layout 300+ lines, 5 nesting levels. Feature : Enhanced flex/grid layouts, responsive design support. Code : Refactored health metrics overview using Row with SpaceBetween and reusable buildMetricItem builder. Result : Code halved, auto-adapts to device sizes, layout dev time half day vs full day.

2. Advanced State Management: @ComponentV2

Problem : State sync across dashboard, fasting log, stats pages; event bus caused ordering bugs. Feature : Optimized @State/@Local performance, efficient UI updates. Code : DashboardPage using @Local for UI state, services for data, Promise.all for parallel loading, batch state updates. Result : Zero inconsistency bugs, 30% faster state response, cleaner code.

3. Service Cards: Quick Access to Core Info

Problem : Users frequently open app for fasting progress, water intake. Feature : Service cards show core data on home screen without opening app. Code :

@Entry(storageLocal) @Component export default struct HealthWidget

using @LocalStorageProp + @Watch for formTime, fastingProgress, todayWaterIntake, etc. postCardAction for call/router actions. Progress bar, color-coded scores. Result : Users with cards show 20% higher daily active rate. DevEco CodeGenie now accelerates card creation.

4. Background Task Management: Reliable Background Execution

Problem : Reminders (fasting start/end, water) failed when app backgrounded. Feature : Long-running tasks (DATA_TRANSFER mode) and short transient tasks with capability detection and fallback to local notifications. Code : BackgroundTaskService with requestLongRunningTask() (WantAgent, startBackgroundRunning) and requestShortTask() (requestSuspendDelay, canIUse check). Fallback logic on failure. Result : Background reminder delivery rate from 70% to 95%.

5. Security & Privacy: Fine-Grained Permission Management

Problem : Data leak fears; poor permission UX (bulk requests, block-if-denied). Feature : Granular permissions, request-on-demand, transparent rationale, secure photo/camera access (unused here). Code : DataImportExportPage with validation, pre-import backup, just-in-time file access permission, progress/result toasts. Result : Permission grant rate 65% → 85%; users praise reasonable requests.

Results Showcase

Development Efficiency

Declarative UI: Complex layout dev time 1 day → 0.5 day (50% faster).

Optimized state management: State code -30%, debugging time drastically cut.

Performance Metrics

App startup time : 2.5s → 1.5s (40% improvement)

Page switch speed : 1.2s → 0.8s (33% improvement)

Data load time : 1.8s → 1.0s (44% improvement)

Memory usage : 180MB → 120MB (33% improvement)

User Feedback

92% satisfaction, 15% avg DAU growth, 4.8/5.0 rating.

Market Performance

Top 10 in health category within 3 months.

100k+ cumulative downloads.

Huawei AppGallery featured recommendation.

Technical Reflections

1. HarmonyOS 6 Development Experience Transformation

10+ years mobile dev experience; HarmonyOS 6 drastically simplified layout, adaptation, state management. First ArkUI dashboard: 300+ lines → 100+ lines, clearer structure, easier maintenance, left work early.

2. Declarative UI Advantages

Concise code (50% reduction).

Intuitive layout (WYSIWYG mental model).

Auto-adaptation (one codebase, multi-device).

Maintainable structure.

3. Cross-Device Development: From Single to Multi-Device Collaboration

Distributed capability shifts mindset: app as a service across phone, tablet, watch. Enables phone for planning, watch for reminders, tablet for detailed analysis.

4. Future HarmonyOS Ecosystem Expectations

More third-party libraries/tools.

Better docs/tutorials to lower entry barrier.

More developers joining ecosystem.

Larger user base on HarmonyOS devices.

Future Roadmap

1. Feature Iterations

AI-powered recommendations based on logs, fasting data, goals.

User community for sharing experiences.

More health metrics (sleep quality, exercise intensity).

Smart hardware integration (scales, water cups) for auto-sync.

2. HarmonyOS New Feature Adoption

Track HarmonyOS 7 AI capabilities for smarter health advice.

3. Ecosystem Collaboration

Partner with professional health institutions.

Collaborate with smart hardware vendors.

Contribute to HarmonyOS ecosystem, share dev experience.

Conclusion: Technology Empowering Healthy Living

Light Meal merges HarmonyOS 6 tech with health philosophy — not just a tech product but a healthy lifestyle companion. User feedback (weight loss, better sleep, regular fasting) validates the mission. Thanks to Huawei for the platform, AGC reviewers, and ecosystem support. Committed to continuous innovation for better health services.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

mobile developmentperformance-optimizationState ManagementArkUIDeclarative UIBackground TasksHealth AppHarmonyOS 6cross-device developmentService Cards
51CTO HarmonyOS Developer Community
Written by

51CTO HarmonyOS Developer Community

The HarmonyOS Developer Community is a learning-oriented community for developers to learn, communicate, ask questions, and share.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.