139

I write websocket chat. How to generate unique id for user?

now i use this code:

id = new DateTime.now().millisecondsSinceEpoch;

is there any more neat solution?

Sergey Karasev
  • 4,513
  • 4
  • 25
  • 24

8 Answers8

197

1. There is a UUID pub package:

http://pub.dartlang.org/packages/uuid

example usage:

import 'package:uuid/uuid.dart';

// Create uuid object
var uuid = Uuid();

// Generate a v1 (time-based) id
uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 (random) id
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

// Generate a v5 (namespace-name-sha1-based) id
uuid.v5(uuid.NAMESPACE_URL, 'www.google.com'); // -> 'c74a196f-f19d-5ea9-bffd-a2742432fc9c'

2. This src has a dart GUID generator

https://github.com/MikeMitterer/AndroidIconGenerator.DART/blob/445884924/lib/src/model/communication/GUIDGen.dart

I'll not post the function src here directly as there is no apparent licence with it, but example usage is as follows:

final String uuid = GUIDGen.generate();
Zombo
  • 1
  • 62
  • 391
  • 407
Chris Buckett
  • 13,738
  • 5
  • 39
  • 46
  • 21
    Just a word of caution: this does not rely on strong random data. Therefore, the generated UUIDs should not be considered cryptographically strong. Whether it matters or not, I'll leave it to the reader to decide. – Kai Sellgren Mar 21 '13 at 21:12
  • thanks, i know, I will make an additional check the list of existing uuids – Sergey Karasev Mar 22 '13 at 07:01
  • 1
    @KaiSellgren This is a pretty old post, but I think I could enrich it by asking a question here. You said that "this does not rely on strong random data". Can you elaborate that? I mean, how could we make it stronger? – Felipe Jul 11 '15 at 18:16
  • @Felipe The library seems to now have an alternative function for random data generation: https://github.com/Daegalus/dart-uuid/blob/master/lib/uuid_util.dart -- I have not verified nor tested how strong that is, but you can do it rather trivially by calculating the chi square distribution. My Github page has a project for determining random data strength if you are curious. – Kai Sellgren Jul 12 '15 at 11:05
  • How can I use uuid multi times? I need to parse it in two different fields I have define final String image_name = Uuid().v1(); but every time I get differnt result. – Filippos Ser Nov 21 '18 at 19:04
  • How can I crate from string? thing about that, when you using a database transfer object? – withoutOne Mar 04 '22 at 10:36
  • Should the uuid object stay the same throughout the application or can it be remade for example on every object constructor call? – Kulpas Mar 16 '23 at 12:29
76

In year 2020 you can do UniqueKey(); which is a built in class:

https://api.flutter.dev/flutter/foundation/UniqueKey-class.html

Note

A key that is only equal to itself.

This cannot be created with a const constructor because that implies that all instantiated keys would be the same instance and therefore not be unique.

rekire
  • 47,260
  • 30
  • 167
  • 264
