apeescape2.com
  • メイン
  • エンジニアリング管理
  • ライフスタイル
  • 人とチーム
  • デザイナーライフ
モバイル

Flutterチュートリアル:最初のFlutterアプリを作成する方法

Flutterとは何ですか?

FlutterはGoogleのモバイルアプリ開発SDKであり、2つの別々のコードベースを維持することなく、AndroidプラットフォームとiOSプラットフォームの両方を同時にターゲットにすることができます。さらに、Flutterを使用するアプリは、Googleの今後のターゲットに合わせてコンパイルすることもできます Fuchsiaオペレーティングシステム 。

Flutterは最近、主要なマイルストーンである安定バージョン1.0に到達しました。リリースは、2018年12月5日にロンドンで行われました。 Flutterライブイベント 。それはまだ初期の進化するソフトウェアベンチャーと見なすことができますが、この記事では、すでに実証済みの概念に焦点を当て、を使用して両方の主要なモバイルプラットフォームを対象とする完全に機能するメッセージングアプリを開発する方法を示します フラッター1.2 そして Firebase 。

下のグラフからわかるように、Flutterはここ数か月で多くのユーザーを獲得しています。 2018年、Flutterの市場シェアは2倍になり、検索クエリの点でReact Nativeを上回る軌道に乗っているため、新しいFlutterチュートリアルを作成することにしました。



2018年7月から9月までのFlutterユーザーとReactユーザーを比較したグラフ。

注意: この記事では、実装の特定の部分にのみ焦点を当てています。プロジェクトの完全なソースコードリファレンスは、にあります。 このGitHubリポジトリ 。

前提条件

モバイル開発の最初の試みであっても、読者がこのプロジェクトをフォローして達成できるように努力しましたが、Flutter固有ではない多くのコアモバイル開発の概念が言及され、詳細な説明なしで使用されています。

その目的の1つは読者が一度にプロジェクトを完了することであるため、これは記事の簡潔さのために行われました。最後に、この記事では、必要なAndroidStudioプラグインやFlutterSDKなど、開発環境が既にセットアップされていることを前提としています。

Firebaseのセットアップ

プラットフォームごとに個別に行う必要があるのは、Firebaseの設定だけです。まず、で新しいプロジェクトを作成することを確認してください Firebaseダッシュボード 新しく生成されたワークスペースにAndroidおよびiOSアプリケーションを追加します。プラットフォームは、ダウンロードする必要のある2つの構成ファイルを生成します:google-services.json AndroidおよびGoogleService-Info.plistの場合iOS用。ダッシュボードを閉じる前に、FirebaseとGoogleの認証プロバイダーを有効にしてください。ユーザーの識別に使用します。これを行うには、メニューから[認証]項目を選択し、[サインイン方法]タブを選択します。

これで、残りのセットアップがコードベースで行われるので、ダッシュボードを閉じることができます。まず、ダウンロードしたファイルをプロジェクトに配置する必要があります。 google-services.jsonファイルは$(FLUTTER_PROJECT_ROOT)/android/appに配置する必要がありますフォルダとGoogleService-Info.plist $(FLUTTER_PROJECT_ROOT)/ios/Runnerに配置する必要がありますディレクトリ。次に、プロジェクトで使用するFirebaseライブラリを実際に設定し、構成ファイルに接続する必要があります。これは、プロジェクトのpubspec.yamlで使用するDartパッケージ(ライブラリ)を指定することによって行われます。ファイル。ファイルの依存関係セクションに、次のスニペットを貼り付けます。

flutter_bloc: shared_preferences: firebase_auth: cloud_firestore: google_sign_in: flutter_facebook_login:

最初の2つはFirebaseとは関係ありませんが、プロジェクトで頻繁に使用されます。最後の2つは、うまくいけば、自明です。

最後に、認証フローを正常に完了することができるように、プラットフォーム固有のプロジェクト設定を構成する必要があります。 Android側では、プロジェクトレベルのGradle構成にgoogle-servicesGradleプラグインを追加する必要があります。つまり、$(FLUTTER_PROJECT_ROOT)/android/build.gradleの依存関係リストに次の項目を追加する必要があります。ファイル:

