اذهب إلى المحتوى

السؤال

نشر

اقوم بتعلم تطوير التطبيقات بواسطة flutter منذ شهر، حيث أقوم بتنفيذ تطبيقات تدريبية لممارسة ما أتعلمه.
أحاول جلب 500 تعليق كـJSON  من الرابط التالي: https://jsonplaceholder.typicode.com/comments ومن ثم عرضها في ListView.
لاحظت بطئ وعدم إستجابة مؤقتة في عناصر واجهة المستخدم للتطبيق عند جلب عدد كبير من البيانات من الانترنت بواسطة الاضافة http  حيث أن ProgressIndicator تتوقف عن الدوران  وتصبح بطيئة.
هذا هو الكود :

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      theme: ThemeData(

        primarySwatch: Colors.blue,

        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text('Hello'),
      ),
      body:FutureBuilder(
        future: getData(),
        builder: (context,AsyncSnapshot<List> snapshot){


              if(snapshot.hasData){
                return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context,i){

                      return ListTile(title: Text('comment:${snapshot.data[i]['email']}'));

                });
              }
              else{
                return Center(child: CircularProgressIndicator());
              }
          }
        ),
      );

  }

  Future<List> getData() async{
    
    var response = await http.get('https://jsonplaceholder.typicode.com/comments');

    return jsonDecode(response.body);

  }



}

شكرا لكم.

Recommended Posts

  • 1
نشر

البطئ وعدم الإستجابة ناتج عن معالجة 500 تعليق وبالتالي إجهاد الـmain thread الخاصة بالتطبيق ومنعه من الإستجابة والتفاعل مع المستخدم خلال معالجته للتعليقات، بدلا من ذلك يجب تنفيذ العمليات التي تستغرق وقتاً في المعالجة في Thread أُخرى معزولة كلياً لكي لا تؤثر على عناصر الواجهة الخاصة بالتطبيق.
توفر لغة دارت الدالة compute التي تمكنك من تنفيذ دالة ما بمعزل عن الـ main thread الرئيسية ومن ثم إرجاع قيمة.

إليك الشكل العام للدالة compute مع التوضيح:

var data = compute(function, argument);// تأخذ معاملان وهما إسم الدالة التي تريد تنفيذها
  //و المعامل الذي نريد إضافته للدالة 
//نحفظ البيانات التي ترجعها الدالة
//compute
//في المتغير 
//data
  
  
static myFunc(String response){  // يجب ان تكون الدالة static
	//هنا نقوم بتنفيذ العمليات التي تستغرق وقتاً طويلاً بحيث لا تؤثر على اداء التطبيق
}

إليك الكود بعد تعديله وإضافة تحويل البيانات في thread أخرى معزولة عن الـmain thread :

import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      theme: ThemeData(

        primarySwatch: Colors.blue,

        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text('Hello'),
      ),
      body:FutureBuilder(
        future: getData(),
        builder: (context,AsyncSnapshot<List> snapshot){

          print('try');

              if(snapshot.hasData){
                return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context,i){

                      return ListTile(title: Text('comment:${snapshot.data[i]['body']}'));

                });
              }
              else{
                return Center(child: CircularProgressIndicator());
              }
          }
        ),
      );

  }

  Future<List> getData() async{
    
    var response = await http.get('https://jsonplaceholder.typicode.com/comments'); // جلب البيانات

    //List mapList = jsonDecode(response.body);
    return compute(responseToJson,response.body); // نقوم بتحويل البيانات في الخلفية وليس في 
	//thread الرئيسية
    //الخاصة بالتطبيق

  }

  static List responseToJson(String body){ // يجب أن تكون الدالة الذي تنفذها
    // compute 
    //من نوع
    //static
    // او global

    return jsonDecode(body);

  }

}


 

  • 0
نشر

لتجنب عدم الاستجابة عند الاتصال بأي api في تطبيق flutter يجب استخدام دالة compute وهذه الدالة تقوم بتشغيل الوظائف المجهدة في الخلفية بحيث لا تؤثر على التطبيق. 

أيضا من النصائح المتبعة ايضا هي اضافة البيانات المرجعة من api في كلاس Model بحيث تستطيع جلب البيانات وتخزينها في هذا الكلاس Model بحيث تقلل عملية الاستجابة ووقت التنفيذ. 

الشكل العام لهذه الدالة هو 

var getData = await compute(function, parameter);

بحيث function هي المستقبل أو الوظيفة التي نمررها إلى الدالة.

parameter هي البيانات التي تمرر الى function.

يمكنك مراجعة دالة compute من هنا

ولقد عدلت على الكود الخاص بك واصبح سربعا في الاستجابة 

import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Hello'),
      ),
      body: FutureBuilder<List<Welcome>>(
        future: getData(),
        builder: (context, AsyncSnapshot<List> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return Center(
                child: Text('No Connection'),
              );
              break;
            case ConnectionState.waiting:
            case ConnectionState.active:
              return Center(
                child: CircularProgressIndicator(),
              );
              break;
            case ConnectionState.done:
              if (snapshot.hasError) print(snapshot.error);

              return snapshot.hasData
                  ? WelcomeList(welcome: snapshot.data)
                  : Center(
                      child: CircularProgressIndicator(),
                    );
              break;
          }
          return Container();
        },
      ),
    );
  }

  Future<List<Welcome>> getData() async {
    var response =
        await http.get('https://jsonplaceholder.typicode.com/comments');
    return compute(welcomeFromJson, response.body);
  }
}

// To parse this JSON data, do
//
//     final welcome = welcomeFromJson(jsonString);

List<Welcome> welcomeFromJson(String str) =>
    List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));

String welcomeToJson(List<Welcome> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Welcome {
  Welcome({
    this.postId,
    this.id,
    this.name,
    this.email,
    this.body,
  });

  int postId;
  int id;
  String name;
  String email;
  String body;

  factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
        postId: json["postId"],
        id: json["id"],
        name: json["name"],
        email: json["email"],
        body: json["body"],
      );

  Map<String, dynamic> toJson() => {
        "postId": postId,
        "id": id,
        "name": name,
        "email": email,
        "body": body,
      };
}

class WelcomeList extends StatelessWidget {
  final List<Welcome> welcome;

  WelcomeList({Key key, this.welcome}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: welcome.length,
      itemBuilder: (context, i) {
        return ListTile(
          title: Text('comment:${welcome[i].name}'),
        );
      },
    );
  }
}

وهذه صورة من النتيجة 

66.PNG

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...