Pascal
  • 12,265
  • 25
  • 103
  • 195
  • 30
    I think the intended use of this class is for Widgets and not to be used as ID's in a db. – Gino Mar 06 '20 at 15:59
  • @Gino so this class is not secure as a unique ID? Why? – Rutrus Apr 09 '20 at 19:45
  • 10
    @Rutrus If you take a look at the class you can clearly see that it creates a key that it's unique only inside the app. This meaning that if you save you key outside the app like in a DB you might recreate again the same unique key later. [check Here](https://github.com/flutter/flutter/blob/f139b11009/packages/flutter/lib/src/widgets/framework.dart#L42) from row 83 to 103 and there's also a discussion if you want to take a look at it – Gino Apr 11 '20 at 10:26
  • 1
    Thank you Gino, but 16^5 is enough randomness for me. This UnikeKey() works fine for my utility. Of course is not cryptographically safe, but it is a quick and built-in method. – Rutrus Apr 11 '20 at 23:36
  • 2
    @Rufus It's not about crypto yet if it works for your utility then you should use it. Like they say "If it works then dont touch it!" – Gino Apr 16 '20 at 14:40
  • I was looking for a way to provide an ID for my model objects. Using UniqueKey() from the flutter framework would mean my redux models would depend on a UI framework. Therefore I just use a simple library to generate a unique identifier. – David Jun 06 '21 at 17:34
  • 2
    @Gino , u can use `UniqueKey().toString()` to get a unique string literal that can be saved in database. The Flutter team has overriden the `toString()` method of the `UniqueKey` class to return the underlying id associated with the key, [check here](https://github.com/flutter/flutter/blob/f139b11009/packages/flutter/lib/src/widgets/framework.dart#L42). – Son Nguyen Sep 18 '21 at 10:47
  • @SonXuanNguyen Glad they had the chance to improve it! Thanks for the update! – Gino Sep 23 '21 at 14:39
  • I recommend reading more about `UniqueKey` [in this answer](https://stackoverflow.com/a/67733173/1903781) There are some important things to understand about this class. – Adrian Moisa Mar 26 '22 at 13:04
  • Run and see how many duplicates you'll get with such method: void main() { final keyList = List.generate(2000, (_) => UniqueKey().toString()); var map = {}; for (var key in keyList) { map[key] = map.containsKey(key) ? map[key]! + 1 : 1; } map.removeWhere((key, count) => count == 1); print('duplicates: ${map.length} \n$map'); } – mhr Apr 08 '22 at 10:55
  • 1
    It may be sufficient randomness but it is "built-in" to the Widgets package which is a UI dependency and you are talking about generating IDs for a database so you are mixing/coupling logic and UI framework which is an unclean architecture. – TimMutlow Aug 02 '22 at 13:20
  • Is the hashCode guaranteed to always be unique? – jasxir Oct 04 '22 at 04:28
20

I use microseconds instead of milliseconds, which is much more accurate and there is no need to add any package.

 String idGenerator() {
    final now = DateTime.now();
    return now.microsecondsSinceEpoch.toString();
  }
dev001
  • 637
  • 8
  • 16
  • 1
    Yes - reasonable and no dependencies – Kenneth N Jun 04 '22 at 21:47
  • I notice the difference that micro always adds `000` at the back. – Kucing Malaya Sep 28 '22 at 07:27
  • 1
    A warning for anyone using this on Flutter web: "Note that this value does not fit into 53 bits (the size of a IEEE double). A JavaScript number is not able to hold this value.". – Alex Rintt Feb 17 '23 at 19:48
  • I have run into a situation in a Flutter Windows app where the generated microseconds repeat several times when used in a `for` loop (like when making a whole bunch of records in a row). Be careful since this may not be a guaranteed way to get unique values. – Clifton Labrum Jun 28 '23 at 20:56
11

Besides from uuid, you can also try this to generate small unique keys:

https://pub.dev/packages/nanoid

They even have a collision calculator:

https://zelark.github.io/nano-id-cc/

theredforest
  • 427
  • 4
  • 9
3

This method will generate unique Id similar to (-N4pvg_50j1CEqSb3SZt)

String getCustomUniqueId() {
  const String pushChars =
      '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
  int lastPushTime = 0;
  List lastRandChars = [];
  int now = DateTime.now().millisecondsSinceEpoch;
  bool duplicateTime = (now == lastPushTime);
  lastPushTime = now;
  List timeStampChars = List<String>.filled(8, '0');
  for (int i = 7; i >= 0; i--) {
    timeStampChars[i] = pushChars[now % 64];
    now = (now / 64).floor();
  }
  if (now != 0) {
    print("Id should be unique");
  }
  String uniqueId = timeStampChars.join('');
  if (!duplicateTime) {
    for (int i = 0; i < 12; i++) {
      lastRandChars.add((Random().nextDouble() * 64).floor());
    }
  } else {
    int i = 0;
    for (int i = 11; i >= 0 && lastRandChars[i] == 63; i--) {
      lastRandChars[i] = 0;
    }
    lastRandChars[i]++;
  }
  for (int i = 0; i < 12; i++) {
    uniqueId += pushChars[lastRandChars[i]];
  }
  return uniqueId;
}
Aks
  • 405
  • 4
  • 6
2

I've built a scenario to generate a unique cryptographically secure random id. with 4 random generations id's

  1. First 4 Alphabets from an alphabets list [a-z].

  2. Middle 4 digits from a digits list [0-9].

  3. DateTime 4 microseconds since epoch substring 8 - 12 because they change frequently.

  4. Last 4 Alphabets from an alphabets list [a-z].

Screen Shots of Generated id's:

first generated id second generated id third generated id

A Function to Call

  randomIdGenerator() {
  var ranAssets = RanKeyAssets();
  String first4alphabets = '';
  String middle4Digits = '';
  String last4alphabets = '';
  for (int i = 0; i < 4; i++) {
    first4alphabets += ranAssets.smallAlphabets[
        math.Random.secure().nextInt(ranAssets.smallAlphabets.length)];

    middle4Digits +=
        ranAssets.digits[math.Random.secure().nextInt(ranAssets.digits.length)];

    last4alphabets += ranAssets.smallAlphabets[
        math.Random.secure().nextInt(ranAssets.smallAlphabets.length)];
  }

  return '$first4alphabets-$middle4Digits-${DateTime.now().microsecondsSinceEpoch.toString().substring(8, 12)}-$last4alphabets';
}

Class for list

    class RanKeyAssets {
  var smallAlphabets = [
    'a',
    'b',
    'c',
    'd',
    'e',
    'f',
    'g',
    'h',
    'i',
    'j',
    'k',
    'l',
    'm',
    'n',
    'o',
    'p',
    'q',
    'r',
    's',
    't',
    'u',
    'v',
    'w',
    'x',
    'y',
    'z'
  ];
  var digits = [
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
  ];
}
Osama Buzdar
  • 1,115
  • 10
  • 20
1

If you like MongoDB style ids you could consider this small package that will help create the object id:

https://pub.dev/packages/crossplat_objectid

import 'package:bson_objectid/bson_objectid.dart';

main() {
  ObjectId id1 = new ObjectId();
  print(id1.toHexString());

  ObjectId id2 = new ObjectId.fromHexString('54495ad94c934721ede76d90');
  print(id2.timestamp);
  print(id2.machineId);
  print(id2.processId);
  print(id2.counter);
}
34m0
  • 5,755
  • 1
  • 30
  • 22
1

There is also https://pub.dev/packages/xid which is lock free and has a Unicity guaranteed for 16,777,216 (24 bits) unique ids per second and per host/process

import 'package:xid/xid.dart';

void main() {
  var xid = Xid();
  print('generated id: $xid');

}
Bwire
  • 1,181
  • 1
  • 14
  • 25