classpath 'com.google.gms:google-services:4.2.0' // change 4.2.0 to the latest version

次に、この行を$(FLUTTER_PROJECT_ROOT)/android/app/build.gradleの末尾に追加して、そのプラグインを適用する必要があります。

最高のc ++チュートリアル
apply plugin: 'com.google.gms.google-services'

このプラットフォームの最後のことは、Facebookアプリケーションのパラメーターを登録することです。ここで探しているのは、これら2つのファイルを編集することです-$(FLUTTER_PROJECT_ROOT)/android/app/src/main/AndroidManifest.xmlおよび$(FLUTTER_PROJECT_ROOT)/android/app/src/main/res/values/strings.xml:

ApeeScape Chat ${YOUR_FACEBOOK_APP_ID} ${YOUR_FACEBOOK_URL}

さあ、iOSの時間です。幸い、この場合、変更する必要があるのは1つのファイルだけです。次の値をCFBundleURLTypesに追加します($(FLUTTER_PROJECT)ROOT/ios/Runner/Info.plist項目はリストにすでに存在している可能性があります。その場合、これらの項目を再度宣言するのではなく、既存の配列に追加する必要があります)。ファイル:

CFBundleURLTypes CFBundleURLSchemes ${YOUR_FACEBOOK_URL} CFBundleTypeRole Editor CFBundleURLSchemes ${YOUR_REVERSED_GOOGLE_WEB_CLIENT_ID} FacebookAppID ${YOUR_FACEBOOK_APP_ID} FacebookDisplayName ${YOUR_FACEBOOK_APP_NAME} LSApplicationQueriesSchemes fbapi fb-messenger-share-api fbauth2 fbshareextension

BLoCアーキテクチャに関する一言

このアーキテクチャ標準は、以前の記事の1つで説明されており、 FlutterとAngularDartでのコード共有のためのBLoC なので、ここでは詳しく説明しません。

主なアイデアの背後にある基本的なアイデアは、すべての画面に次のクラスがあるということです。 見る -これは、現在の状態を表示し、ユーザー入力をイベントとしてブロックに委任する役割を果たします。 - 状態 -これは、ユーザーが現在のビューを使用して操作する「ライブ」データを表します。 - ブロック -イベントに応答し、それに応じて状態を更新します。オプションで、1つまたは複数のローカルまたはリモートリポジトリからデータを要求します。 - イベント -これは、現在の状態を変更する場合と変更しない場合がある明確なアクション結果です。

グラフィック表現として、次のように考えることができます。

c ++ファイルをコンパイルする

Flutterチュートリアル:BLoCアーキテクチャのグラフィック表現。

さらに、 モデル これらのクラスのインスタンスを生成するデータクラスとリポジトリを含むディレクトリ。

UI開発

FLutterを使用したUIの作成は、UIがXMLスキームを使用して構築され、ビジネスロジックコードベースから完全に分離されているAndroidおよびiOSでのネイティブアプリ開発とは対照的に、Dartで完全に行われます。現在の状態に基づいてさまざまなコンポーネント(isLoading、isEmptyパラメーターなど)を使用した比較的単純なUI要素の構成を使用します。 FlutterのUIは、ウィジェット、つまりウィジェットツリーを中心に展開します。ウィジェットは、ステートレスまたはステートフルのいずれかになります。ステートフルなものになると、setState()のときにそれを強調することが重要です現在表示されている特定のウィジェットで呼び出されると(コンストラクターで呼び出すか、破棄した後にランタイムエラーが発生します)、ビルドと描画のパスが次の描画サイクルで実行されるようにスケジュールされます。

簡潔にするために、ここではUI(ビュー)クラスの1つのみを示します。

