diff --git a/lib/main.dart b/lib/main.dart
index 9bd28bc65bbcab34c58de1fe677e1384d73485ee..da393dc7425c3fe7fd04eda48fc29377762bb0f1 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,11 +9,12 @@ import 'dialogs/error_dialog.dart';
 import 'drawer/drawer.dart';
 import 'timetable/timetable.dart';
 import 'toolbar/toolbar.dart';
-import 'untis/element_type.dart';
 import 'untis/fetch.dart';
 import 'untis/timetable.dart';
 import 'user/save_state.dart';
 import 'util/listenable.dart';
+import 'views/mixed_class_view.dart';
+import 'views/view.dart';
 
 void main() {
   runApp(const MyApp());
@@ -57,9 +58,11 @@ class MyHomePage extends StatefulWidget {
 }
 
 class _MyHomePageState extends State<MyHomePage> {
-  TimetableData? timetable;
+  late TimetableView view;
   late List<StreamSubscription> _subscriptions;
 
+  TimetableData? timetable;
+
   AppContext get appContext => widget.appContext;
   UntisFetch get untis => appContext.untis;
 
@@ -109,18 +112,11 @@ class _MyHomePageState extends State<MyHomePage> {
     final profile = await appContext.profile.firstNotNull;
     final selectedClasses = profile.selectedClasses;
 
-    final allTimetables = await Future.wait(selectedClasses.map((classId) {
-      final cacheable = untis.timetableOf(
-        type: ElementType.classGroup,
-        elementId: classId,
-        date: date,
-      );
-
-      return Future(() => cacheable.fetched);
-    }));
+    view = MixedClassView(classIds: selectedClasses);
+    final fetchedTimetable = await view.timetableOf(date, untis: untis);
 
     setState(() {
-      timetable = TimetableData.mergeAll(allTimetables);
+      timetable = fetchedTimetable;
     });
   }
 
diff --git a/lib/views/mixed_class_view.dart b/lib/views/mixed_class_view.dart
new file mode 100644
index 0000000000000000000000000000000000000000..57fd7d60c3ba708c004b558290e632fbe7af8081
--- /dev/null
+++ b/lib/views/mixed_class_view.dart
@@ -0,0 +1,30 @@
+import '../untis/element_type.dart';
+import '../untis/fetch.dart';
+import '../untis/timetable.dart';
+import 'dart:async';
+
+import 'view.dart';
+
+class MixedClassView extends TimetableView {
+  final Set<int> classIds;
+
+  MixedClassView({required this.classIds});
+
+  @override
+  FutureOr<TimetableData?> timetableOf(
+    DateTime date, {
+    required UntisFetch untis,
+  }) async {
+    final allTimetables = await Future.wait(classIds.map((classId) {
+      final cacheable = untis.timetableOf(
+        type: ElementType.classGroup,
+        elementId: classId,
+        date: date,
+      );
+
+      return Future(() => cacheable.fetched);
+    }));
+
+    return TimetableData.mergeAll(allTimetables);
+  }
+}
diff --git a/lib/views/view.dart b/lib/views/view.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ae9a46418c7b8357f02fb26ab6fc6645c88cbd16
--- /dev/null
+++ b/lib/views/view.dart
@@ -0,0 +1,11 @@
+import 'dart:async';
+
+import '../untis/fetch.dart';
+import '../untis/timetable.dart';
+
+abstract class TimetableView {
+  FutureOr<TimetableData?> timetableOf(
+    DateTime date, {
+    required UntisFetch untis,
+  });
+}