“This is the 7th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
review
Last time we got the data, this chapter is mainly about how to display the data. Data display inevitably involves asynchronous loading and data conversion
Json to a dictionary
Json data in a Flutter can be converted to a dictionary using json.decode
import 'dart:convert';
json.decode(response.body);
Copy the code
Dictionaries are transformed into models
The constructor needs to use the factory method if it wants to have a return value
class ChatModel {
final String? imgUrl;
final String? name;
final String? message;
ChatModel({this.imgUrl, this.name, this.message});
factory ChatModel.fromMap(Map map) {
return ChatModel(
imgUrl: map['imgUrl'], name: map['name'], message: map['message']); }}Copy the code
Model data source
For asynchronously loaded data, get the return values of all the data, and use the Future
Future<List<ChatModel>> getData() async {
final url =
Uri.parse('http://rap2api.taobao.org/app/mock/293759/home/chat/list');
var response = await http.get(url);
if (response.statusCode == 200) {
// json to a dictionary
final responseBody = json.decode(response.body);
return responseBody['data']
.map<ChatModel>((item) => ChatModel.fromMap(item))
.toList();
/ / model
} else {
throw Exception('statusCode=${response.statusCode}'); }}}Copy the code
Apply colours to a drawing
There’s a FutureBuilder for rendering asynchronously loaded data, there’s a mandatory parameter Builder, Typedef AsyncWidgetBuilder
= Widget Function(BuildContext context, AsyncSnapshot
snapshot);
Container(
child: FutureBuilder(
builder: (BuildContext context, AsyncSnapshot snapshot) {
print('${snapshot.data}');
return Container();
},
future: getData(),
)),
Copy the code
When printing snapshot.data, there will be two steps. One is null when the page is loaded, and the second is to refresh the data again after the array is retrieved
When the snapshot. ConnectionState: waiting without the data, when done shows that data have finished loading.
So at this point we can use thisconnectionState
To judge the state of
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Loading... '));
}
Copy the code
The children of the ListView can be generated by traversing the snapshot.data.map
((ChatModel item) array, and a new Widget is introduced here: The ListTile contains simple, commonly used layouts
const ListTile({
Key? key,
this.leading,
this.title,
this.subtitle,
this.trailing,
this.isThreeLine = false.this.dense,
this.visualDensity,
this.shape,
this.contentPadding,
this.enabled = true.this.onTap,
this.onLongPress,
this.mouseCursor,
this.selected = false.this.focusColor,
this.hoverColor,
this.focusNode,
this.autofocus = false.this.tileColor,
this.selectedTileColor,
this.enableFeedback,
this.horizontalTitleGap,
this.minVerticalPadding,
this.minLeadingWidth,
}) : assert(isThreeLine ! =null),
assert(enabled ! =null),
assert(selected ! =null),
assert(autofocus ! =null),
assert(! isThreeLine || subtitle ! =null),
super(key: key);
Copy the code
The layout looks like this:
State reserve
There was a slight problem with the data being reloaded every time the page was cut out and then cut back. In this case, the state is not preserved. If you want to keep it:
- inheritance
AutomaticKeepAliveClientMixin
class _ChatPageState extends State<ChatPage> with AutomaticKeepAliveClientMixin
- Then implement the methods of the parent class
@override
bool get wantKeepAlive => true;
Copy the code
- in
Widget build(BuildContext context)
In the implementationsuper.build(context);
Modify the Widget tree
Despite the implementation of the above three steps, it is still init again when cutting back. This is because each page is regenerated under the root controller and not in the current Widget tree. We will go back to the RootPage page to make changes
- Declare a
final PageController _pageController = PageController();
body
usePageView
body: PageView(
children: _pages,
controller: _pageController,
),
Copy the code
- When I switch pages,
_pageController
Synchronous jump
setState(() {
_currentIndex = index;
_pageController.jumpToPage(_currentIndex);
});
Copy the code
This saves the current page state every time you click on a TabbarItem. There is a slight problem, though. The current page can be swiped, but the buttons at the bottom don’t work with it. This minor problem can be solved in PageView onPageChanged:
onPageChanged: (index) {
setState(() {
_currentIndex = index;
});
},
Copy the code
Cut or setting cannot drag screen: physics: NeverScrollableScrollPhysics (),
Future
The Future was used in the network request above, so what is this?
String _temp = '0';
void main() {
// operatorDemo();
getData();
print('Before loop');
}
getData() {
print('Here we go.');
Future(() {
for (int i = 0; i < 100; i++) {}
print('End of loop');
});
}
Copy the code
Found to be used after testingFuture
The modified code block executes asynchronously and does not choke the current thread. If you want to wait until the asynchronous task is complete, you need to run theFuture
I’ll put one in front of itawait
String _temp = '0';
void main() {
// operatorDemo();
getData();
print('Before loop');
}
getData() async {
print('Here we go.');
await Future(() {
for (int i = 0; i < 100; i++) {}
print('End of loop');
});
print('Code after await');
}
Copy the code
Full code address: