Getting Started with Appwrite Realtime API in Your Flutter App

Getting Started with Appwrite Realtime API in Your Flutter App

ยท

5 min read

In the world of modern application development, real-time interactions have become essential to create engaging and dynamic user experiences. Appwrite, a powerful backend-as-a-service platform, offers a Realtime API that enables developers to implement real-time functionality into their applications. In this tutorial, we'll explore how to integrate the Appwrite Realtime API into a Flutter app to create a real-time Rick and Morty character showcase app.

Buckle up and prepare for an exciting coding journey! We're about to dive into a world brimming with the quirky characters and uproarious escapades of Rick and Morty.

Start Building ๐Ÿ‘จโ€๐Ÿ’ป

Prerequisites:

  1. Basic understanding of Flutter and Dart programming.

  2. Appwrite Cloud Account.

Step 1: Create Appwrite Project And Add The Collection

Login to cloud.appwrite.io and click on Create project button from the dashboard. Name your project, hit the Create button, and your Appwrite project is ready. Click on the Databases menu in the navbar and create a new database. Now make the characters Collections to store data of the characters with attributes like name, species, age, image, etc. Go to settings and update permissions. This would help you to control who has what access and permissions to the docs inside the collections.

Step 2: Set Up Your Flutter Project

If you're new to Flutter, start by setting up a new Flutter project using the Flutter CLI or your preferred IDE. Absolute beginners can follow my tutorial on Setting up Flutter on your local machine.

Step 3: Add Your Flutter App As A Platform

In the Overview menu, click on Add a Platform and add the app name and package name to add the Flutter app to the project.

Step 4: Add Appwrite Dependency

Open your pubspec.yaml file and add the Appwrite dependency to your project.

dependencies:
  flutter:
    sdk: flutter
  appwrite: ^8.1.0

Run flutter pub get in your project root directory to install the dependency.

Step 3: Initialize Appwrite

In your Flutter app's main.dart file, import the required packages and initialize the Appwrite SDK.

import 'package:flutter/material.dart';
import 'package:rickandmorty/home.dart';
import 'package:appwrite/appwrite.dart';

Client client = Client();

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  client
      .setEndpoint('YOUR_APPWRITE_ENDPOINT')
      .setProject('YOUR_APPWRITE_PROJECT_ID')
      .setSelfSigned(status: true);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

Replace YOUR_APPWRITE_ENDPOINT and YOUR_APPWRITE_PROJECT_ID with your actual Appwrite server endpoint and project ID.

Step 4: Subscribing To Realtime Data

Listen for changes in the collection using the Appwrite SDK's Realtime API and update the UI with new character details.

import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:rickandmorty/main.dart';
import 'package:appwrite/appwrite.dart';
import 'package:rickandmorty/mycard.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Databases databases = Databases(client);
  String databaseId = 'Your_Database_ID';
  String collectionId = 'Your_Collection_ID';

  late RealtimeSubscription subscription;

  List<Map<String, dynamic>> items = [];

  @override
  void initState() {
    super.initState();
    loadItems();
    subscribe();
  }

  loadItems() async {
    try {
      await databases
          .listDocuments(
        databaseId: databaseId,
        collectionId: collectionId,
      )
          .then((value) {
        var currentDocs = value.documents;
        setState(() {
          items = currentDocs.map((e) => e.data).toList();
        });
      });

      for (var i in items) {
        log(i.toString());
      }
    } on AppwriteException catch (e) {
      log(e.message.toString());
    }
  }

  void subscribe() {
    final realtime = Realtime(client);

    subscription = realtime.subscribe(
        ['databases.$databaseId.collections.$collectionId.documents']);

    // listen to changes
    subscription.stream.listen((data) {
      log("there is some change");
      // data will consist of `events` and a `payload`
      if (data.payload.isNotEmpty) {
        log("there is some change");
        if (data.events
            .contains("databases.*.collections.*.documents.*.create")) {
          var item = data.payload;
          log("Item Added");
          items.add(item);
          setState(() {});
        } else if (data.events
            .contains("databases.*.collections.*.documents.*.delete")) {
          var item = data.payload;
          log("item deleted");
          items.removeWhere((it) => it['\$id'] == item['\$id']);
          setState(() {});
        } else if (data.events
            .contains("databases.*.collections.*.documents.*.update")) {
          var item = data.payload;
          log("item update");
          int idx = items.indexWhere((it) => it['\$id'] == item['\$id']);
          log("${idx} is the index");
          items[idx] = item;
          setState(() {});
        }
      }
    });
  }

  @override
  void dispose() {
    subscription.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Rick and Morty"),
        ),
        body: items.isNotEmpty
            ? ListView.builder(
                physics: const BouncingScrollPhysics(),
                itemCount: items.length,
                itemBuilder: (BuildContext context, int index) {
                  Map<String, dynamic> current_obj = items[index];
                  return MyCard(current_obj: current_obj);
                })
            : const Center(
                child: Text(
                  "Oops! No character to show",
                ),
              ));
  }
}

Replace Your_Database_ID and Your_Collection_ID with the actual ID of the collection, you created for storing Rick and Morty character data.

Step 5: Custom Card Widget To Display Character Data

Create a new mycard.dart file and define your character data card widget according to the type of data received.

import 'package:flutter/material.dart';

class MyCard extends StatelessWidget {
  final Map<String, dynamic> current_obj;
  const MyCard({Key? key, required this.current_obj}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: Container(
        clipBehavior: Clip.antiAliasWithSaveLayer,
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: Colors.lightBlue[100],
        ),
        height: 100,
        width: double.maxFinite,
        child: Row(
          children: [
            Container(
              height: 80,
              width: 80,
              clipBehavior: Clip.antiAliasWithSaveLayer,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(40),
                color: Colors.grey
              ),
              child: Image.network(current_obj["image"]),
            ),
            Column(
              children: [
                Text(current_obj["name"], style: TextStyle(fontSize: 22),),
                Text(current_obj["age"].toString()),
                Text(current_obj["gender"]),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

You can find the source code below ๐Ÿ‘‡

Woohoo ๐ŸŽ‰

Congratulations! You've successfully integrated the Appwrite Realtime API into your Flutter app to create a real-time Rick and Morty character showcase app. With the power of Appwrite, you can easily add real-time functionality to various parts of your application, enhancing the user experience and engagement.

Remember that this tutorial provides a basic introduction to using the Appwrite Realtime API. Appwrite offers a wide range of features beyond what's covered here, so explore their official documentation for more advanced use cases and customization options.

Happy Hacking!

To learn more about Appwrite and Flutter, check out ๐Ÿ‘‡

๐Ÿ“„ Appwrite Docs

โœจ Getting Started For Flutter

๐Ÿ’– Appwrite Discord Community

ย