Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

แอพ Fullstack Serverless พร้อม Flutter, Serverless Framework และ Upstash (REDIS) - PART 2

ยินดีต้อนรับสู่ส่วนที่ 2 ของชุดบทช่วยสอนนี้ ในส่วนแรก เราเห็นวิธีสร้าง REST API โดยใช้ Upstash, Serverless Framework และ Redis

ในส่วนนี้ เราจะสร้างแอปพลิเคชันมือถือโดยใช้ Flutter เพื่อใช้ปลายทาง REST API ของเรา

มาเริ่มกันเลย 🙃

ประการแรก คุณจะต้องติดตั้ง Flutter และใช้งานบนคอมพิวเตอร์ของคุณ

  • กระพือ

สร้างโปรเจ็กต์ flutter ใหม่ใน IDE ของคุณและตั้งชื่อตามที่คุณต้องการ

เปิด pubspec.yaml ไฟล์ที่ไดเร็กทอรีรากของโปรเจ็กต์ flutter ของคุณ และเพิ่มการพึ่งพาเหล่านี้ภายใต้ dev_dependencies

timeago: ^3.1.0
shared_preferences: ^2.0.6
http: ^0.13.4

ในที่สุดมันก็ควรจะเป็นแบบนี้

dev_dependencies:
  flutter_test:
    sdk: flutter

  timeago: ^3.1.0
  shared_preferences: ^2.0.6
  http: ^0.13.4

timeago ไลบรารีกำลังแปลงการประทับเวลา Unix (1636824843) เป็นรูปแบบที่มนุษย์อ่านได้ เช่น a minute ago , 5 mins ago เป็นต้น

