📅  最后修改于: 2023-12-03 15:30:47.883000             🧑  作者: Mango
本文介绍了使用 Flutter API 创建基本测验应用程序的步骤和方法。
首先,使用 Flutter 命令行工具创建一个新的 Flutter 应用程序。
flutter create quiz_app
cd quiz_app
这将创建一个名为 "quiz_app" 的新目录,并在其中创建一个包含默认模板代码的新 Flutter 应用程序。
接下来,我们需要添加一些依赖项来构建我们的应用程序。我们将使用两个依赖项:flutter_bloc
和 equatable
。
flutter_bloc
用于实现业务逻辑组件(bloc)equatable
用于轻松比较数据模型,从而更轻松地实现 ==
方法打开 pubspec.yaml
文件,并将以下依赖项添加到 dependencies
部分。
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^6.0.0
equatable: ^2.0.3
保存并运行 flutter packages get
命令以安装新的依赖项。
在这个应用程序中,我们将使用一个非常简单的数据模型——一个包含问题和答案的问题对象。我们将创建一个新的 Question
类来表示这些问题。
import 'package:equatable/equatable.dart';
class Question extends Equatable {
final String question;
final String answer;
Question({this.question, this.answer});
@override
List<Object> get props => [question, answer];
}
注意,我们扩展了 Equatable
类,并实现了 props
属性。这使得使用 ==
比较两个 Question
对象变得更容易。
我们将使用 flutter_bloc
创建一个新的业务逻辑组件(bloc),该组件将与应用程序的 UI 交互,并处理显示、回答问题等操作。
首先,我们将创建一个新的类,称为 QuizBloc
,该类将扩展 bloc
类。我们将添加一个 Question
列表,并定义一些 stream
来控制应用程序的状态。
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:quiz_app/models/question.dart';
part 'quiz_event.dart';
part 'quiz_state.dart';
class QuizBloc extends Bloc<QuizEvent, QuizState> {
var _questions = [
Question(question: '你叫什么名字', answer: 'My name is Jon Snow.'),
Question(question: '你今年多大了', answer: 'I am 22 years old.'),
Question(question: '今天天气如何?', answer: 'The weather is great today.')
];
int _currentQuestionIndex = 0;
QuizBloc() : super(QuizInitial()) {
add(QuizStarted());
}
@override
Stream<QuizState> mapEventToState(
QuizEvent event,
) async* {
if (event is QuizStarted) {
yield QuestionLoadedState(_questions[_currentQuestionIndex]);
} else if (event is AnswerProvidedEvent &&
event.answer == _questions[_currentQuestionIndex].answer) {
if (_currentQuestionIndex < _questions.length - 1) {
_currentQuestionIndex++;
yield QuestionLoadedState(_questions[_currentQuestionIndex]);
} else {
yield QuizFinishedState();
}
} else {
yield IncorrectAnswerState();
}
}
}
这里我们只有一个 _currentQuestionIndex
列表变量,该变量“指向”正确的问题对象。每次回答正确的问题之后,我们会将它提前一个位置并且更新 stream
,从而显示一下个问题。
注意,我们将事件和状态分开管理,以使应用程序变得更简洁和可维护。
现在,我们必须定义一些事件和状态,这些事件和状态将用于驱动业务逻辑组件并更新应用程序的状态。
part of 'quiz_bloc.dart';
abstract class QuizEvent extends Equatable {
@override
List<Object> get props => [];
}
class QuizStarted extends QuizEvent {}
class AnswerProvidedEvent extends QuizEvent {
final String answer;
AnswerProvidedEvent({@required this.answer});
@override
List<Object> get props => [answer];
}
part of 'quiz_bloc.dart';
abstract class QuizState extends Equatable {
@override
List<Object> get props => [];
}
class QuizInitial extends QuizState {}
class QuestionLoadedState extends QuizState {
final Question question;
QuestionLoadedState(this.question);
@override
List<Object> get props => [question];
}
class IncorrectAnswerState extends QuizState {}
class QuizFinishedState extends QuizState {}
这是我们最后的任务:构建用户界面。我们将使用 Flutter 的内置小部件构建我们的应用程序。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:quiz_app/blocs/quiz/quiz_bloc.dart';
import 'package:quiz_app/models/question.dart';
class QuizPage extends StatelessWidget {
const QuizPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<QuizBloc, QuizState>(
builder: (context, state) {
if (state is QuestionLoadedState) {
return Scaffold(
appBar: AppBar(
title: Text('Quiz App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
state.question.question,
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
buildAnswerButton(context, 'Yes'),
SizedBox(height: 10),
buildAnswerButton(context, 'No'),
],
),
),
);
} else if (state is QuizFinishedState) {
return Scaffold(
appBar: AppBar(
title: Text('Quiz App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Congratulation! You have completed the quiz',
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
FlatButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
BlocProvider.of<QuizBloc>(context).add(QuizStarted());
},
child: Text('Restart Quiz'),
),
],
),
),
);
} else if (state is IncorrectAnswerState) {
return Scaffold(
appBar: AppBar(
title: Text('Quiz App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Sorry, the answer is incorrect.',
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
FlatButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
BlocProvider.of<QuizBloc>(context).add(QuizStarted());
},
child: Text('Start Over'),
),
],
),
),
);
} else {
return Scaffold(
appBar: AppBar(
title: Text('Quiz App'),
),
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
Widget buildAnswerButton(BuildContext context, String answer) {
return SizedBox(
width: 200,
height: 50,
child: FlatButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
BlocProvider.of<QuizBloc>(context)
.add(AnswerProvidedEvent(answer: answer));
},
child: Text(answer),
),
);
}
}
我们使用了 flutter_bloc
提供的 BlocBuilder
来构建 UI。这样,我们的 UI 将根据业务逻辑组件的状态动态构建。
根据当前的状态,我们通过不同的 Scaffold
和内部的小部件构建不同的 UI。
至此,我们已经构建了一个简单的测验应用程序,并在其中使用了 flutter_bloc
和 equatable
库。
我们通过构建一个业务逻辑组件并在用户界面中使用 BlocBuilder
来控制 UI 状态。这种设计模式使我们的应用程序变得更加模块化、可维护性更高。
我们还提供了一些简单的代码示例,以帮助您更好地理解如何使用 Flutter API 创建应用程序。