我有一个由提供者处理并通过 SQL 查询设置的字符对象数组。当我执行 INSERT 操作时,新角色已成功添加到网页浏览中。但是,当我执行 DELETE 操作并从网页浏览中删除字符时,它会将其从列表中删除,但不会更新 UI 以显示数组中的下一个字符 - 它会继续显示已删除字符的信息,直到强制重建导航离开和返回。我知道它已成功从数据库和数组中删除,因为我的页面指示器减少了 1。当前 Character 由另一个提供程序处理,并通过将其作为参数传递给 CharacterState 通知程序来设置。
我想要的是 CharacterState 在执行 DELETE 操作后显示来自数组中下一个字符的信息。我认为问题在于 Character 对象如何从 CharacterListState 传递到 CharacterState。当用户在页面之间滑动或删除数组中的最后一项时,它可以正常工作,但否则 CharacterState 只会继续显示旧信息,直到通过离开页面并返回手动重建整个状态。
请在下面找到相关代码:
class CharacterListPage extends StatefulWidget {
@override
_CharacterListPageState createState() => _CharacterListPageState();
}
class _CharacterListPageState extends State<CharacterListPage> {
PageController _pageController = PageController();
@override
Widget build(BuildContext context) {
final AppState appState = Provider.of<AppState>(context);
final CharacterListState characterListState =
Provider.of<CharacterListState>(context);
// _pageController.jumpToPage(appState.position);
return Scaffold(
resizeToAvoidBottomPadding: true,
body: FutureBuilder<bool>(
future: characterListState.setCharacterList(),
builder: (context, AsyncSnapshot<bool> _snapshot) {
return _snapshot.hasError
? Container(child: Text(_snapshot.error.toString()))
: !_snapshot.hasData
? Container(
child: Center(child: CircularProgressIndicator()),
height: MediaQuery.of(context).size.height,
)
: PageIndicatorContainer(
child: PageView.builder(
controller: _pageController =
PageController(initialPage: appState.position),
onPageChanged: (_index) async {
var prefs = await SharedPreferences.getInstance();
appState.position = _index;
prefs.setInt('position', _index);
appState.setTheme(characterListState
.characterList[_index].classColor);
prefs.setString(
'themeColor',
characterListState
.characterList[_index].classColor);
},
itemCount: characterListState.characterList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: EdgeInsets.all(smallPadding),
child: Card(
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9),
image: DecorationImage(
image: AssetImage(
'images/class_icons/${characterListState.characterList[index].classIcon}'),
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.9),
BlendMode.lighten),
),
),
),
Container(
color: Color(int.parse(
characterListState
.characterList[index]
.classColor))
.withOpacity(0.2)),
SingleChildScrollView(
child: ChangeNotifierProvider<
CharacterState>(
builder: (context) => CharacterState(
characterListState
.characterList[index].id,
),
child: Container(
padding: EdgeInsets.all(smallPadding),
child: CharacterPage(),
),
),
)
],
),
),
);
},
),
align: IndicatorAlign.top,
length: characterListState.characterList.length,
indicatorSpace: smallPadding,
padding: const EdgeInsets.only(top: 20),
indicatorColor: Colors.white,
indicatorSelectorColor: appState.accentColor,
shape: IndicatorShape.circle(size: 12),
);
// shape: IndicatorShape.roundRectangleShape(size: Size.square(12),cornerSize: Size.square(3)),
// shape: IndicatorShape.oval(size: Size(12, 8)),
}),
floatingActionButton: SpeedDial(
animatedIcon: AnimatedIcons.menu_close,
animatedIconTheme: IconThemeData(size: 22.0),
closeManually: false,
curve: Curves.bounceIn,
overlayColor: Colors.black,
overlayOpacity: 0.5,
elevation: 8.0,
shape: CircleBorder(),
children: [
SpeedDialChild(
child: Icon(Icons.add),
backgroundColor: Theme.of(context).accentColor,
label: 'Import Legacy Character',
labelStyle: TextStyle(fontSize: 18.0),
onTap: () async => await characterListState.addLegacyCharacter()),
SpeedDialChild(
child: Icon(Icons.add),
backgroundColor: Colors.green,
label: 'Add New Character',
labelStyle: TextStyle(fontSize: 18.0),
onTap: () async {
await showDialog(
context: context,
builder: (BuildContext context) {
return NewCharacterDialog(characterListState: characterListState);
},
);
_pageController
.jumpToPage(characterListState.characterList.length + 1);
},
),
SpeedDialChild(
child: Icon(Icons.add),
backgroundColor: Colors.green,
label: 'OPEN OLD CHAR SHEET',
labelStyle: TextStyle(fontSize: 18.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CharacterSheetPage()),
);
})
],
),
);
}
}
CharacterListState 类
class CharacterListState with ChangeNotifier {
List<Character> _characterList = [];
List<bool> _legacyPerks = [];
DatabaseHelper db = DatabaseHelper.instance;
List<Character> get characterList => _characterList;
Future<bool> setCharacterList() async {
// List _list = [];
_characterList = await db.queryAllCharacters();
// _list.forEach((_result) => _result.))
// await db.queryPlayerClass(_classCode)
return true;
}
Future addCharacter(String _name, PlayerClass _playerClass) async {
Character _character = Character();
List<bool> _perks = [];
perkList.forEach((_perk) {
for (var x = 0; x < _perk.numOfPerks; x++) {
_perks.add(false);
}
});
_character.name = _name;
// _character.playerClass = _playerClass;
_character.classCode = _playerClass.classCode;
_character.classColor = _playerClass.classColor;
_character.classIcon = _playerClass.classIconUrl;
_character.classRace = _playerClass.race;
_character.className = _playerClass.className;
_character.xp = 0;
_character.gold = 0;
_character.notes = 'Add notes here';
_character.checkMarks = 0;
_character.isRetired = false;
int id = await db.insertCharacter(_character, _perks);
_character.id = id;
print('inserted row: $id');
print(_character.name);
print(_character.classCode);
notifyListeners();
}
Future deleteCharacter(int _characterId) async {
await db.deleteCharacter(_characterId);
// _characterList.removeWhere((value) => value.id == _characterId);
notifyListeners();
}
}