go_router尝试从动态链接打开应用程序之后 - 未经手的例外:该小部件已被卸载,因此状态不再具有上下文
我使用的是Flutter + Go_router 3.0 + FlutterFlow + Firebase(创建我的动态链接)。 该应用程序正常工作。我的问题来自当用户单击动态链接并打开应用程序时,我有一个错误(请参见下文)。它仅在从firebase生成的动态链接打开时显示此错误,例如 - app.page.link/settings
我在这里看到了很多问题,我知道应该做什么,但是我仍然需要一些指导方针,即应该更改哪个示例以及错误来自哪里。
这是我的代码,
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:go_router/go_router.dart';
import 'package:kulturno_mi_e/login/login_widget.dart';
import 'package:kulturno_mi_e/splash_screen/splash_screen_widget.dart';
import 'package:provider/provider.dart';
import 'auth/auth_util.dart';
import 'auth/firebase_user_provider.dart';
import 'favourites/favourites_widget.dart';
import 'flutter_flow/flutter_flow_theme.dart';
import 'flutter_flow/internationalization.dart';
import 'home/home_widget.dart';
import 'settings/settings_widget.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FlutterFlowTheme.initialize();
runApp(MyApp());
}
class LoginInfo extends ChangeNotifier {
var _userName = '';
String get userName => _userName;
bool get loggedIn => _userName.isNotEmpty;
// set loggedIn(bool loginStatus) {
// loggedIn = loginStatus;
// }
void login(String userName) {
_userName = userName;
notifyListeners();
}
void logout() {
_userName = '';
notifyListeners();
}
}
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
static _MyAppState of(BuildContext context) =>
context.findAncestorStateOfType<_MyAppState>();
}
class _MyAppState extends State<MyApp> {
Locale _locale;
ThemeMode _themeMode = FlutterFlowTheme.themeMode;
Stream<KulturnoMiEFirebaseUser> userStream;
KulturnoMiEFirebaseUser initialUser;
bool displaySplashImage = true;
final authUserSub = authenticatedUserStream.listen((_) {});
void setLocale(Locale value) => setState(() => _locale = value);
void setThemeMode(ThemeMode mode) => setState(() {
_themeMode = mode;
FlutterFlowTheme.saveThemeMode(mode);
});
@override
void initState() {
super.initState();
userStream = kulturnoMiEFirebaseUserStream()
..listen((user) => initialUser ?? setState(() => initialUser = user));
Future.delayed(
Duration(seconds: 1), () => setState(() => displaySplashImage = false));
}
@override
void dispose() {
authUserSub.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final _loginInfo = LoginInfo();
final GoRouter _router = GoRouter(
initialLocation: '/events',
// redirect to the login page if the user is not logged in
redirect: (state) {
// if the user is not logged in, they need to login
// final loggedIn = _loginInfo.loggedIn;
final loggedIn = currentUser == null ? false : currentUser.loggedIn;
final loggingIn = state.subloc == '/login';
// bundle the location the user is coming from into a query parameter
// TODO: Chane '/' with the "Entry Page"
final fromp = state.subloc == '/' ? '' : '?from=${state.subloc}';
if (!loggedIn) return loggingIn ? null : '/login$fromp';
// if the user is logged in, send them where they were going before (or
// home if they weren't going anywhere)
if (loggingIn) return state.queryParams['from'] ?? '/events';
// no need to redirect at all
return null;
},
// changes on the listenable will cause the router to refresh it's route
refreshListenable: _loginInfo,
debugLogDiagnostics: true,
routes: <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const SplashScreenWidget(),
),
GoRoute(
path: '/login',
builder: (BuildContext context, GoRouterState state) =>
const LoginWidget(),
),
GoRoute(
path: '/events',
builder: (BuildContext context, GoRouterState state) =>
// TODO: In this demo I use NavBar, but it can be also normal - const PageWidget(),
NavBarPage(initialPage: 'home'),
),
GoRoute(
name: '/settings',
path: '/settings',
builder: (BuildContext context, GoRouterState state) =>
NavBarPage(initialPage: 'settings'),
),
],
errorBuilder: (context, state) => Text('ERROR! PAGE NOT FOUND!'),
);
// final router = GoRouter.of(context);
// print(['ROUTER!!! ', _router.location]);
return ChangeNotifierProvider<LoginInfo>.value(
value: _loginInfo,
child: MaterialApp.router(
title: 'Kulturno mi e',
localizationsDelegates: [
FFLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
locale: _locale,
supportedLocales: const [Locale('en', '')],
theme: ThemeData(brightness: Brightness.light),
darkTheme: ThemeData(brightness: Brightness.dark),
themeMode: _themeMode,
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
// home: initialUser == null || displaySplashImage
// ? Container(
// color: Colors.transparent,
// child: Builder(
// builder: (context) => Image.asset(
// 'assets/images/photo_2022-03-24_12-00-45.jpg',
// fit: BoxFit.contain,
// ),
// ),
// )
// : currentUser.loggedIn
// ? NavBarPage()
// : SplashScreenWidget(),
),
);
}
}
class NavBarPage extends StatefulWidget {
NavBarPage({Key key, this.initialPage}) : super(key: key);
final String initialPage;
@override
_NavBarPageState createState() => _NavBarPageState();
}
/// This is the private State class that goes with NavBarPage.
class _NavBarPageState extends State<NavBarPage> {
String _currentPage = 'home';
@override
void initState() {
super.initState();
_currentPage = widget.initialPage ?? _currentPage;
}
@override
Widget build(BuildContext context) {
final tabs = {
'home': HomeWidget(),
'favourites': FavouritesWidget(),
'settings': SettingsWidget(),
};
final currentIndex = tabs.keys.toList().indexOf(_currentPage);
return Scaffold(
body: tabs[_currentPage],
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (i) => setState(() => _currentPage = tabs.keys.toList()[i]),
backgroundColor: Colors.black,
selectedItemColor: Colors.white,
unselectedItemColor: Color(0xFF57636C),
showSelectedLabels: false,
showUnselectedLabels: false,
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home_outlined,
size: 24,
),
activeIcon: Icon(
Icons.home,
size: 24,
),
label: 'Начало',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.favorite_border,
size: 24,
),
activeIcon: Icon(
Icons.favorite,
size: 24,
),
label: 'Известия',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.settings_outlined,
size: 24,
),
activeIcon: Icon(
Icons.settings,
size: 24,
),
label: 'Настройки',
tooltip: '',
)
],
),
);
}
}
这是我遇到的错误
E/flutter (23539): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
E/flutter (23539): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
E/flutter (23539): #0 State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:929:9)
E/flutter (23539): #1 State.context (package:flutter/src/widgets/framework.dart:935:6)
E/flutter (23539): #2 _DynamicLinksState.initDynamicLinks.<anonymous closure> (package:kulturno_mi_e/custom_code/widgets/dynamic_links.dart:48:27)
E/flutter (23539): #3 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter (23539): #4 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter (23539): #5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
E/flutter (23539): #6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter (23539): #7 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (23539): #8 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (23539): #9 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (23539): #10 _rootRun (dart:async/zone.dart:1418:47)
E/flutter (23539): #11 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #12 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #13 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #14 _rootRun (dart:async/zone.dart:1426:13)
E/flutter (23539): #15 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #16 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #17 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #18 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (23539): #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (23539):
E/flutter (23539): [ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
E/flutter (23539): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active., stack trace: #0 State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:929:9)
E/flutter (23539): #1 State.context (package:flutter/src/widgets/framework.dart:935:6)
E/flutter (23539): #2 _DynamicLinksState.initDynamicLinks.<anonymous closure> (package:kulturno_mi_e/custom_code/widgets/dynamic_links.dart:48:27)
E/flutter (23539): #3 _rootRunUnary (dart:async/zone.dart:1442:13)
E/flutter (23539): #4 _RootZone.runUnaryGuarded (dart:async/zone.dart:1621:7)
E/flutter (23539): #5 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter (23539): #6 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (23539): #7 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (23539): #8 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (23539): #9 _rootRun (dart:async/zone.dart:1418:47)
E/flutter (23539): #10 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #11 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #12 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #13 _rootRun (dart:async/zone.dart:1426:13)
E/flutter (23539): #14 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #15 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #16 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #17 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (23539): #18 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (23539):
I am using Flutter + go_router 3.0 + Flutterflow + Firebase (to create my dynamic link).
The app is working perfectly fine. My problem comes from when a user clicks on a Dynamic link and the app opens and I got an error (see below). It only shows this error when the app is opened from a Dynamic link which was generated from Firebase, example - app.page.link/settings
I saw many questions here and I know what it should be done in general, but I still need some guideline of what example should be changed and where is the error coming from.
Here is my code
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:go_router/go_router.dart';
import 'package:kulturno_mi_e/login/login_widget.dart';
import 'package:kulturno_mi_e/splash_screen/splash_screen_widget.dart';
import 'package:provider/provider.dart';
import 'auth/auth_util.dart';
import 'auth/firebase_user_provider.dart';
import 'favourites/favourites_widget.dart';
import 'flutter_flow/flutter_flow_theme.dart';
import 'flutter_flow/internationalization.dart';
import 'home/home_widget.dart';
import 'settings/settings_widget.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FlutterFlowTheme.initialize();
runApp(MyApp());
}
class LoginInfo extends ChangeNotifier {
var _userName = '';
String get userName => _userName;
bool get loggedIn => _userName.isNotEmpty;
// set loggedIn(bool loginStatus) {
// loggedIn = loginStatus;
// }
void login(String userName) {
_userName = userName;
notifyListeners();
}
void logout() {
_userName = '';
notifyListeners();
}
}
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
static _MyAppState of(BuildContext context) =>
context.findAncestorStateOfType<_MyAppState>();
}
class _MyAppState extends State<MyApp> {
Locale _locale;
ThemeMode _themeMode = FlutterFlowTheme.themeMode;
Stream<KulturnoMiEFirebaseUser> userStream;
KulturnoMiEFirebaseUser initialUser;
bool displaySplashImage = true;
final authUserSub = authenticatedUserStream.listen((_) {});
void setLocale(Locale value) => setState(() => _locale = value);
void setThemeMode(ThemeMode mode) => setState(() {
_themeMode = mode;
FlutterFlowTheme.saveThemeMode(mode);
});
@override
void initState() {
super.initState();
userStream = kulturnoMiEFirebaseUserStream()
..listen((user) => initialUser ?? setState(() => initialUser = user));
Future.delayed(
Duration(seconds: 1), () => setState(() => displaySplashImage = false));
}
@override
void dispose() {
authUserSub.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final _loginInfo = LoginInfo();
final GoRouter _router = GoRouter(
initialLocation: '/events',
// redirect to the login page if the user is not logged in
redirect: (state) {
// if the user is not logged in, they need to login
// final loggedIn = _loginInfo.loggedIn;
final loggedIn = currentUser == null ? false : currentUser.loggedIn;
final loggingIn = state.subloc == '/login';
// bundle the location the user is coming from into a query parameter
// TODO: Chane '/' with the "Entry Page"
final fromp = state.subloc == '/' ? '' : '?from=${state.subloc}';
if (!loggedIn) return loggingIn ? null : '/login$fromp';
// if the user is logged in, send them where they were going before (or
// home if they weren't going anywhere)
if (loggingIn) return state.queryParams['from'] ?? '/events';
// no need to redirect at all
return null;
},
// changes on the listenable will cause the router to refresh it's route
refreshListenable: _loginInfo,
debugLogDiagnostics: true,
routes: <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const SplashScreenWidget(),
),
GoRoute(
path: '/login',
builder: (BuildContext context, GoRouterState state) =>
const LoginWidget(),
),
GoRoute(
path: '/events',
builder: (BuildContext context, GoRouterState state) =>
// TODO: In this demo I use NavBar, but it can be also normal - const PageWidget(),
NavBarPage(initialPage: 'home'),
),
GoRoute(
name: '/settings',
path: '/settings',
builder: (BuildContext context, GoRouterState state) =>
NavBarPage(initialPage: 'settings'),
),
],
errorBuilder: (context, state) => Text('ERROR! PAGE NOT FOUND!'),
);
// final router = GoRouter.of(context);
// print(['ROUTER!!! ', _router.location]);
return ChangeNotifierProvider<LoginInfo>.value(
value: _loginInfo,
child: MaterialApp.router(
title: 'Kulturno mi e',
localizationsDelegates: [
FFLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
locale: _locale,
supportedLocales: const [Locale('en', '')],
theme: ThemeData(brightness: Brightness.light),
darkTheme: ThemeData(brightness: Brightness.dark),
themeMode: _themeMode,
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
// home: initialUser == null || displaySplashImage
// ? Container(
// color: Colors.transparent,
// child: Builder(
// builder: (context) => Image.asset(
// 'assets/images/photo_2022-03-24_12-00-45.jpg',
// fit: BoxFit.contain,
// ),
// ),
// )
// : currentUser.loggedIn
// ? NavBarPage()
// : SplashScreenWidget(),
),
);
}
}
class NavBarPage extends StatefulWidget {
NavBarPage({Key key, this.initialPage}) : super(key: key);
final String initialPage;
@override
_NavBarPageState createState() => _NavBarPageState();
}
/// This is the private State class that goes with NavBarPage.
class _NavBarPageState extends State<NavBarPage> {
String _currentPage = 'home';
@override
void initState() {
super.initState();
_currentPage = widget.initialPage ?? _currentPage;
}
@override
Widget build(BuildContext context) {
final tabs = {
'home': HomeWidget(),
'favourites': FavouritesWidget(),
'settings': SettingsWidget(),
};
final currentIndex = tabs.keys.toList().indexOf(_currentPage);
return Scaffold(
body: tabs[_currentPage],
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (i) => setState(() => _currentPage = tabs.keys.toList()[i]),
backgroundColor: Colors.black,
selectedItemColor: Colors.white,
unselectedItemColor: Color(0xFF57636C),
showSelectedLabels: false,
showUnselectedLabels: false,
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home_outlined,
size: 24,
),
activeIcon: Icon(
Icons.home,
size: 24,
),
label: 'Начало',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.favorite_border,
size: 24,
),
activeIcon: Icon(
Icons.favorite,
size: 24,
),
label: 'Известия',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.settings_outlined,
size: 24,
),
activeIcon: Icon(
Icons.settings,
size: 24,
),
label: 'Настройки',
tooltip: '',
)
],
),
);
}
}
This is the error I got
E/flutter (23539): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
E/flutter (23539): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
E/flutter (23539): #0 State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:929:9)
E/flutter (23539): #1 State.context (package:flutter/src/widgets/framework.dart:935:6)
E/flutter (23539): #2 _DynamicLinksState.initDynamicLinks.<anonymous closure> (package:kulturno_mi_e/custom_code/widgets/dynamic_links.dart:48:27)
E/flutter (23539): #3 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter (23539): #4 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter (23539): #5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
E/flutter (23539): #6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter (23539): #7 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (23539): #8 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (23539): #9 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (23539): #10 _rootRun (dart:async/zone.dart:1418:47)
E/flutter (23539): #11 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #12 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #13 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #14 _rootRun (dart:async/zone.dart:1426:13)
E/flutter (23539): #15 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #16 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #17 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #18 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (23539): #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (23539):
E/flutter (23539): [ERROR:flutter/shell/common/shell.cc(93)] Dart Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
E/flutter (23539): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active., stack trace: #0 State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:929:9)
E/flutter (23539): #1 State.context (package:flutter/src/widgets/framework.dart:935:6)
E/flutter (23539): #2 _DynamicLinksState.initDynamicLinks.<anonymous closure> (package:kulturno_mi_e/custom_code/widgets/dynamic_links.dart:48:27)
E/flutter (23539): #3 _rootRunUnary (dart:async/zone.dart:1442:13)
E/flutter (23539): #4 _RootZone.runUnaryGuarded (dart:async/zone.dart:1621:7)
E/flutter (23539): #5 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter (23539): #6 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter (23539): #7 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter (23539): #8 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter (23539): #9 _rootRun (dart:async/zone.dart:1418:47)
E/flutter (23539): #10 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #11 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #12 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #13 _rootRun (dart:async/zone.dart:1426:13)
E/flutter (23539): #14 _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter (23539): #15 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter (23539): #16 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter (23539): #17 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (23539): #18 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
E/flutter (23539):
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论