#在这里插入图片描述

前言

状态管理是应用开发中的核心问题之一,它决定了数据如何在组件间流动、如何响应用户操作、如何保持界面与数据的同步。在笔记应用中,笔记列表、编辑状态、用户设置等数据都需要通过状态管理来维护。选择合适的状态管理方案可以让代码更加清晰、可维护,同时提升应用性能。本文将详细介绍Flutter和OpenHarmony平台上的状态管理方案。

Flutter setState基础

setState是Flutter中最基本的状态管理方式。

class NoteEditorPage extends StatefulWidget {
  
  _NoteEditorPageState createState() => _NoteEditorPageState();
}

class _NoteEditorPageState extends State<NoteEditorPage> {
  String _title = '';
  String _content = '';
  bool _isSaving = false;
  
  void _updateTitle(String value) {
    setState(() {
      _title = value;
    });
  }
  
  void _updateContent(String value) {
    setState(() {
      _content = value;
    });
  }
}

StatefulWidget配合setState是Flutter内置的状态管理方式。状态变量定义在State类中,通过setState方法更新状态并触发UI重建。这种方式简单直接,适合管理单个组件内部的状态。在笔记编辑页面中,标题、内容、保存状态等都可以作为组件内部状态来管理。setState会触发build方法重新执行,Flutter会智能地只更新变化的部分。

Future<void> _saveNote() async {
  if (_isSaving) return;
  
  setState(() => _isSaving = true);
  try {
    await NoteService.saveNote(Note(title: _title, content: _content));
    Navigator.pop(context);
  } catch (e) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('保存失败')),
    );
  } finally {
    setState(() => _isSaving = false);
  }
}

异步操作中的状态管理需要注意时序问题。_isSaving状态用于防止重复提交和显示加载状态。在异步操作开始前设置为true,完成后设置为false。try-catch-finally确保无论成功还是失败都会重置状态。这种模式在处理网络请求、数据库操作等异步任务时非常常见。

Flutter Provider状态管理

Provider是Flutter官方推荐的状态管理方案之一。

class NotesProvider extends ChangeNotifier {
  List<Note> _notes = [];
  bool _isLoading = false;
  
  List<Note> get notes => _notes;
  bool get isLoading => _isLoading;
  
  Future<void> loadNotes() async {
    _isLoading = true;
    notifyListeners();
    
    try {
      _notes = await NoteService.fetchNotes();
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
  
  void addNote(Note note) {
    _notes.add(note);
    notifyListeners();
  }
  
  void deleteNote(String id) {
    _notes.removeWhere((note) => note.id == id);
    notifyListeners();
  }
}

Provider基于ChangeNotifier实现状态管理。状态变量定义为私有属性,通过getter暴露给外部。修改状态后调用notifyListeners通知所有监听者更新UI。这种模式将状态逻辑集中在Provider类中,使得状态管理更加清晰和可测试。Provider可以在组件树的任意位置提供和消费状态,解决了跨组件状态共享的问题。

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => NotesProvider(),
      child: MyApp(),
    ),
  );
}

class NotesListPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Consumer<NotesProvider>(
      builder: (context, notesProvider, child) {
        if (notesProvider.isLoading) {
          return Center(child: CircularProgressIndicator());
        }
        return ListView.builder(
          itemCount: notesProvider.notes.length,
          itemBuilder: (context, index) {
            return NoteListItem(note: notesProvider.notes[index]);
          },
        );
      },
    );
  }
}

ChangeNotifierProvider在组件树顶部提供NotesProvider实例。Consumer组件监听Provider的变化并重建UI,builder回调接收notesProvider参数用于访问状态和方法。这种依赖注入的方式使得组件与状态解耦,组件只需要声明依赖的Provider类型,具体实例由框架提供。

OpenHarmony状态管理

OpenHarmony通过装饰器实现响应式状态管理。

@Entry
@Component
struct NoteEditorPage {
  @State title: string = ''
  @State content: string = ''
  @State isSaving: boolean = false
  
  build() {
    Column() {
      TextInput({ placeholder: '标题', text: this.title })
        .onChange((value: string) => {
          this.title = value
        })
      
      TextArea({ placeholder: '内容', text: this.content })
        .onChange((value: string) => {
          this.content = value
        })
      
      Button(this.isSaving ? '保存中...' : '保存')
        .enabled(!this.isSaving)
        .onClick(() => {
          this.saveNote()
        })
    }
  }
}

