Skip to main content
Version: 5.x.x

Realtime Store - Flutter

The Realtime Store allows you to store, update, retrieve, and observe custom key-value data within a room — in real time. It acts as a shared data layer across all connected participants, ensuring synchronized states throughout the session.

This is particularly useful for collaborative or stateful room experiences such as:

  • Pinned messages and flags
  • Moderation data (e.g., blocked users)
  • Collaborative notes or polls
note

Every RealtimeStore method needs a joined room, so call them from your Events.roomJoined handler or later. Called before the room is joined, they throw a VideoSDKError with code 3035. When the SDK refuses a call, it throws a VideoSDKError. Wrap each call in try/catch.

setValue()​

The setValue() method is used to store or update data in the RealtimeStore. If a key already exists, it will be overwritten with the new value. Passing null as the value deletes the key.

Key Notes​

  • Supports String values only.
  • Each key can store up to 1 KB of data (1024 bytes of UTF-8).
  • A maximum of 100 keys are allowed per session.
  • Deletion is performed by setting the value to null.
  • Throws a VideoSDKError if:
    • The key is empty or only whitespace (3073).
    • The value is empty or only whitespace (3073). Use null to delete a key.
    • The value is larger than 1 KB (3072).
    • The room has not been joined yet. This throws a VideoSDKError with code 3035.
    • The request fails. This throws a VideoSDKError, for example 4045 (FAILED_TO_SET_VALUE), or 3065 (ERROR_ROOM_RECONNECTING) while the room reconnects.
    • The session exceeds the 100-key limit.

Parameters​

  • key (String)
    The unique key to store the data under.

  • value (String?)
    The string value to be stored. Pass null to delete the key.

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
//Existing configuration
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

@override
void initState() {
super.initState();
_room = VideoSDK.createRoom(
roomId: widget.roomId,
token: widget.token,
participantName: "User1",
micEnabled: true,
camEnabled: true,
defaultCamera: FacingMode.FRONT,
multiStream: true,
mode: Mode.SEND_AND_RECV,
);
_joinRoom();
}

Future<void> _joinRoom() async {
try {
await _room.join();
} on VideoSDKError catch (e) {
print("Join failed: ${e.code} ${e.name}");
}
}

@override
void dispose() {
// Leave the room when the screen closes. The room releases itself.
_room.leave().catchError((Object e) => print("Leave failed: $e"));
super.dispose();
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
onPressed: () async {
String key = "BLOCK_CHAT";
String value = "true";
try {
await _room.realtimeStore.setValue(key, value);
} catch (e) {
print("Error:$e");
}
},
child: const Text("Realtime Store Set Value"),
),
]);
}
}


getValue()​

The getValue() method retrieves the current value associated with a given key.

Key Notes​

  • Returns the current string value for the given key, or null when the server answers with no value. A key that is not set throws 4046.
  • Useful for fetching shared state when joining a room or reloading a view.
  • Throws a VideoSDKError: 3073 for an empty key, 3035 if the room has not been joined yet, 4046 (FAILED_TO_GET_VALUE) when the key is not set or was cleared, or another code if the request fails.

Parameters​

  • key (String)
    The key whose value you want to retrieve. It must not be empty.

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
//Existing configuration
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;
String? _response;

@override
void initState() {
super.initState();
_room = VideoSDK.createRoom(
roomId: widget.roomId,
token: widget.token,
participantName: "User1",
micEnabled: true,
camEnabled: true,
defaultCamera: FacingMode.FRONT,
multiStream: true,
mode: Mode.SEND_AND_RECV,
);
_joinRoom();
}

Future<void> _joinRoom() async {
try {
await _room.join();
} on VideoSDKError catch (e) {
print("Join failed: ${e.code} ${e.name}");
}
}

@override
void dispose() {
// Leave the room when the screen closes. The room releases itself.
_room.leave().catchError((Object e) => print("Leave failed: $e"));
super.dispose();
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
onPressed: () async {
String key = "BLOCK_CHAT";
try {
String? response = await _room.realtimeStore.getValue(key);
setState(() => _response = response);
} catch (e) {
print("Error:$e"); // 4046 when the key is not set
}
},
child: Text("Realtime Store Get Value: $_response"),
),
]);
}
}

