星期六

Firebase用户中的多种状态与其转换的测试

在FirebaseAuth中应用中用户形态大致被分为3种:有信息用户、匿名用户(默认用户)、未登陆
  • 在未登录时获取的user总是为null
  • 在匿名用户时,获取头像url等将被返回null
  • 在匿名用户时,历遍user.providerData将只有一个厂商为firebase的关联账户
在用户形态中互相转换也需要注意:
  • 从未登录转到有信息用户(虽然未尝试,但理所当然是会创建新的ID进行登录)
  • 从匿名用户转到有信息用户
    • 当有信息用户曾经登录时,匿名用户将会被登出并更换为有信息用户
    • 经测试,当有信息用户是新用户时,仍然会创建新的用户ID进行登录,正在寻找此解决方案。(此时所利用的是 _auth.signInWithCredential(credential)  进行的用户登录
    • 经过进一步测试,如果是需要从匿名用户转到有信息用户的话,必须从现在匿名用户的user中的linkWithCredential(credential) 成员进行转换
    • 匿名用户的user中的linkWithCredential(credential) 成员进行转换到已经有信息的账号时,将会弹出一个错误:出现异常:PlatformException (PlatformException(ERROR_CREDENTIAL_ALREADY_IN_USE, This credential is already associated with a different user account., null))
  • 当登出时,进入未登录状态,匿名用户若未链接,可能此用户被飘在虚无中
  • 当从未登录进入匿名用户时,创建一个新的匿名用户进行登录
顺带一提,在有信息用户内的 providerData 是这样的:{firebase:<uid> , google.com: <谷歌的专有ID:如123456...>} 而在应用中获取的uid是firebase的。如果是匿名用户,则内部是这样的:{firebase:<uid>}
如果考虑到Firebase有信息用户异常的形态时,或许有以下几种情况:
  • 在登录状态时,在其他设备发生密码修改的操作。
  • 在登录状态时,该用户被删除或删除。
  • 在已经绑定某服务商时,在其他设备实施解绑操作。
在Firebase用户管理中可以对Firebase有信息用户进行以下三项设置:
接下来将进行测试

  • 删除Firebase有信息用户账号时
    • 在删除账号时,实时数据库的数据并不会删除,这是可以预想到的。而这可能会产生数据的沉余。
    • 在删除账号后,客户端并不会发生错误、自动掉线等,用户仍能正常使用,实时数据库数据也能正常读取。
    • 在删除用户后,客户端重新调用登录用户时,并不会跳出请求登录页面,而是自动利用服务商来生成一个新的Firebase有信息用户,此时的用户ID不再是之前删除的用户ID了。再读取数据时也发现数据为空。
  • 停用Firebase有信息用户账号时
    • 在停用账号后,客户端并没有什么反应,数据也能读取。
    • 在停用账号后再从新登陆时,客户端发生错误:出现异常。PlatformException (PlatformException(ERROR_USER_DISABLED, The user account has been disabled by an administrator., null))
    • 此错误发生在://用凭据进行登录
    • var result =await _auth.signInWithCredential(credential);   行中,返回的result也为null
    • 启用账户后从新登陆将如旧运行。





星期一

Flutter中利用Firebase进行数据保存

这次我们要利用的是Firebase中的RealTimeDatabase讲成中文就是【实时数据库】,在Firebase中实时数据库是json式的带镶嵌的数据保存格式,最多可保存32层,如果使用用户认证那一般会用去两层,剩下30层。当然官网建议使用扁平式数据结构,应注意层级划分。
那么就让我们进控制台看看吧:

控制台上我刚从程序中将一些测试数据上传上去,下面是如何用Flutter进行数据的上传和查看:
首先从https://pub.dev/packages/firebase_database连接所需的包资源到应用,步骤如下:
  1. 在控制台设置连接规则,可以设置用户权限如图。
  2. 使用 FirebaseDatabase.instance.reference() 来进行连接并获取根目录。
  3. 获得目录后使用 child 来进入子目录
  4. 在目录中调用once函数来进行获取目录中的数据
  5. 调用onChildentChange的listen来进行侦听数据的变更
值得一提的是这个数据库有离线储存,在线自动同步的功能,所以有那部分需求的人的代码可以省略很多,而且我监测这功能时发现在离线时程序仍然能够侦听数据的变更(如果数据在程序其它部位发出更改),这是不是很高级?


顺带一提这里我把它进行了一个简单的封装,相信一看你就能知道怎么用这个插件了。


星期三

flutter中利用firebase实现登录方案

firebase中集成了许多的常用功能,甚至让开发者可以在只有客户端的情况下实现一个完整的应用程序,但这仍然是比较新颖的方案,而且收费也许不合部分开发者的胃口,所以网上并没太多的讲解,特别是对于flutter的。
在dart的包库中已经实现了许多对firebase功能的提供
我建议对这方面的学习是:边参照firebase上的安卓或者iOS的说明,边查找dart包中的对应关键字,通常他们会在两边起同样的名字以使开发者便利。

这次是简单说下如何来实现flutter上的谷歌登录:
首先,创建一个登陆页面,然后在上面放个button,ontap进入以下的代码块:
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  final FirebaseAuth _auth = FirebaseAuth.instance;  
Future<FirebaseUser> _handleSignIn() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user = (await _auth.signInWithCredential(credential)).user;
print("signed in " + user.displayName);
return user;
}
就是这样