Once we create a user account, we want to keep track of their . ของพวกเขา userIdand other minor details. We'll use shared_preferencesfor that. Then we'll use the ไลบรารี http` สำหรับการโทรผ่าน HTTP

เริ่มกันเลย...

สร้างผู้ใช้

หน้าจอแรกที่เราจะสร้างคือหน้าจอสร้างผู้ใช้ ซึ่งจะใช้ปลายทางการสร้างผู้ใช้

นี่คือลักษณะของหน้าจอ

แอพ Fullstack Serverless พร้อม Flutter, Serverless Framework และ Upstash (REDIS) - PART 2 อย่ากังวลเรื่องรูปกระต่าย เป็นเพียงตัวยึดสำหรับการดูภาพ

สร้างโฟลเดอร์ภายใน lib โฟลเดอร์ชื่อ account แล้วสร้างไฟล์ใหม่ชื่อ create_profile_screen.dart ภายใน account โฟลเดอร์

นี่คือวิธี lib . สุดท้ายของฉัน โครงสร้างโฟลเดอร์ดูเหมือน แอพ Fullstack Serverless พร้อม Flutter, Serverless Framework และ Upstash (REDIS) - PART 2 ในการสร้างผู้ใช้ใหม่ เราจำเป็นต้องมี

  • URL รูปโปรไฟล์
  • ชื่อ
  • นามสกุล
  • ชื่อผู้ใช้
  • ปลายทาง

มาดูโค้ดกันเลย

static const String  CREATE_USER_PROFILE_URL = "https://5vafvrk8kj.execute-api.us-east-1.amazonaws.com/dev/user";
  bool _loading = false;

 Future<void>createUserProfile() async{
    setState(() {
      _loading = true;
    });
  print(usernameController.text);
  print(firstNameController.text);
  print(lastNameController.text);
  print(profilePicUrl);
    await http.post(Uri.parse(CREATE_USER_PROFILE_URL),
        body: convert.jsonEncode({'username': usernameController.text,
          "firstName":firstNameController.text,"lastName":lastNameController.text,
          "profilePic":profilePicUrl})).then((response) async {

      var jsonResponse =
      convert.jsonDecode(response.body) as Map<String, dynamic>;

      setState(() {
        _loading = false;
      });
      if(response.statusCode == 400){

       ScaffoldMessenger.of(context).showSnackBar(SnackBar(padding:EdgeInsets.all(10),backgroundColor: Colors.red,content: Text(jsonResponse['message'])));
      }else if(response.statusCode == 200) {

        print('user id is :' +jsonResponse['userId']);
        await saveUserId(jsonResponse['userId']);
        Navigator.push(context, MaterialPageRoute(builder: (context){
          return HomeScreen();
        }));
      }
    });



  }

Future เป็นคลาส Dart หลักสำหรับการทำงานกับการดำเนินการแบบอะซิงโครนัส วัตถุในอนาคตแสดงถึงค่าที่เป็นไปได้หรือข้อผิดพลาดที่จะพร้อมใช้งานในอนาคตในอนาคต

คลาส http.Response มีข้อมูลที่ได้รับจากการโทร http ที่สำเร็จ

โค้ดด้านบนใช้ http post วิธีการส่งคำขอโพสต์ไปยัง create user endpoint จากนั้นรอการตอบกลับ

หากรหัสสถานะการตอบกลับคือ 200 แสดงว่าคำขอสำเร็จ เราจะบันทึก UserId ที่สร้างขึ้นในการตั้งค่าที่ใช้ร่วมกัน จากนั้นเราจะย้ายไปที่หน้าจอหลัก

นี่คือลิงค์ไปยังซอร์สโค้ดที่สมบูรณ์สำหรับหน้าจอนี้ สร้างหน้าจอโปรไฟล์

สร้างโพสต์

หนึ่งในอุปกรณ์ปลายทางของเราอนุญาตให้ผู้ใช้สร้างโพสต์ได้ นี่คือลักษณะของหน้าจอ

แอพ Fullstack Serverless พร้อม Flutter, Serverless Framework และ Upstash (REDIS) - PART 2

ในการสร้างโพสต์ ผู้ใช้ต้องการ

  • รหัสผู้ใช้
  • ข้อความ
  • imageUrl

โปรดจำไว้ว่า เพื่อจุดประสงค์ในการสาธิต เรากำลังใช้ imageUrl สำเร็จรูป ในแอปจริง คุณจะต้องอนุญาตให้ผู้ใช้เลือกรูปภาพ อัปโหลดไปยังเซิร์ฟเวอร์ รับ URL รูปภาพ แล้วใช้เพื่อสร้างโพสต์

CreatePost เมธอดดูเหมือน CreateUser วิธีการ

 Future<void> createPost(String userId) async {
    await http
        .post(Uri.parse(CREATE_USER_POST_URL),
            body: convert.jsonEncode({
              'userId': userId,
              "postText": postTextController.text,
              "postImage": _postPicUrl[i]
            }))
        .then((response) async {
      var jsonResponse =
          convert.jsonDecode(response.body) as Map<String, dynamic>;

      setState(() {
        _loading = false;
      });
      if (response.statusCode == 400) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            padding: EdgeInsets.all(10),
            backgroundColor: Colors.red,
            content: Text(jsonResponse['message'])));
      } else if (response.statusCode == 200) {
        print('post id is :' + jsonResponse['id']);
        Navigator.of(context).pop();
      }
    });
  }

แสดงรายการโพสต์ทั้งหมด

หน้าจอหลักในแอปพลิเคชันของเราจะแสดงรายการโพสต์ทั้งหมดที่สร้างขึ้น

อะไรประมาณนี้

แอพ Fullstack Serverless พร้อม Flutter, Serverless Framework และ Upstash (REDIS) - PART 2 เพื่อดึงข้อมูลโพสต์ทั้งหมดในลักษณะที่ปราศจากความเครียด ขั้นแรกเราต้องสร้างวัตถุโผแบบกำหนดเองที่ แสดงถึงโพสต์เดียว

class Post {
  String? postText;
  String? userId;
  String? createdOn;
  String? id;
  String? postImage;
  PostAdmin? postAdmin;

  Post(
      {this.postText,
      this.userId,
      this.createdOn,
      this.id,
      this.postImage,
      this.postAdmin});

  Post.fromJson(Map<String, dynamic> json) {
    postText = json['postText'];
    userId = json['userId'];
    createdOn = json['createdOn'];
    id = json['id'];
    postImage = json['postImage'];
    postAdmin = json['postAdmin'] != null
        ? PostAdmin.fromJson(json['postAdmin'])
        : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['postText'] = this.postText;
    data['userId'] = this.userId;
    data['createdOn'] = this.createdOn;
    data['id'] = this.id;
    data['postImage'] = this.postImage;
    if (this.postAdmin != null) {
      data['postAdmin'] = this.postAdmin!.toJson();
    }
    return data;
  }
}

class PostAdmin {
  String? timestamp;
  String? userId;
  String? username;
  String? firstName;
  String? lastName;
  String? profilePic;

  PostAdmin(
      {this.timestamp,
      this.userId,
      this.username,
      this.firstName,
      this.lastName,
      this.profilePic});

  PostAdmin.fromJson(Map<String, dynamic> json) {
    timestamp = json['timestamp'];
    userId = json['userId'];
    username = json['username'];
    firstName = json['firstName'];
    lastName = json['lastName'];
    profilePic = json['profilePic'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['timestamp'] = this.timestamp;
    data['userId'] = this.userId;
    data['username'] = this.username;
    data['firstName'] = this.firstName;
    data['lastName'] = this.lastName;
    data['profilePic'] = this.profilePic;
    return data;
  }
}

จากนั้น เราแปลง http.Response ไปยังวัตถุ Dart ที่กำหนดเองนั้น

List<Post> parsePosts(String responseBody) {
  final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();

  return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}

Future<List<Post>> fetchPosts(http.Client client) async {
  final response = await client
      .get(Uri.parse(GET_POSTS));

  return compute(parsePosts,response.body);
}

ประเภทการส่งคืนสำหรับ fetchPosts เมธอดเป็น Future<List<Post>> .

หากคุณเรียกใช้ฟังก์ชัน fetchPosts() บนอุปกรณ์ที่ช้ากว่า คุณอาจสังเกตเห็นว่าแอปหยุดทำงานชั่วขณะขณะแยกวิเคราะห์และแปลง JSON นี่คือขยะ และคุณต้องการกำจัดมัน

เราลบ jank โดยการย้ายการแยกวิเคราะห์และการแปลงเป็นพื้นหลังโดยใช้ compute ฟังก์ชัน

compute(parsePosts, response.body);

ฟังก์ชัน compute() เรียกใช้ฟังก์ชันราคาแพงในเบื้องหลังแยกและส่งคืนผลลัพธ์

ในไฟล์หน้าจอหลัก เราจะใช้วิดเจ็ต FutureBuilder เพื่อดึงโพสต์ทั้งหมดเป็นรายการจากฐานข้อมูลของคุณแบบอะซิงโครนัส

เราต้องระบุพารามิเตอร์สองตัว:

  • อนาคตที่คุณต้องการทำงานด้วย ในกรณีนี้ อนาคตที่ส่งคืนจากฟังก์ชัน fetchPosts()

ฟังก์ชันตัวสร้างที่บอก Flutter ว่าจะแสดงผลอะไร ขึ้นอยู่กับสถานะของอนาคต:การโหลด สำเร็จ หรือข้อผิดพลาด

โปรดทราบว่า snapshot.hasData จะคืนค่า จริง ต่อเมื่อสแน็ปช็อตมีค่าข้อมูลที่ไม่เป็นค่าว่าง

เนื่องจาก fetchPosts สามารถคืนค่าที่ไม่ใช่ค่า Null ได้เท่านั้น ฟังก์ชันจึงควรมีข้อยกเว้นแม้ในกรณีที่มีการตอบสนองของเซิร์ฟเวอร์ "404 Not Found" การส่งข้อยกเว้นจะตั้งค่า snapshot.hasError เป็น true ซึ่งสามารถใช้เพื่อแสดงข้อความแสดงข้อผิดพลาดได้

มิฉะนั้น สปินเนอร์จะปรากฏขึ้น

Expanded(child: FutureBuilder<List<Post>>(
              future: _posts,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  List<Post>? posts = snapshot.data;
                  if(posts != null){
                    return ListView.builder(itemBuilder: (context,index){
                      return  Card(
                        child: Container(
                          padding: EdgeInsets.all(10),
                          child: Row(
                           crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                          ClipRRect(
                          borderRadius: BorderRadius.circular(1000),
                          child: Image.network(
                            posts[index].postAdmin!.profilePic!,
                            fit: BoxFit.cover,
                            height: 40,
                            width: 40,
                          ),
                      ),
                          Expanded(
                            child: Container(
                              padding: EdgeInsets.only(left: 10),
                              child: Column(
                               mainAxisAlignment: MainAxisAlignment.start,
                               crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                              Text(posts[index].postAdmin!.username!,style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16),),
                              Text(posts[index].postText!),
                                  ClipRRect(
                                    borderRadius: BorderRadius.circular(10),
                                    child: Image.network(
                                      posts[index].postImage!,
                                      fit: BoxFit.cover,
                                      height: 150,
                                      width: size.width,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          )
                            ],
                          ),
                        ),
                      );
                    },itemCount: posts.length,);
                  }

                } else if (snapshot.hasError) {
                  return Text("${snapshot.error}");
                }

                // By default, show a loading spinner.
                return Container(
                    height: 40,
                    width: 40,

                    child: Center(child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).colorScheme.secondary))));
              },
            ))

ในเมธอด initState เราเรียก fetchPosts

late Future<List<Post>> _posts;


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _posts = fetchPosts(http.Client());

  }

เหตุผลที่เราเรียก fetchPosts ใน initState แทนวิธีการ build เป็นเพราะ flutter เรียกใช้เมธอด build() ทุกครั้งที่จำเป็นต้องเปลี่ยนแปลงสิ่งใดในมุมมอง และสิ่งนี้เกิดขึ้นบ่อยครั้งอย่างน่าประหลาดใจ การออกจากการเรียกการดึงข้อมูลในเมธอด build() ของคุณจะทำให้ API ล้นด้วยการเรียกที่ไม่จำเป็นและทำให้แอปของคุณช้าลง

โปรดอ่านซอร์สโค้ดที่สมบูรณ์

ยังมีจุดปลายสองสามจุดที่จะสร้างอินเทอร์เฟซสำหรับ แต่บทช่วยสอนที่ดีคืออะไรโดยไม่ต้องออกกำลังกาย 😂

บทสรุป

ในชุดโพสต์นี้ เรามาดูวิธีสร้าง API ส่วนที่เหลือแบบไร้เซิร์ฟเวอร์ด้วย Upstash ในขณะที่ใช้งานผ่านแอปพลิเคชันมือถือ

ฉันชอบที่จะได้เห็นสิ่งที่คุณสร้างต่อไปด้วย Upstash หรือวิธีปรับปรุงบทช่วยสอนนี้ให้เหมาะกับกรณีการใช้งานของคุณ

หากคุณพบว่างานชิ้นนี้มีประโยชน์ โปรดแชร์บนหน้าโซเชียลมีเดียของคุณ

มีคำถามหรือไม่? แสดงความคิดเห็น

หากคุณพบข้อผิดพลาด คุณรู้ว่าต้องทำอย่างไร แสดงความคิดเห็นและฉันจะดำเนินการโดยเร็วที่สุด

มีความสุขในการเข้ารหัส✌🏿

ข้อมูลอ้างอิง

  • เอกสารสำรอง
  • เรดิส
  • กระพือ
  • ดึงข้อมูลจากอินเทอร์เน็ต