Skip to content

Usage examples

Vid Klopcic edited this page Oct 5, 2023 · 14 revisions

Creating the SocketApi instance

The SocketApi class has a factory constructor, that only creates a new instance if the passed address is new, else it return the existing instance. Usually we define a global variable that is used across the entire application.

SocketApi socketApi = SocketApi('$SCHEME://$HOST/ws/')

Handling authentication

There is a default abstract class AuthenticationController that handles authentication logic using the default auth messages (defined in proto/authentication.proto).

class MyAuthController extends AuthenticationController {
  MyAuthController() : super(socketApi) {
    listen(socketApi.connection.connected.changes, _connectionChanges);
  }

  void _connectionChanges(bool connected) {
    if (connected) authenticationController.verifyToken();
  }
}

MyAuthController authenticationController = MyAuthController();

Default login-token message is cached for 1 year. To load the cached token message, call await authenticationController.init() before the app starts. From here on, we can check whether we are logged in using socketApi.authenticated.val or listen to its changes by subscribing to the socketApi.authenticated.changes stream.

To logout the user, just set the socketApi.setAuth(null) or prefferrably myAuthenticationController.logout(), which will also invalidate the cache for you.

Listening to a message

It is recommended to use the listen helper from the SubscriptionsMixin in gm5_utils package, because it handles the casts for you (stream.listen((item) => callback(item as T) where T is the type of the message argument in the handler function). It is also convenient that subscription objects are automatically stored, so you can only call cancelSubscriptions() in the dispose method of the widget / class to cancel all subscriptions.

listen(socketApi.getMessageHandler(RxShowDialog()), _showDialog);
void _showDialog(RxShowDialog message) {
    // handle the message
}

Loading cached messages

In order to fire the cached messages from cache, you can call fireFromCache method, which will dispatch matching Rx messages to all registered handlers.

int nMessagesSent = await socketApi.fireFromCache(RxDynamicForm());

If you want to load messages directly without emitting them to handlers, you can use getFromCache method, which returns null if no messages are found, else list of all matching messages.

// fetch first message or create new if no messages are found
RxAppState appState = (await socketApi.getFromCache(RxAppState()))?.first ?? RxAppState();
List<RxNotification> notification = await socketApi.getFromCache(RxNotification())

FILTERING

You might want to load only a specific instance of the cached message (eg. only the one that was cached using a specific id and kind value). All examples are applicable to getFromCache method as well.

socketApi.fireFromCache(RxDynamicForm()
      ..data.carEntryId = car.id
      ..data.kind = kind
);

In order for this to work, cache keys must include the carEntryId and kind parameters!

If you need more control of the filtering, you can specify the filter parameter and get access to the raw SQL query. Make sure you import the import 'package:moor/moor.dart'; package!

final message = RxDynamicFieldValue();
socketApi.fireFromCache(message,
  filter: (q) => q
  ..where(
    (table) => message.cacheKeys.myCacheKey.realField(table).isSmallerThan(someValue)
  )
);

Sending a message

socketApi.sendMessage(TxLoadReport.create((data) => data..reportId = reportId));

Listening to a message using generated provider

This will fetch the last received value and update whenever new message is received.

final user = context.watch<RxUserProfile>();

In order to setup generated providers add them above the MaterialApp

import 'messages.dart';
import 'package:flutter_persistent_socket/messages.dart' as fps;

MultiProvider(
  providers: getMessageProviders(socketApi) + fps.getMessageProviders(socketApi),
  child: MyApp(),
),

Invalidate cache

To invalidate entire cache just call.

database.socketRxEventDao.invalidateCache();

If user logs out, the AuthenticationController does this automatically.

To invalidate specific message type call

database.socketRxEventDao.invalidateCacheForMessageType(RxMessage());

To invalidate message based on a cacheUuid, that depends on defined client cache_keys and messageType, call

database.socketRxEventDao.invalidateCacheForCacheUuid(filterMessage);

To invalidate using custom SQL query, use

database.socketRxEventDao.invalidateCache((q) => q..where((table) => ...));