星期日

flutter的flutter setstate after dispose 错误来源

会点英语的人会知道flutter setstate after dispose 这句话的意思。
它的意思是说,你在dispose后调用setstate,在我发生这个错误时是在使用tab控件时发生的。
如下图所示
当我在SQL时直接点击history,这时会经过收藏页面,而触发收藏页面的init,而我在init中放了一个延时的setstate说到这了,我想你都知道是什么回事了吧。
到最后我是这样解决的:
        if(this.mounted){//防止flutter setstate after dispose错误
setState(() {});
}

flutter出现的奇妙bug,既不弹错误也不触发函数,直接跳回主页面

在一次的开发中,我使用push和pop来进行页面跳转,一开始安然无恙,但后来由于项目格局逐渐庞大,某些代码需要移动到其它地方才能让项目代码更加明了:

是这样的:
这个多tab中外层是一个stateful而四个内层也分别是stateful,而跳转代码要从外层中搬到了内层中。
结果搬动后发生了意想不到的错误。
点击右上角的加号跳转到另一个页面后再按返回时,竟然直接跳到主页面去了。不报错,不跳到返回键的函数中,这个问题我苦恼了挺久的,在走路回家时就想会不会是context的问题呢?

其实我对context的理解也不是很深,但既然跳转时要利用到它,而我们在更换代码位置时,虽然没有改到代码,但事实上是context受到了改变,而在跳转到第二个页面时,第一个页面可能遭到刷新,而导致所有的子satateful的tab遭到删除,而导致所使用的context没了还是什么的,想来想去果然如此,一修改果然就好了。
果然有时候当场修不好的bug要放松下大脑重新思考才行啊。

星期五

SQLite数据库中怎么获取主键的名称

表有主键,常称为id,但也有不属常者,何以寻其出?
try{
var tableData = await _getRows("pragma table_info ('$table')");
for(var i in tableData){
if(i['pk'] == 1){
    _idFieldName[table] =i['name'];
    return _idFieldName[table];
}
}
}catch(e){
Fluttertoast.showToast(msg: e.toString());
}
如上所示,于Flutter中的dart代码,输入因有table而已。
主要为以下的SQL代码所产生的作用。
pragma table_info ('$table')

愿大众习得码之智慧,风云于世间风云之上。

遗产

遗产,您可以在随后的退位中解锁和购买

要解锁他们,您需要解锁该派系的冠军奖杯,这需要购买该派系的每个派系升级一旦解锁,它的价格将在Faction Coins中,具体数字取决于派系的等级:Vanilla,5000;中立,两个派系25000;威望75000; 雇佣兵,每人100000。

名称成本解锁要求影响
公平遗产
童话遗产5000仙子硬币童话冠军奖杯您拥有的农场,旅馆和铁匠将所有建筑物的生产量提高0.075%。
精灵遗产
精灵遗产5000精灵币精灵冠军奖杯找到派系硬币的机会增加5%,并根据找到派系硬币的机会增加点击奖励。

式: / 2   x是您找到派系硬币的机会。

天使遗产
天使遗产5000天使硬币天使冠军奖杯魔力回复提高10%。
妖精传承
地精遗产5000哥布林硬币地精冠军奖杯根据您拥有宝石数量来增加所有建筑物的产量

