我尝试为我的应用程序制作一个简单的个人资料页面,但我不完全知道该怎么做。
我想打电话时遇到错误
'${widget.user['first_name']}'
在我的个人资料小部件中:
NoSuchMethodError (NoSuchMethodError: The method '[]' was called on null. Receiver: null Tried calling: []("first_name"))
我的主页是一个包含 2 个小部件的 PageView。
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables
import 'dart:convert';
import 'package:clic_ads/Login/apiClient.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../Composants/appbar.dart';
import '../Login/login.dart';
import 'notifs.dart';
import 'profil.dart';
class MainPage extends StatefulWidget {
final dynamic user;
const MainPage({super.key, this.user});
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
final Api _apiClient = Api();
dynamic user;
final PageController _controller = PageController(
initialPage: 0,
);
int activePage = 0;
@override
Future<void> dispose() async {
_controller.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
}
void bottomTapped(int index) {
setState(() {
activePage = index;
_controller.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
});
}
@override
Widget build(BuildContext context) {
Future<void> getUser() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
this.user = await _apiClient.user(token!);
print(user);
return user ;
}
getUser();
return Scaffold(
appBar: PreferredSize(
preferredSize:
Size.fromHeight(MediaQuery.of(context).size.height * 0.07),
child: TopAppbar()),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: activePage,
backgroundColor: const Color(0xffC64C4E),
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white.withOpacity(.55),
selectedFontSize: 14,
unselectedFontSize: 14,
onTap: (value) {
bottomTapped(value);
},
items: [
BottomNavigationBarItem(
label: 'Notifs',
icon: Icon(Icons.view_list),
),
BottomNavigationBarItem(
label: 'Profil',
icon: Icon(
Icons.account_circle,
),
),
],
),
backgroundColor: const Color(0xffEEEEEE),
body: PageView(
onPageChanged: (index) {
setState(() {
activePage = index;
});
},
controller: _controller,
children: [Notifs(), Profil(user: this.user)],
),
);
}
}
我的第一个小部件是一个显示通知的小部件:
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables, unnecessary_new
import 'package:clic_ads/Login/apiClient.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Notifs extends StatefulWidget {
final dynamic user;
const Notifs({super.key, this.user});
@override
State\<Notifs\> createState() =\> \_NotifsState();
}
class \_NotifsState extends State\<Notifs\> {
final Api \_apiClient = Api();
dynamic user;
@override
Widget build(BuildContext context) {
double deviceWidth = MediaQuery.of(context).size.width;
double deviceHeight = MediaQuery.of(context).size.height;
Future\<void\> getUser() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
this.user = await \_apiClient.user(token!);
print(user);
return user ;
}
getUser();
return ListView.builder(
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
new Container(
decoration: new BoxDecoration(
color: Color.fromARGB(255, 255, 255, 255),
borderRadius: new BorderRadius.only(
topRight: const Radius.circular(15.0),
topLeft: const Radius.circular(15.0),
)),
margin: EdgeInsets.only(
top: deviceWidth * 0.03,
right: deviceWidth * 0.05,
left: deviceWidth * 0.05),
height: deviceHeight * 0.148,
alignment: Alignment.centerLeft,
child: Row(
children: [
Container(
decoration: new BoxDecoration(
color: const Color(0xffC64C4E),
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(15.0),
)),
width: deviceWidth * 0.12,
child: Center(
child: FittedBox(
child: Text(
'CU',
style: TextStyle(
fontSize: deviceWidth * 0.06,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
),
),
Padding(
padding: EdgeInsets.all(deviceWidth * 0.02),
child: SizedBox(
width: deviceWidth * 0.73,
child: Column(
children: [
Row(
children: [
Text('17:24',
style: TextStyle(
fontSize: deviceWidth * 0.04,
color: const Color(0xffC64C4E),
fontWeight: FontWeight.w600)),
Spacer(),
Text('20/10/2022',
style: TextStyle(
fontSize: deviceWidth * 0.04,
color: const Color(0xffC64C4E),
fontWeight: FontWeight.w600))
],
),
Padding(
padding: EdgeInsets.all(deviceWidth * 0.02),
child: Row(
children: [
Icon(Icons.person),
Text('DUPOND Martin (M.)',
style: TextStyle(
fontSize: deviceWidth * 0.035,
fontWeight: FontWeight.w500))
],
),
),
Padding(
padding: EdgeInsets.all(deviceWidth * 0.02),
child: Row(
children: [
Icon(
Icons.book,
),
Text('CU01201222U0009',
style: TextStyle(
fontSize: deviceWidth * 0.035,
fontWeight: FontWeight.w500))
],
),
)
],
),
),
)
],
),
),
Container(
color: const Color(0xffC64C4E),
height: 3,
width: deviceWidth * 0.90)
],
);
},
);
}
}
我想显示用户详细信息的第二个小部件在这里:
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables
import 'package:clic_ads/Login/apiClient.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Profil extends StatefulWidget {
final dynamic user;
const Profil({super.key, this.user});
@override
State\<Profil\> createState() =\> \_ProfilState();
}
class \_ProfilState extends State\<Profil\> {
// final Api \_apiClient = Api();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
// Future<void> getUser() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// var token = prefs.getString('token');
// user = await _apiClient.user(token!);
// print(user['data']);
// }
// getUser();
// print(user);
double deviceWidth = MediaQuery.of(context).size.width;
double deviceHeight = MediaQuery.of(context).size.height;
return Padding(
padding: EdgeInsets.all(deviceWidth * 0.05),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Profil',
style: TextStyle(
fontSize: deviceWidth * 0.06, fontWeight: FontWeight.w500)),
Padding(
padding: EdgeInsets.only(left: deviceWidth * 0.05),
child: Row(
children: [
Icon(
Icons.account_circle,
size: deviceWidth * 0.3,
),
Padding(
padding: EdgeInsets.only(left: deviceWidth * 0.05),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text('${widget.user['first_name']}',
style: TextStyle(
fontSize: deviceWidth * 0.04,
fontWeight: FontWeight.w500)),
SizedBox(width: 10),
Text('${widget.user['last_name']}',
style: TextStyle(
fontSize: deviceWidth * 0.04,
fontWeight: FontWeight.w500))
],
),
SizedBox(
height: 15,
),
Text('${widget.user['email']}',
style: TextStyle(
fontSize: deviceWidth * 0.04,
fontWeight: FontWeight.w500))
],
),
)
],
),
),
Text('Paramètres',
style: TextStyle(
fontSize: deviceWidth * 0.06, fontWeight: FontWeight.w500))
],
),
);
}
}
我希望在我的个人资料页面上显示我的用户信息
尝试接受 null 就像
'${widget.user?['first_name']}'
getUser();
方法是异步方法,但在_MainPageState.build
方法执行期间不会等待它。
因此,当执行
children: [Notifs(), Profil(user: this.user)],
行时,user
类成员未初始化。
所以您可能想使用 FutureBuilder 来等待未来并获得结果。
此方案需要将
getUser
方法调整为类方法,并返回Future<dynamic>
值供后续使用:
class _NotifsState extends State<Notifs> {
...
Future<dynamic> getUser() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
this.user = await _apiClient.user(token!);
print(user);
return user ;
}
@override
Widget build(BuildContext context) {
...
children: [Notifs(), FutureBuilder<dynamic>(
future: getUser(),
builder: (c, snapshot) => snapshot.hasData
? Profil(user: snapshot.data)
: const CircularProgressIndicator())
],
}
}
在第二个代码示例的
'${widget.user['first_name']}'
行中,用户信息是从哪里获取的?对我来说,似乎没有当前用户的实例可以从中获取信息。