“This is the 12th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
Hi 👋
- Wechat: RyukieW
- Wechat official account: LabLawliet
- 📦 Archive of technical articles
- 🐙 making
My personal project | Minesweeper Elic Endless Ladder | Dream of books | Privacy Access Record |
---|---|---|---|
type | The game | financial | tool |
AppStore | Elic | Umemi | Privacy Access Record |
More columns:
The independent development of Lawliet
Lawliet’s iOS garden party
Lawliet’s underlying iOS lab
Lawliet’s iOS Reverse lab
Lawliet’s brush book
Lawliet’s Flutter Lab
Flutter tips | Gesture handling and CLAMP functions from side index bar encapsulation
Flutter tips | Widget initialization method rewrite & chain call & Sort
Flutter tips | Assertion through the style of cells
Flutter tips | ListView slide to group heads
preface
In iOS development we often use tools like CocoaPods for package management. So what about flutter development?
This section uses the session list as an example and imports the network library: HTTP for interpretation.
Import the dependency library
This is the official web library: HTTP
Click on the copy
1.1 Modify the pubspec.yaml configuration file
Add the copied information to the configuration file
1.2 Update the dependency library
1.3 Import it where it is used
import 'package:http/http.dart' as http;
Copy the code
Asynchronous functions
2.1 Summary of Services
A brief summary of services is provided for subsequent use.
import 'package:flutter/material.dart';
class ServiceURL {
/// The session list
static Uri conversationList = Uri.parse('xxxxxx');
}
Copy the code
2.2 Sending a Request
The simple choice here is to make the network request in initState and call the move method
@override
void initState() {
super.initState();
_loadConversation();
}
/// Loading session list
void _loadConversation() async {
var response = await http.get(ServiceURL.conversationList);
print(response.body);
}
Copy the code
This is very different from the way we call web requests in iOS development. In iOS development, we receive the result of a request as a callback. We use await here.
Data model transformation
After receiving network data, we naturally need to transform the data model.
3.1 Defining the data model
import 'package:flutter/material.dart';
class ConversationData {
final String nick;
final String avatar;
final String lastestMessage;
ConversationData({
required this.nick,
required this.avatar,
required this.lastestMessage,
});
factory ConversationData.formMap(Map map) {
return ConversationData(
nick: map['nick'],
avatar: map['avatar'],
lastestMessage: map['lastest_message']); }}Copy the code
3.2 turn the Map Json
List _conversations = [];
/// Loading session list
void _loadConversation() async {
var response = await http.get(ServiceURL.conversationList);
if (response.statusCode == 200) {
final bodyMap = json.decode(response.body);
_conversations = bodyMap['lists']
.map((item) {
return ConversationData.formMap(item);
})
.toList();
} else {
throw Exception('Request failed:${response.statusCode}'); }}Copy the code
3.3 build a Cell
- Text
- The style is set
- Thumbnail Settings
- Set the maximum width
- Container
- Set the rounded corners of the image
class ConversationCell extends StatelessWidget {
ConversationCell({required this.conversation});
final ConversationData conversation;
@override
Widget build(BuildContext context) {
return Container(
height: 60,
color: Colors.white,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(
width: 12,),/ / the rounded
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
image: DecorationImage(
// Network image
image: NetworkImage(conversation.avatar),
),
),
),
const SizedBox(
width: 12,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 12),
Text(
conversation.nick,
maxLines: 1,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
Container(
// Limit the width
width: UIConfig.screenWidth(context) * 0.7,
child: Text(
conversation.lastestMessage,
maxLines: 1.// thumbnail styles
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
)
],
),
],
),
),
),
/ / line
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.only(left: 70),
height: 0.5, color: Colors.grey, ), ), ], ), ); }}Copy the code
3.4 build a ListView
Widget _itemForRow(BuildContext context, int index) {
return ConversationCell(conversation: _conversations[index]);
}
body: Container(
color: Colors.yellow,
child: ListView.builder(
itemBuilder: _itemForRow,
itemCount: _conversations.length,
),
),
Copy the code
3.5 the effect
Future & FutureBuilder
4.1 Request method modification
Previous loading methods:
/// Loading session list
void _loadConversation() async {
var response = await http.get(ServiceURL.conversationList);
if (response.statusCode == 200) {
final bodyMap = json.decode(response.body);
_conversations = bodyMap['lists']
.map((item) {
return ConversationData.formMap(item);
})
.toList();
} else {
throw Exception('Request failed:${response.statusCode}'); }}Copy the code
Is amended as:
/// Loading session list
Future<List> _loadConversation() async {
var response = await http.get(ServiceURL.conversationList);
if (response.statusCode == 200) {
final bodyMap = json.decode(response.body);
return bodyMap['lists'].map((item) {
return ConversationData.formMap(item);
}).toList();
} else {
throw Exception('Request failed:${response.statusCode}'); }}Copy the code
4.2 ListView to modify
AsyncSnapshot
Contains data for bound Future callbacks, as well as the status of asynchronous tasks. We can use this to determine whether to display the load page.
@override
Widget build(BuildContext context) {
returnScaffold( appBar: AppBar(...) , body: Container( color: Colors.yellow, child: FutureBuilder(/ / in the Future
future: _loadConversation(),
builder: (context, AsyncSnapshot snap){
// Determine the status of the request
if(snap.connectionState ! = ConnectionState.done) {return const Center(
child: Text('Loading')); }// Process the data presentation according to the results
return ListView(
children: snap.data.map<Widget>((item){
returnConversationCell(conversation: item); }).toList(), ); },),),); }Copy the code
4.3 See the effect
Five, combine the above two ways
In combination with the above two approaches, the Future is used here to tune the function that loads the data.
5.1 Request function modification
/// Loading session list
Future<List> _loadConversation() async {
_isLoading = true;
var response = await http.get(ServiceURL.conversationList);
_isLoading = false;
if (response.statusCode == 200) {
final bodyMap = json.decode(response.body);
final result = bodyMap['lists'].map((item) {
return ConversationData.formMap(item);
}).toList();
return result;
} else {
throw Exception('Request failed:${response.statusCode}'); }}Copy the code
5.2 Callback Processing
@override
void initState() {
super.initState();
_loadConversation().then((value) {
// Value is the result of a Future return
setState(() {
_conversations = value;
});
});
}
Copy the code
5.3 Exception Handling
With the Future we can also catch exceptions.
@override
void initState() {
super.initState();
_loadConversation().then((value) {
setState(() {
_conversations = value;
});
}).catchError((error) {
print(error);
});
}
Copy the code
Six, summarized
- The first approach is much closer to the way we think about iOS development
- The second approach, Future & FutureBuilder, makes more use of Future features
- The way of combining the two is more familiar and new to me as a newcomer to Flutter on iOS
The complete code
GitHub