结丹期

8. Flutter 中的 StatefulWidgetStatelessWidget 有什么区别?

StatefulWidgetStatelessWidgetFlutter 中两种基本的 Widget 类型,二者的主要区别在于是否具有状态。

  • StatelessWidget

    • 不需要维护状态,状态一经创建后就不再发生变化。

    • 通常用于显示静态内容,比如文本、图标等。

    class MyStatelessWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Text('I am Stateless');
      }
    }
    
  • StatefulWidget

    • 需要维护状态,状态可以在生命周期内发生变化。

    • 适用于需要更新 UI 的动态场景,比如表单输入、计数器等。

    class MyStatefulWidget extends StatefulWidget {
      @override
      _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
    }
    
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      int counter = 0;
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Text('Counter: $counter'),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  counter++;
                });
              },
              child: Text('Increment'),
            ),
          ],
        );
      }
    }
    

StatelessWidget 适用于静态内容,而 StatefulWidget 适用于动态交互,使用 setState() 更新 UI


9. 如何在 Flutter 中使用路由和导航?如何在页面之间传递数据?

Flutter 中,页面之间的导航是通过 Navigator 类来管理的,页面的切换是通过路由来实现的。

基本的导航方法

  • Navigator.push():用于导航到新页面。

  • Navigator.pop():用于返回上一个页面。

传递数据的方式

  • 使用 Navigator.push() 方法时,可以通过构造函数将数据传递给新页面。

  • 返回数据时可以通过 Navigator.pop() 方法传递结果。

// 页面之间的导航与数据传递
// 主页
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final result = await Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondPage(data: 'Hello from HomePage')),
            );
            print('Returned data: $result');
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

// 第二页
class SecondPage extends StatelessWidget {
  final String data;

  SecondPage({required this.data});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Column(
        children: [
          Text('Received data: $data'),
          ElevatedButton(
            onPressed: () {
              Navigator.pop(context, 'Hello from SecondPage');
            },
            child: Text('Go back with data'),
          ),
        ],
      ),
    );
  }
}

在页面间导航时,可以通过 MaterialPageRoute 创建新路由并传递数据,使用 Navigator.pop() 返回数据给上一个页面。


10. 如何在 Flutter 中实现异步编程?什么是 Futureasync/await

Flutter 中,异步编程通过 Futureasync/await 关键字来实现,Future 表示一个延迟完成的异步任务。

Future:表示一个异步操作的结果,它可以是成功的结果或者失败的错误。

async/awaitasync 将函数声明为异步函数,await 用于暂停代码执行,直到异步操作完成。

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));  // 模拟耗时操作
  return 'Data fetched';
}

void main() async {
  String data = await fetchData();
  print(data);  // 输出 'Data fetched'
}

async 标记函数为异步,await 用于等待异步操作完成。在这个示例中,模拟了一个耗时任务,等待 2 秒后返回数据。


11. Flutter 中的 Stream 是什么?它的常见应用场景有哪些?

StreamFlutter 中的一种异步数据处理方式,表示一个可以连续接收异步事件的数据流。

它适合处理多次事件的场景,比如消息、传感器数据、文件读取等。

Stream 的常见应用场景

  • 网络请求的响应:处理持续的 WebSocket 数据流。

  • 用户输入:实时监听输入框内容的变化。

  • 传感器数据:处理设备传感器发送的连续数据。

Stream<int> numberStream = Stream.periodic(Duration(seconds: 1), (i) => i);

void listenToStream() {
  numberStream.listen((number) {
    print('Received: $number');
  });
}

void main() {
  listenToStream();  // 每秒输出一个自增的数字
}

Stream 类似于 Future,但它可以接收多个异步事件。在此示例中,Stream 每秒产生一个自增的数字并将其传递给监听器。


12. 如何在 Flutter 中进行本地数据存储?常见的持久化方式有哪些?

  • SharedPreferences:用于存储简单的键值对数据,适合存储少量的配置信息或用户设置。

     SharedPreferences prefs = await SharedPreferences.getInstance();
     prefs.setString('username', 'John');
     String username = prefs.getString('username') ?? 'defaultUser';
    
  • 文件存储:使用 dart:io 提供的文件系统,适合存储较大或者结构化的数据。

     final directory = await getApplicationDocumentsDirectory();
     final file = File('${directory.path}/data.txt');
     await file.writeAsString('Hello Flutter');
    
  • SQLite:使用 sqflite 插件进行结构化数据存储,适合存储复杂的关系型数据。

     Database db = await openDatabase('my_db.db');
     await db.insert('users', {'name': 'John', 'age': 25});
    

SharedPreferences 适用于轻量数据存储,文件系统和 SQLite 适用于大数据或结构化数据的存储。


13. 如何在 Flutter 中发起网络请求?如何使用 http 包?

Flutter 中可以使用 http 包来发起网络请求,处理 GETPOST 等常见的 HTTP 请求。

  • 添加依赖

    pubspec.yaml 文件中添加 http 依赖。

     dependencies:
       http: ^0.13.3
    
  • 发起 GET 请求

     import 'package:http/http.dart' as http;
    
     Future<void> fetchData() async {
       final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    
       if (response.statusCode == 200) {
         print(response.body);  // 处理成功响应
       } else {
         throw Exception('Failed to load data');
       }
     }
    
  • 发起 POST 请求

     Future<void> sendData() async {
       final response = await http.post(
         Uri.parse('https://jsonplaceholder.typicode.com/posts'),
         body: {'title': 'Flutter', 'body': 'Hello World'},
       );
       print('Response status: ${response.statusCode}');
     }
    

http 包提供了简洁的 GETPOST 请求方式,异步处理网络请求并获取响应数据。


14. 如何在 Flutter 中实现状态管理?常见的状态管理解决方案有哪些?

Flutter 中,状态管理是一个非常重要的话题,setState() 是最基础的状态管理方法,但对于复杂应用,常常需要使用更高级的状态管理工具。

  • setState()

    • 用于本地状态管理,适合简单的单页面应用,但不适合跨页面或跨组件的复杂状态管理。
  • Provider

    • 基于 InheritedWidget,是 Flutter 官方推荐的状态管理方式,适合全局状态共享。

      class Counter extends ChangeNotifier {
      int _count = 0;
      int get count => _count;
      
      void increment() {
        _count++;
        notifyListeners();
      }
      }
      
      void main() {
      runApp(
        ChangeNotifierProvider(
          create: (_) => Counter(),
          child: MyApp(),
        ),
      );
      }
      
  • Bloc(业务逻辑组件)

    • Bloc 是基于事件的状态管理框架,适合大型项目,具有较高的架构清晰度。

      BlocBuilder<CounterBloc, int>(
      builder: (context, count) {
        return Text('Counter: $count');
      },
      );
      
  • Riverpod

    • RiverpodProvider 的改进版,解决了 Provider 中一些常见的局限性,提供了更灵活的依赖注入方式。

Provider 是最常用的状态管理方式,Bloc 则适合复杂的状态管理需求,而 Riverpod 是最新的状态管理方案,提供了更强的灵活性和可测试性。

results matching ""

    No results matching ""