class LoginScreen extends StatefulWidget { LoginScreen({Key key}) : super(key: key); @override State createState() => _LoginState(); } class _LoginState extends State { final _bloc = LoginBloc(); @override Widget build(BuildContext context) { return BlocProvider( bloc: _bloc, child: LoginWidget(widget: widget, widgetState: this) ); } @override void dispose() { _bloc.dispose(); super.dispose(); } } class LoginWidget extends StatelessWidget { const LoginWidget({Key key, @required this.widget, @required this.widgetState}) : super(key: key); final LoginScreen widget; final _LoginState widgetState; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Login'), ), body: BlocBuilder( bloc: BlocProvider.of(context), builder: (context, LoginState state) { if (state.loading) { return Center( child: CircularProgressIndicator(strokeWidth: 4.0) ); } else { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ ButtonTheme( minWidth: 256.0, height: 32.0, child: RaisedButton( onPressed: () => BlocProvider.of(context).onLoginGoogle(this), child: Text( 'Login with Google', style: TextStyle(color: Colors.white), ), color: Colors.redAccent, ), ), ButtonTheme( minWidth: 256.0, height: 32.0, child: RaisedButton( onPressed: () => BlocProvider.of(context).onLoginFacebook(this), child: Text( 'Login with Facebook', style: TextStyle(color: Colors.white), ), color: Colors.blueAccent, ), ), ], ), ); } }), ); } void navigateToMain() { NavigationHelper.navigateToMain(widgetState.context); } }

残りのUIクラスは同じパターンに従いますが、アクションが異なる可能性があり、状態の読み込みに加えて、空の状態ウィジェットツリーを備えている場合があります。

認証

ご想像のとおり、google_sign_inを使用しますおよびflutter_facebook_loginソーシャルネットワークプロファイルに依存してユーザーを認証するライブラリ。まず、ログイン要求ロジックを処理するファイルにこれらのパッケージをインポートしてください。

import 'package:flutter_facebook_login/flutter_facebook_login.dart'; import 'package:google_sign_in/google_sign_in.dart';

次に、認証フローを処理する2つの独立した部分があります。 1つ目は、FacebookまたはGoogleのサインインリクエストを開始します。

void onLoginGoogle(LoginWidget view) async { dispatch(LoginEventInProgress()); final googleSignInRepo = GoogleSignIn(signInOption: SignInOption.standard, scopes: ['profile', 'email']); final account = await googleSignInRepo.signIn(); if (account != null) { LoginRepo.getInstance().signInWithGoogle(account); } else { dispatch(LogoutEvent()); } } void onLoginFacebook(LoginWidget view) async { dispatch(LoginEventInProgress()); final facebookSignInRepo = FacebookLogin(); final signInResult = await facebookSignInRepo.logInWithReadPermissions(['email']); if (signInResult.status == FacebookLoginStatus.loggedIn) { LoginRepo.getInstance().signInWithFacebook(signInResult); } else if (signInResult.status == FacebookLoginStatus.cancelledByUser) { dispatch(LogoutEvent()); } else { dispatch(LoginErrorEvent(signInResult.errorMessage)); } }

2つ目は、いずれかのプロバイダーからプロファイルデータを取得するときに呼び出されます。ログインハンドラにfirebase_auth onAuthStateChangeをリッスンするように指示することで、これを実現します。ストリーム:

void _setupAuthStateListener(LoginWidget view) { if (_authStateListener == null) { _authStateListener = FirebaseAuth.instance.onAuthStateChanged.listen((user) { if (user != null) { final loginProvider = user.providerId; UserRepo.getInstance().setCurrentUser(User.fromFirebaseUser(user)); if (loginProvider == 'google') { // TODO analytics call for google login provider } else { // TODO analytics call for facebook login provider } view.navigateToMain(); } else { dispatch(LogoutEvent()); } }, onError: (error) { dispatch(LoginErrorEvent(error)); }); } }

UserRepoおよびLoginRepo実装はここに掲載されませんが、お気軽にご覧ください GitHubリポジトリ 完全な参照用。

Flutterチュートリアル:インスタントメッセージングアプリを構築する方法

最後に、興味深い部分に行き着きます。名前が示すように、メッセージはできるだけ速く交換する必要があります。理想的には、これは次のようにする必要があります。 インスタント 。幸いなことに、cloud_firestore Firestoreインスタンスと対話でき、そのsnapshots()を使用できます。リアルタイムで更新を提供するデータストリームを開く機能。私の意見では、すべてのchat_repo startChatroomForUsersを除いて、コードは非常に単純です。方法。両方のユーザーを含む既存のチャットルームがない限り(同じユーザーペアの複数のインスタンスを持ちたくないため)、2人のユーザー用に新しいチャットルームを作成する責任があります。その場合、既存のチャットルームが返されます。

ただし、Firestoreの設計により、現在、ネストされたarray-containsはサポートされていません。クエリ。したがって、適切なデータストリームを取得することはできませんが、追加のフィルタリングを実行する必要があります。このソリューションは、ログインしたユーザーのすべてのチャットルームを取得してから、選択したユーザーも含まれているチャットルームを検索することで構成されます。

Future startChatroomForUsers(List users) async { DocumentReference userRef = _firestore .collection(FirestorePaths.USERS_COLLECTION) .document(users[1].uid); QuerySnapshot queryResults = await _firestore .collection(FirestorePaths.CHATROOMS_COLLECTION) .where('participants', arrayContains: userRef) .getDocuments(); DocumentReference otherUserRef = _firestore .collection(FirestorePaths.USERS_COLLECTION) .document(users[0].uid); DocumentSnapshot roomSnapshot = queryResults.documents.firstWhere((room) { return room.data['participants'].contains(otherUserRef); }, orElse: () => null); if (roomSnapshot != null) { return SelectedChatroom(roomSnapshot.documentID, users[0].displayName); } else { Map chatroomMap = Map(); chatroomMap['messages'] = List(0); List participants = List(2); participants[0] = otherUserRef; participants[1] = userRef; chatroomMap['participants'] = participants; DocumentReference reference = await _firestore .collection(FirestorePaths.CHATROOMS_COLLECTION) .add(chatroomMap); DocumentSnapshot chatroomSnapshot = await reference.get(); return SelectedChatroom(chatroomSnapshot.documentID, users[0].displayName); } }

また、同様の設計上の制約により、Firebaseは現在、特別なFieldValue.serverTimestamp()を使用した配列の更新(既存の配列フィールド値への新しい要素の挿入)をサポートしていません。値。

資本予算は、以下を分析するプロセスです。

この値は、実際の値の代わりにこれを含むフィールドに、トランザクションが発生した時点でのサーバー上の実際のタイムスタンプを入力する必要があることをプラットフォームに示します。代わりに、DateTime.now()を使用しています現在、新しいメッセージシリアル化オブジェクトを作成し、そのオブジェクトをチャットルームのメッセージコレクションに挿入しています。

Future sendMessageToChatroom(String chatroomId, User user, String message) async { try { DocumentReference authorRef = _firestore.collection(FirestorePaths.USERS_COLLECTION).document(user.uid); DocumentReference chatroomRef = _firestore.collection(FirestorePaths.CHATROOMS_COLLECTION).document(chatroomId); Map serializedMessage = { 'author' : authorRef, 'timestamp' : DateTime.now(), 'value' : message }; chatroomRef.updateData({ 'messages' : FieldValue.arrayUnion([serializedMessage]) }); return true; } catch (e) { print(e.toString()); return false; } }

まとめ

明らかに、私たちが開発したFlutterメッセージングアプリは、市場に対応したインスタントメッセージングアプリケーションというよりも、概念実証に近いものです。さらなる開発のアイデアとして、エンドツーエンドの暗号化またはリッチコンテンツ(グループチャット、メディア添付ファイル、URL解析)の導入を検討することができます。ただし、その前に、インスタントメッセージングアプリケーションに必須の機能であるプッシュ通知を実装する必要があります。簡潔にするために、プッシュ通知はこの記事の範囲外に移動しました。さらに、Firestoreには、ネストされたarray-containsのように、より単純で正確なデータを取得するためのいくつかの機能がまだありません。クエリ。

記事の冒頭で述べたように、Flutterは最近安定した1.0リリースに成熟し、フレームワークの特徴や機能だけでなく、開発コミュニティやサードパーティのライブラリやサードパーティのライブラリに関しても成長を続けています。リソース。 Flutterアプリの開発に今すぐ慣れるために時間を費やすのは理にかなっています。これは、ここにとどまり、 モバイル開発プロセスをスピードアップ 。

追加費用なしで、 Flutter開発者 また、Googleの新しいOSであるFuchsiaをターゲットにする準備が整います。

関連: Dart言語:JavaとC#が十分にシャープでない場合

基本を理解する

Flutterは何に使用されますか?

Flutterは、AndroidとiOSで実行され、同じユーザーエクスペリエンスを提供するアプリを開発するために使用されます。 Flutterは、Googleの次期OSであるFuchsiaをターゲットにすることもできます。

Flutterはどの言語を使用しますか?

Flutterの開発は、Googleが開発したオープンソースのプログラミング言語であるDartで行われます。

FlutterはReactNativeよりも優れていますか?

FlutterとReactNativeはどちらも同じ結果、クロスプラットフォームアプリを提供しますが、まったく異なるため、どちらかを単に「より良い」と指定することは困難です。文脈から外れた比較はほとんど価値がありません。

FlutterはReactNativeに取って代わりますか?

FlutterはGoogleが所有および開発しているため、リーチが広がり、市場シェアが拡大する可能性があります。現在、2019年末までに開発市場シェアが拡大すると予測されています。ただし、これは、いつでもReactNativeに完全に取って代わることを意味するものではありません。

Dartプログラミング言語は何に使用されますか?

Dartは、ウェブ、サーバー、モバイルアプリを構築するための、堅牢なライブラリとランタイムを備えた、Googleが開発したオープンソースのスケーラブルなプログラミング言語です。

Dartは良い言語ですか?

Dartは、長年にわたって複数の主要な更新を経ており、現在、複数のパラダイムをサポートしています。これにより、非常に堅牢になり、さまざまな製品要件に適しています。

Dartはコンパイル言語ですか?

ダートはこの点で非常にユニークです。 JavaScriptへの変換をサポートします。これは、ジャストインタイムコンパイルを提供するスタンドアロンVMであり、最後に、プラットフォームネイティブ命令セットへの事前コンパイルをサポートします。

タイポグラフィの解剖学の複雑さを分析する(インフォグラフィックを使用)

ツールとチュートリアル

タイポグラフィの解剖学の複雑さを分析する(インフォグラフィックを使用)
デザイン教育の現状に関する専門家の視点

デザイン教育の現状に関する専門家の視点

デザイナーライフ

人気の投稿
Django開発者が犯す間違いトップ10
Django開発者が犯す間違いトップ10
iOSで無限ランナーを構築する方法:Cocos2D、自動化など
iOSで無限ランナーを構築する方法:Cocos2D、自動化など
iOSでT9検索を実装する方法
iOSでT9検索を実装する方法
ASP.NETCoreを使用したASP.NETWebAPIの構築
ASP.NETCoreを使用したASP.NETWebAPIの構築
より良いUXのためのUIスタイルガイドの作成
より良いUXのためのUIスタイルガイドの作成
 
なぜ自社株買いは失敗するのですか?いくつかの提案された救済策
なぜ自社株買いは失敗するのですか?いくつかの提案された救済策
10最も一般的なWebセキュリティの脆弱性
10最も一般的なWebセキュリティの脆弱性
iOSアニメーションと効率のためのチューニング
iOSアニメーションと効率のためのチューニング
ElmでWebフロントエンドの信頼性を高める
ElmでWebフロントエンドの信頼性を高める
感情分析の精度の4つの落とし穴
感情分析の精度の4つの落とし穴
人気の投稿
  • 給与を契約レートに変換する
  • main以外のc ++関数が実行されます。
  • tddとbddの面接の質問
  • ヘッダーファイルのc ++の例
  • sとccorpの違い
  • javascripttypeerrorは関数ではありません
カテゴリー
収益性と効率性 アジャイルタレント ライフスタイル 収益と成長 プロジェクト管理 アジャイル トレンド データサイエンスとデータベース その他 Webフロントエンド

© 2021 | 全著作権所有

apeescape2.com