I am attempting to convert an old flutter code to a null safety code and encounter a problem with an abstract authentication class using firebase, basically its listening to a authStateChange
abstract class AuthBase {
User get currentUser;
Stream<User> authStateChanges();
....
}
class Auth implements AuthBase {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
#override
Stream<User> authStateChanges() => _firebaseAuth.authStateChanges();
But after running the code it returns A value of type 'Stream<User?>' can't be returned from the method 'authStateChanges' because it has a return type of 'Stream<User>'. error
so what i did was cast it
#override
Stream<User> authStateChanges() => _firebaseAuth.authStateChanges() as Stream<User>;
But now i encounter a new problem type '_AsBroadcastStream<User?>' is not a subtype of type 'Stream<User>' in type cast any advice on how to address this.
_firebaseAuth.authStateChanges()
will give User or null so need to make it nullable as
Stream<User?> authStateChanges() => _firebaseAuth.authStateChanges() as Stream<User?>;
and also need to change in the base class as well as same.
Related
I'm currently working on a simple project crypto_wallet. State management (BLoC) and Value Equality (freezed) creating CRUD operation of DB (Firebase) and in the watch method, I use StreamSubcription code is :
#injectable
class CoinWatcherBloc extends Bloc<CoinWatcherEvent, CoinWatcherState> {
final ICoinRepository _repository;
CoinWatcherBloc(this._repository, this._coinStreamSubscription) :
super(CoinWatcherState.initial());
StreamSubscription<Either<CoinFailure, KtList<CoinEntity>>>? _coinStreamSubscription;
#override
Stream<CoinWatcherState> mapEventToState(CoinWatcherEvent event) async* {
yield* event.map(
watchCoin: (e) async* {
yield CoinWatcherState.loadInProgress();
await _coinStreamSubscription?.cancel();
_coinStreamSubscription = _repository.watchCoin().listen(
(failureOrSuccess) => add(
CoinWatcherEvent.coinsReceived(failureOrSuccess),
),
);
},
coinsReceived: (e) async* {
yield e.failureOrCoin.fold(
(f) => CoinWatcherState.loadFailure(f),
(coin) => CoinWatcherState.loadSuccess(coin),
);
},
);
}
#override
Future<void> close() async {
await _coinStreamSubscription?.cancel();
return super.close();
}
}
And at last I closed the stream. I inject all third party modules on #lazySingleton :
#module
abstract class FirebaseInjectableModule {
#lazySingleton
FirebaseAuth get firebaseAuth => FirebaseAuth.instance;
#lazySingleton
FirebaseFirestore get firebaseFirestore => FirebaseFirestore.instance;
#lazySingleton
GoogleSignIn get googleSignIn => GoogleSignIn();
}
Then It says :
Object/factory with type StreamSubscription<Either<CoinFailure, KtList<CoinEntity>>> is not
registered inside GetIt.
(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;
Did you forget to register it?)
If I also register this class like this.
#lazySingleton
StreamSubcription get streamSubcription => StreamSubcription();
Then it throws compile time error that abstract classes can't be instantiated like the all Third Party Classes I've registered. How to inject abstract classes? Is there any other way to do this? or I shouldn't use StreamSubcription something else? I'd be thankful <3 :)
You should not add this._coinStreamSubscription to your bloc's constructor. Remove it from the constructor, and declare it as a late final instance.
class CoinWatcherBloc extends Bloc<CoinWatcherEvent, CoinWatcherState> {
final ICoinRepository _repository;
CoinWatcherBloc(this._repository) :
super(CoinWatcherState.initial());
late final StreamSubscription<Either<CoinFailure, KtList<CoinEntity>>>? _coinStreamSubscription;
get_it was trying to inject the abstract streamSubscription since it is in your constructor. And you do not need this. Also, if you look at it from a testing perspective, there is no need to mock the streamSubscription, you can instead mock the class that supplies data to it - which is the repository in this case
I generally just inject the implementation of the abstract class like
#LazySingleton(as:AbstractClass).
I am writing a Firestore Model abstract class that handles common operations. Each model matches a collection in Firestore... I want to refer to that both from a create instance and before the instance exists. But I can't make collectionPath static because I can't override static methods, variables, getters, etc... I get that.
Could create an instance as needed maybe Model().collectionPath but I couldn't get that to work.
Is there a way to do this? How are others making these types of Models?
This is what I'm trying to do:
abstract class Model {
String get collectionPath => "";
void create() async {
CollectionReference collection = FirebaseFirestore.instance.collection(this.collectionPath);
this.reference = await collection.add(this.toMap());
}
static Stream<QuerySnapshot> snapshots() {
return FirebaseFirestore.instance.collection(this.collectionPath).snapshots();
}
//...
class User extends Model {
String get collectionPath => "users";
//...
I want to be able add an existing instance to the firestore:
User user = User("Values");
user.create();
And I'd also like to load all the users before I've created any particular one:
Widget _buildBody(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: User.snapshots(),
I am a beginner of programming and dart lang. I have a question about how to write class about database service related to flutter and firestore.
// what is the difference this
class DbService {
final Firestore _db;
DbService() : _db = Firestore.instance;
Future<QuerySnapshot> getDataCollection(String id) {
return _db.collection(id).getDocuments();
}
}
// and this
class DbService {
final Firestore _db = Firestore.instance;
Future<QuerySnapshot> getDataCollection(String id) {
return _db.collection(id).getDocuments();
}
}
// when use this class
_dbService = DbService();
What is the best practice. or should I use singleton to instantiate this class? Any comments or help is appreciate.
They are the same for computer, but they give me different impression.
2nd one is obvious, where 1st one telling me the constructor used to take value, or may be take value in future version.
I already solved this problem, but I would like to understand why it occurred in the first place:
1. I'm using the Java template of Tokens SDK
2. I created my own token type
3. I modified ExampleFlowWithFixedToken class to issue my new token
4. When I ran start ExampleFlowWithFixedToken amount: 100, recipient: PartyB, I got the error: There is a token group with no assigned command
5. Initially my new token class didn't implement the equals() method, when I added it; the error was gone and I was able to issue my token.
Why adding that method, fixes the problem?
public class MyTokenType implements TokenType {
private final int fractionDigits = 6;
private final String tokenIdentifier = "MY_TOKEN";
#NotNull
#Override
public BigDecimal getDisplayTokenSize() {
return BigDecimal.ONE.scaleByPowerOfTen(-fractionDigits);
}
#Override
public int getFractionDigits() {
return fractionDigits;
}
#NotNull
#Override
public Class<?> getTokenClass() {
return this.getClass();
}
#NotNull
#Override
public String getTokenIdentifier() {
return tokenIdentifier;
}
#Override
public boolean equals(Object obj) {
return obj instanceof MyTokenType;
}
}
ExampleFlowWithFixedToken calls the built-in IssueTokens Flow.
This flow , builds the transaction internally specifying input, output states, commands(IssueCommand in this case).
Next step is to verify the contract.
Before verifying the contracts we group the input/output tokens by the issuer.
Each group is then assigned a token command.
This is done because if a transaction contains more than one type of token, they need to grouped by IssuedTokenType.
Also note same token type issued by different issuers are not fungible.
Hence the grouping by IssuedTokenType is required.
Once we have the groups by IssuedTokenType, contract verification is done separately for each group.
When we try to assign a token command to each group , we compare the IssuedTokenType in command to one in our groups.
So if we dont override equals method, none of the IssuedTokenType from the groups will match to the one in the TokenCommand.
Hence the group will not be assigned any TokenCommand.
Each group should at least have one command. If there isn’t then we would not know what to do with that group. Hence it fails saying "There is a token group with no assigned command"
Hope that helps!
Having an asynchronous function that doesn't return a value, what's the ideal return type Future<Null> or Future<void>?, or more specifically, what's the difference in using either? Both are legal, and in both cases the return value of the function is a Future that resolves to null. The following code prints null two times:
import 'dart:async';
Future<void> someAsync() async {}
Future<Null> otherAsync() async {}
main() {
someAsync().then((v) => print(v));
otherAsync().then((v) => print(v));
}
The type Null only allows the value null
The type void allows values of any type, but communicates that the value shouldn't be used.
It's not yet clear to me how tools support will treat void. There will probably linter rules that hint or warn at using void values.
Null was used instead of void previously because void was only supported as return type of methods/functions.