式: Fø ø - [R 7.5 ö   其中x是您拥有的宝石数量。

脱遗产
亡灵遗产5000枚亡灵硬币亡灵冠军奖杯您会根据在游戏中花费的时间获得更多的助手

式: Fø ø - [R 1.5 *X0.5  其中x是您的游戏时间(本游戏)统计信息(以小时为单位)。

妖魔化
恶魔遗产5000恶魔币恶魔冠军奖杯使您拥有的每个传奇大厅的所有建筑物的生产量提高0.3%。
泰坦传承
泰坦遗产25,000个天使硬币,25,000个地精硬币泰坦冠军奖杯皇家交易所的生产奖金各增加15%。
德鲁伊遗产
德鲁伊遗产25,000精灵币,25,000恶魔币德鲁伊冠军奖杯每拥有15座建筑物,最大法力值增加1。
不露面的遗产
不露面的遗产25,000仙灵硬币,25,000不死硬币不露面冠军奖杯根据一次游戏中购买的最高建筑物数量来增加所有建筑物的生产量。

式: 0.25 *X0.75  其中x是您的建筑物拥有(最大)统计信息。

矮人遗产
矮人遗产75,000矮人币矮人冠军奖杯,黑社会外交根据发掘的数量增加所有建筑物的生产量

式: X0.9  其中x是您已购买的挖掘数量。

众议院遗产
卓尔传统75,000卓尔币卓尔冠军奖杯,冥界外交根据您在此游戏中购买的皇室往来数量增加助理的产量。

式: *X0.8  其中x是您的Royal Exchanges Made(此游戏)统计信息。

雇佣徽章
雇佣徽章每个派系硬币100,000地下世界外交佣兵冠军奖杯根据您在单个游戏中获得的最高硬币数量来提高所有建筑物的生产量。

式: Fg  其中x是您的“获得的硬币(最大)”统计。

龙传承传承400 B(4 E 11)矮人和卓尔硬币龙冠军奖杯,冥界外交根据与Dragons关联的时间增加助理制作。

式: 0.55 *X0.55  其中x是在所有R上与龙相关的小时数。

先进遗产

名称成本解锁要求影响
公平遗产
先进的童话遗产7.5 Oc(7.5e27)仙子硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据农场,旅馆和铁匠(添加剂)的数量获得助手。

公式:(2 *(x + y + z)^ 0.8),其中x是农场数量,y是客栈数量,z是铁匠数量。

精灵遗产
高级精灵遗产7.5 Oc(7.5e27)精灵币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据在此轮回中获得的点击次数,成倍增加派系硬币的发现机会。

公式:(0.3 * ln(1 + x)^ 1.5)%,其中x是此轮回的点击次数。

天使遗产
先进的天使遗产7.5 Oc(7.5e27)天使硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据在此游戏中施放的咒语数量提高法力回复。

公式:(2.5 * x ^ 0.25)%,其中x是施放此游戏的咒语。


妖精传承
先进的地精遗产7 Oc(7.5 E 27)哥布林硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据所拥有的宝石,征税会花更多的时间进行生产。

公式:(0.25 * log(1 + x)^ 0.95),其中x是拥有的宝石。

脱遗产
先进的亡灵遗产7 Oc(7.5 E 27)亡灵硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据您的离线赠金,Assistact的数量更多。公式:(0.018 * ln(1 + x)^ 2)%,其中x是离线奖金乘数。
妖魔化
先进的恶魔遗产7.5 Oc(7.5e27)恶魔币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯 基于解锁的奖杯增加所有建筑物的生产。

公式:(0.25 * x ^ 0.75)%,其中x是解锁的奖杯数量。

泰坦传承
进阶泰坦遗产7 Oc(7.5 E 27)天使硬币,7 Oc(7.5 E 27)地精硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据购买的皇家交易所的数量增加最大法力值。

公式:(0.2 * ln(x)^ 1.5)%,其中x是购买的皇家交易所。

德鲁伊遗产
先进的德鲁伊传承7 Oc(7.5 E 27)精灵币,7 Oc(7.5 E 27)恶魔币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据您所有法术持续时间的总和成倍增加派系硬币的发现机会。

公式:(0.01 * x ^ 0.85)%,其中x是您所有法术持续时间的总和。

不露面的遗产
先进的不露面遗产7 Oc(7.5 E 27)仙子硬币,7 Oc(7.5 E 27)亡灵硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据拥有的唯一建筑物(添加)的数量获得助手。

公式:(2.5 * x ^ 0.8),其中x是拥有的唯一建筑物。


矮人遗产
矮人高级遗产7.5 Oc(7.5e27)矮人硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯基于挖掘和挖掘重置的数量增加了所有建筑物的产量(此R)。

公式:(0.01 * x ^(0.85 + 0.01 * y)),其中x为开挖,y为开挖重置此R(红宝石和自由重置)。

众议院遗产
高级卓尔遗产7 Oc(7.5 E 27)卓尔硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯根据离线奖励和在游戏中花费的时间,增加所有建筑物的生产量。

公式:(0.0008 * log10(1 + x)* y ^ 0.8),其中x离线奖励和y是花费在此游戏上的时间。

龙传承先进的传承7.5 Oc(7.5e27)矮人和卓尔硬币需要8小时的派系法术活动时间才能解锁。使用各自的血统时,高级传承力量乘以血统等级。需要种族大师奖杯出于所有目的,有效咒语的数量增加5%。

Firebase用户中的多种状态与其转换的测试

在FirebaseAuth中应用中用户形态大致被分为3种:有信息用户、匿名用户(默认用户)、未登陆 在未登录时获取的user总是为null 在匿名用户时,获取头像url等将被返回null 在匿名用户时,历遍user.providerData将只有一个厂商为firebase的关联账...