@State装饰器声明组件内部状态,当状态变化时会自动触发UI更新。与Flutter的setState不同,OpenHarmony的状态更新是自动的,直接赋值即可触发重建。这种响应式的设计使得代码更加简洁,开发者不需要手动调用更新方法。@State适合管理组件内部的简单状态。

@Observed
class NotesStore {
  noteList: NoteItem[] = []
  isLoading: boolean = false
  
  async loadNotes() {
    this.isLoading = true
    try {
      this.noteList = await NoteService.fetchNotes()
    } finally {
      this.isLoading = false
    }
  }
  
  addNote(note: NoteItem) {
    this.noteList.push(note)
  }
  
  deleteNote(id: string) {
    this.noteList = this.noteList.filter(item => item.id !== id)
  }
}

@Observed装饰器使类成为可观察对象,当其属性变化时会通知观察者。NotesStore集中管理笔记相关的状态和操作,类似于Flutter的Provider。方法中直接修改属性即可触发更新,不需要额外的通知调用。这种设计让状态管理代码更加简洁直观。

@Entry
@Component
struct NotesListPage {
  @StorageLink('notesStore') notesStore: NotesStore = new NotesStore()
  
  build() {
    Column() {
      if (this.notesStore.isLoading) {
        LoadingProgress()
      } else {
        List() {
          ForEach(this.notesStore.noteList, (item: NoteItem) => {
            ListItem() {
              this.NoteItemBuilder(item)
            }
          })
        }
      }
    }
  }
  
  aboutToAppear() {
    this.notesStore.loadNotes()
  }
}

@StorageLink装饰器用于连接全局存储中的状态,实现跨组件的状态共享。当notesStore的属性变化时,所有使用@StorageLink连接它的组件都会自动更新。aboutToAppear是组件生命周期方法,在组件即将显示时调用,适合执行数据加载等初始化操作。

状态持久化

应用状态有时需要持久化到本地存储。

class NotesProvider extends ChangeNotifier {
  List<Note> _notes = [];
  
  Future<void> loadFromStorage() async {
    final prefs = await SharedPreferences.getInstance();
    final notesJson = prefs.getString('notes');
    if (notesJson != null) {
      final List<dynamic> decoded = jsonDecode(notesJson);
      _notes = decoded.map((e) => Note.fromJson(e)).toList();
      notifyListeners();
    }
  }
  
  Future<void> _saveToStorage() async {
    final prefs = await SharedPreferences.getInstance();
    final notesJson = jsonEncode(_notes.map((e) => e.toJson()).toList());
    await prefs.setString('notes', notesJson);
  }
  
  void addNote(Note note) {
    _notes.add(note);
    notifyListeners();
    _saveToStorage();
  }
}

状态持久化将内存中的状态保存到本地存储,应用重启后可以恢复。loadFromStorage在应用启动时从SharedPreferences读取数据并反序列化。_saveToStorage在状态变化时将数据序列化并保存。这种模式确保用户数据不会因为应用关闭而丢失,是笔记应用的基本要求。

状态分层

复杂应用通常需要对状态进行分层管理。

// 全局状态
class AppState extends ChangeNotifier {
  ThemeMode themeMode = ThemeMode.system;
  User? currentUser;
}

// 功能模块状态
class NotesState extends ChangeNotifier {
  List<Note> notes = [];
  String? selectedFolderId;
}

// 页面状态
class NoteEditorState extends ChangeNotifier {
  String title = '';
  String content = '';
  bool hasChanges = false;
}

状态分层将不同作用域的状态分开管理。全局状态如主题、用户信息在整个应用中共享。功能模块状态如笔记列表在特定功能模块中使用。页面状态如编辑器内容只在单个页面中有效。这种分层设计使得状态管理更加清晰,避免了全局状态过于庞大的问题。

总结

状态管理是应用开发的核心问题,Flutter和OpenHarmony都提供了多种状态管理方案。对于简单场景,组件内部状态就足够了;对于复杂场景,需要使用Provider或全局存储来实现跨组件状态共享。开发者需要根据应用的复杂度和团队的技术栈选择合适的方案,同时注意状态的分层和持久化。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