type
status
date
slug
summary
tags
category
icon
password
到目前为止,我们等待的时间终于到了,在这一部分中,我们最终将调用 UI 中的方法,您将看到所有代码,直到知道我们在实际编写时为止。
这只是本系列的一部分。查看此处的所有其他部分,并学习构建干净且可维护的应用程序。
注意:在我们的注册页面中,我们还必须上传用户的个人资料图片。如果您熟悉Firebase,我们会将文件和图像上传到Cloud Storage中。这是一个单独的主题,我们将在下一部分中单独讨论。
<ins/>
首先移动到你的 main.dart 并将其更改为:
到:
我们有 Bloc Builder 和 Bloc Listener。
Bloc Builder:
当我们想要根据当前状态绘制小部件时,可以使用Bloc Builder 。
Bloc Listener:
Bloc Listener持续监听状态的新变化,并且不返回小部件。
在上面使用Bloc Builder 的代码中,我们检查AuthState是否已验证,因此返回MainScreen()小部件,否则返回SignInPage()小部件。
注意: MainScreen()接受 uid 参数。转到MainScreen()并创建一个最终字段并将其传递到 Main Screen StatefulWidget的构造函数中。我们稍后将在本页中使用当前用户 ID。
<ins/>
这样,您的Material 应用程序就可以使用MultiBlocProvider进行包装,它接受BlocProviderSingleChildWidget列表。在此列表中,从位于注入容器中的已注册类型请求 Cubits。
用户是我们的首要任务,因此我们请求注入容器内的所有用户立方体,它们将在我们的应用程序启动时被调用,并且由于它们是工厂方法,因此每次都会给我们新的实例。
注意:我从AuthCubit调用了appStarted(context)方法,这是因为,这个appStarted是确保用户是否登录的方法。
现在,如果您热重启应用程序,您将在模拟器上看到登录页面。这是因为我们的用户未经身份验证,并且 Bloc Builder 根据当前状态(未经身份验证状态)绘制小部件。
Sign Up Page:
转到sign_up_page并将无状态小部件转换为有状态小部件。现在您需要添加一些控制器(TextEditingController)并将它们传递到表单(FormContainerWidget)中。
在状态下方执行以下操作:
注意:当用户注册时显示循环进度指示器时,将使用此 _isSigningUp 布尔变量。
也不要忘记处理这些控制器。
现在搜索带有文本“Sign Up”的ButtonContainerWidget() 。你会在那里找到onTapListener ,只需调用这里的方法_signUpUser()。
实现这个方法:
注意:我们不传递uid ,这是因为它是在后端处理的。另请注意_isSigningUp变量,当该方法被调用时,它通过setState变为 true,而稍后在 clear 方法中,当流程结束时,它在setState中变为 false,通过该变量我们将控制何时何地显示循环进度指示器。
在按钮容器小部件检查变量是否为 true 之后,立即显示一些带有指示符的文本,否则显示空容器小部件。
现在用单独的方法分离 Scaffold 的主体。
并将这个 body 小部件传递到脚手架主体中,如下所示:
现在用 Bloc Consumer 包裹身体。
Bloc Consumer:
Bloc Consumer 是 Bloc Builder 和 Bloc Listener 的混合体。当我们想要根据当前状态绘制某些内容并想要根据新到达的状态执行一些操作时,可以使用此方法。
在下面的代码中,我们首先在侦听器中执行两个操作,如果状态为“Credential Success”,然后调用AuthCubitloggingIn ()中的方法,这意味着在“Authenticated”状态下传递uid ,其次,如果存在某些失败则显示 toast。在构建器中,我们再次调用 bloc 构建器来再次检查经过身份验证的状态是否具有uid ,如果有,则将用户移动到主屏幕,否则将其保留在同一页面上。
恭喜 🎉 测试您的注册页面,一切顺利。
Sign In Page:
登录页面不会有太大不同,但只有一种方法会有所不同。
首先从注册页面复制控制器,不是全部控制器(电子邮件和密码)也可以处置它们。
现在搜索ButtonContainerWidget并在onTapListener中调用_signInUser()方法。
然后实现它:
注意:这里的_isSigningIn变量是相同的,从注册页面复制代码,就在ButtonContainerWidget后面;并将其粘贴到登录页面中的同一位置。仅更改变量的名称。
最后分离主体小部件并从注册页面复制代码并粘贴,所有内容都将保持不变。
恭喜 🎉 测试您的登录页面,一切顺利。
Logout User:
转到个人资料页面并到达底部,您将在那里看到底部模式表。用InkWell包装文本小部件“Logout”并调用此onTap方法:
恭喜 🎉 测试注销按钮,一切顺利。
从 Firestore 数据库加载用户数据:
在主屏幕上加载单用户:
如果您还记得,我们创建了getSingleUser来获取当前的单个用户。转到MainScreen()并使用 Bloc Builder 包装Scaffold并传递GetSingleUserCubit和GetSingleUserState ,并检查状态是否为GetSingleUserLoaded然后从状态中检索当前单个用户并将其保存在变量中。
执行此操作后,如果您热重启应用程序,您将在模拟器上看到圆形进度指示器。
为了避免在同一页面(MainScreen)中出现这种情况,请在initState中从GetSingleUserCubit调用getSingleUser方法并在其中传递uid 。
现在该指示器将消失。
最后一件事是在配置文件页面中显示 Firestore 数据库中的当前用户数据。
转到配置文件页面创建一个最终字段UserEntity并将其传递到构造函数中。
您将在MainScreen()页面中看到编译时错误。现在,在页面列表中,其中一个“个人资料页面”需要currentUser (UserEntity),因为我们从GetSingleUserCubit获取当前用户并将其存储在变量currentUser中,因此只需将其传递到此处即可。
主屏幕就是这样。
Profile Page:
通过删除所有虚拟数据,从个人资料页面中的 UserEntity 访问所有数据。
profile_page.dart
Solution Code:
GitHub: https ://github.com/AdnanKhan45/instagram-app-clone
结论
我们已经成功调用了 UI 中的所有方法。