“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