observe()​

The observe() method subscribes a listener to real-time updates for a given key. When the key’s value changes, your listener runs for every participant observing that key.

Key Notes​

  • Returns nothing. The listener itself identifies the observation: pass the same function to stopObserving().
  • The listener receives the new value and information about who updated it.
  • Observing a key subscribes to it on the server, so every change, from any participant, reaches your listener until you stop observing.
  • Ideal for syncing live data like timers, shared notes, or agendas.
  • Throws a VideoSDKError: 3035 if the room has not been joined yet, or another code if the request fails.

Parameters​

  • key (String)
    The key to observe. An empty key observes nothing.

  • listener (void Function(String? value, Participant? updatedBy)) Function triggered on each update. Receives:

    • value (String?) → Updated value or null if deleted
    • updatedBy (Participant?) → Object of participant who made the update, or null if that participant is no longer in the room

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
//Existing configuration
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

@override
void initState() {
super.initState();
_room = VideoSDK.createRoom(
roomId: widget.roomId,
token: widget.token,
participantName: "User1",
micEnabled: true,
camEnabled: true,
defaultCamera: FacingMode.FRONT,
multiStream: true,
mode: Mode.SEND_AND_RECV,
);
_joinRoom();
}

Future<void> _joinRoom() async {
try {
await _room.join();
} on VideoSDKError catch (e) {
print("Join failed: ${e.code} ${e.name}");
}
}

@override
void dispose() {
// Leave the room when the screen closes. The room releases itself.
_room.leave().catchError((Object e) => print("Leave failed: $e"));
super.dispose();
}

// Keep the listener in a field: stopObserving() takes the same function.
void _onBlockChat(String? value, Participant? updatedBy) {
print("New value: $value, updated by: ${updatedBy?.id}");
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
onPressed: () async {
String key = "BLOCK_CHAT";
try {
await _room.realtimeStore.observe(key, _onBlockChat);
} catch (e) {
print("Error:$e");
}
},
child: const Text("Realtime Store Observe"),
),
]);
}
}

stopObserving()​

Stops receiving updates for a specific key and listener combination.

Key Notes​

  • Should be called when the listener is no longer needed (e.g., component unmount).
  • The listener stops at once. When it was the key's last listener, the SDK also stops observing the key, which needs a joined room. Once Events.roomLeft has fired, the listener is still removed, but the call throws a VideoSDKError with code 3035.

Parameters​

  • key (String) The key you passed to observe().

  • listener (void Function(String? value, Participant? updatedBy)) The same function you passed to observe().

Example​

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
//Existing configuration
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

@override
void initState() {
super.initState();
_room = VideoSDK.createRoom(
roomId: widget.roomId,
token: widget.token,
participantName: "User1",
micEnabled: true,
camEnabled: true,
defaultCamera: FacingMode.FRONT,
multiStream: true,
mode: Mode.SEND_AND_RECV,
);
_joinRoom();
}

Future<void> _joinRoom() async {
try {
await _room.join();
} on VideoSDKError catch (e) {
print("Join failed: ${e.code} ${e.name}");
}
}

@override
void dispose() {
// Leave the room when the screen closes. The room releases itself.
_room.leave().catchError((Object e) => print("Leave failed: $e"));
super.dispose();
}

void _onBlockChat(String? value, Participant? updatedBy) {
print("New value: $value, updated by: ${updatedBy?.id}");
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
onPressed: () async {
try {
// The same key and function you passed to observe()
await _room.realtimeStore.stopObserving("BLOCK_CHAT", _onBlockChat);
} catch (e) {
print("Error:$e");
}
},
child: const Text("Realtime Store Stop Observing"),
),
]);
}
}

Error Handling & Constraints​

PropertyDescription
Error HandlingEvery method returns a Future. Await it inside try/catch: a call made before join throws a VideoSDKError with code 3035, and a failed request throws a VideoSDKError.
Payload SizeMaximum 1 KB per key.
Supported TypeOnly String values are supported. Use null to delete key.
ConcurrencyThe latest write overwrites previous values (last write wins)
Key LimitA maximum of 100 keys are allowed in a single session.

API Reference

The API references for this page are provided below.

Got a Question? Ask us on discord