Flutter實戰一Flutter聊天應用(六)
我們將使用Google登入來驗證應用程式的使用者。Google登入功能可讓使用者使用其Google帳戶(與Gmail、Play、照片和其他Google服務所使用的帳戶相同的帳戶)進行安全登入。我們還可以根據與使用者的Google帳戶相關聯的個人資料和身份資訊,個性化使用者體驗。使用者登入後,我們可以使用個人資料照片個性化聊天訊息頭像。
要新增對Google登入的支援,我們將使用google_sign_in
外掛,在main.dart
檔案中匯入相應的包。
import 'package:google_sign_in/google_sign_in.dart';
要啟用Google登入,需要在瀏覽器中開啟Firebase控制檯並選擇我們的專案。導航到Authentication > 登陸方法
要在iOS上配置Google登入,需要確保生成的GoogleService-Info.plist
檔案位於Xcode中Runner專案的Runner目錄中,因此Google登入框架可以確定您的客戶端ID。將客戶端ID的捆綁ID和反向URL新增到應用的Info.plist
檔案的主要字典中:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string >Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<!-- 反轉客戶端ID的URL -->
<string>com.googleusercontent.apps.462578386393-kisbgopib3t6plf4dgv3s0n4ur3svjmo</string>
<!-- 捆綁ID -->
<string>com.yourcompany.friendlychat</string >
</array>
</dict>
</array>
我們可以在GoogleService-Info.plist
檔案中找到客戶端ID的反向URL,複製REVERSED_CLIENT_ID
字串的值並貼上以將其新增到CFBundleURLSchemes
。當用戶登入到應用程式時,此URL型別將處理回撥。
第一次啟動應用程式時,可能需要一兩分鐘才能啟動。在iOS上,需要額外的時間來初始化Cocapods repo,而在Android上,需要下載maven的依賴關係。在下一組更改之後,我們將能夠重新載入應用程式,並且開發週期將快得多。
現在我們的應用程式僅限於單個使用者和裝置,當用戶傳送訊息時,應用程式將其標記為_name
變數的值,並將其顯示在同一個螢幕上,頭像是一個簡單的彩色圓圈。我們現在需要做的是,多個使用者將能夠通過實時資料庫共享訊息。為了有利於擴充套件應用程式,我們將個性化頭像以區分使用者。由於我們將擁有發件人的Google登入憑據,因此我們可以重用使用者的個人資料照片。我們將在稍後的步驟中新增資料庫支援。
首先,新增一個名為googleSignIn
的全域性變數,使用新的GoogleSignIn
例項初始化它,我們將用它來呼叫Google登入API。在main.dart
檔案新增以下程式碼。
final googleSignIn = new GoogleSignIn();
現在定義兩個私有方法,一個用於登入,另一個用於傳送訊息。新增_ensureLoggedIn()
方法來檢查GoogleSignIn
例項的currentUser
屬性。在ChatScreenState
中新增_ensureLoggedIn()
方法定義。
class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
Future<Null> _ensureLoggedIn() async {
GoogleSignInAccount user = googleSignIn.currentUser;
if (user == null)
user = await googleSignIn.signInSilently();
if (user == null) {
await googleSignIn.signIn();
}
}
//...
}
以前的程式碼片段使用多個等待表示式依次執行Google登入方法。如果currentUser
屬性的值為null
,應用程式將首先執行signInSilently()
,獲取結果並將其儲存在user
變數中。signInSilently
方法嘗試在沒有互動的情況下登入之前經過身份驗證的使用者。此方法執行完畢後,如果user
值仍為null
,則應用程式將通過執行signIn()
方法啟動登入過程。使用者登入後,我們可以從GoogleSignIn
例項訪問配置檔案照片。
現在提交訊息的過程有兩步,認證和傳送。我們需要協調工作,以便首先認證,如果成功,那麼使用者可以傳送訊息。首先,將_handleSubmitted
方法從ChatScreenState
拆分為兩種單獨的方法。而不是在_handleSubmitted()
中執行所有提交的工作,我們將使用它來協調其他方法執行的任務,例如驗證使用者是否登入併發送訊息。
在_handleSubmitted()
中保留_textController.clear()
和setState()... _isComposing
方法呼叫。新增_ensureLoggedIn()
和_sendMessage()
呼叫,如下面程式碼所示。
class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
Future _handleSubmitted(String text) async {
_textController.clear();
setState((){
_isComposing = false;
});
await _ensureLoggedIn();
_sendMessage(text: text);
}
//...
}
修改_handleSubmitted()
的簽名,表示它是一個不返回任何內容的非同步方法。在嘗試傳送訊息之前,將呼叫新增到await _ensureLoggedIn()
以等待使用者驗證成功。現在我們來定義_sendMessage()
,將_handleSubmitted()
的其餘部分新增到新的私有方法中。我們將使text
成為一個命名引數,以便稍後可以向_sendMessage
新增更多的String
引數。
class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
//...
void _sendMessage({ String text }) {
ChatMessage message = new ChatMessage(
text: text,
animationController: new AnimationController(
duration: new Duration(milliseconds: 300),
vsync: this
)
);
setState((){
_messages.insert(0, message);
});
message.animationController.forward();
}
//...
}
為了個性化頭像,我們在ChatMessage
類的build()
方法中使用新的GoogleUserCircleAvatar
物件替換CircleAvatar
控制元件,以及其Text
控制元件。CircleAvatar
可以使用網路影象,但是GoogleUserCircleAvatar
幫助器類可以輕鬆地從GoogleSignIn
例項獲取正確大小的配置檔案照片。google_sign_in.dart
外掛定義了這個類。
class ChatMessage extends StatelessWidget {
//...
@override
Widget build(BuildContext context) {
return new SizeTransition(
//...
child: new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
margin: const EdgeInsets.only(right: 16.0),
child: new GoogleUserCircleAvatar(googleSignIn.currentUser.photoUrl),
),
//...
]
)
)
);
}
}
currentUser
屬性是身份驗證物件,我們使用photoUrl
獲取新頭像的影象。現在,我們需要個性化顯示使用者名稱。以前,我們使用硬編碼顯示使用者名稱。現在我們已經集成了Google登入,我們可以刪除_name
全域性變數。改成從已登入的Google使用者處獲取使用者名稱。在ChatMessage
類中使用來自GoogleSignIn
例項的displayName
設定_name
變數。
class ChatMessage extends StatelessWidget {
//...
@override
Widget build(BuildContext context) {
return new SizeTransition(
//...
child: new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//...
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
googleSignIn.currentUser.displayName,
style: Theme.of(context).textTheme.subhead),
new Container(
margin: const EdgeInsets.only(top: 5.0),
child: new Text(text),
)
]
)
]
)
)
);
}
}
現在,當我們傳送訊息時,頭像和發件人姓名與您的Google帳戶中的個人資料資訊相匹配。隨著我們繼續進行更改並優化應用程式的UI,我們可以快速檢視結果,而不需要重新啟動完整的應用程式。使用Flutter的熱重新載入功能將更新的原始檔注入正在執行的Dart虛擬機器(Dart Virtual Machine)並重新整理UI。熱過載是實驗、原型設計和迭代的強大工具。