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

السؤال

نشر

السلام عليكم ورحمة الله وبركاته

تحيه طيبه للجميع.

استفسار لو تكرمتو.

احاول استخدام timer ليعمل تشغيل دالة بشكل مستمر بعد وقت محدد الامر ناجح ولكن توجد مشكلة لو خرجنا من التطبيق ايضا التايمر شغال ولكن لو قام المستخدم باغلاق التطبيق كامل التايمر هنا يتوقف 

هل توجد طريقة تمنعه من التوقف تعمل على  المنصتين ؟ اندرويد / IOS?  في حالة اغلاق التطبيق كامل

Recommended Posts

  • 1
نشر

مرحباً,

بدايةً يجب توضيح أن اللغة التي بُرمج بها Flutter تُسمى Dart وهي لغة من بين عدة لغات مُعدة بنظام العرض-المترابط او المتزامن وهو نظام يُركز على تنفيذ الأوامر سطراً بسطر وحفظها سطر بسطر, كما هو الحال بالنسبة للزر الذي يحسب عدد مرات الضغط عليه

وهذا رابط لمقال مُفيد جداً يشرح الموضع بتعمق : Dart والبرمجة المتزامنة

لكن ما علاقة هذا بسؤالك؟

العلاقة هي أنه بفهم الطريقة التي بُرمج بها Flutter نستطيع إيجاد حل للمشكل 

الحل هو إعتماد خاصية العزل (Isolate) في تنفيذ الأمر الذي تريده (وفي حالتك إبقاء العداد شغال في الخلفية) , هذه الخاصية عند إضافتها في Dart ستسمح بتنفيذ أوامر في الخلفية بشكل منعزل عن باقي الأوامر التي يحتاجها التطبيق أثناء التصفح ويمكن تشغيل هذه الأوامر بصفة دورية (مثلاً كل 1000 جزء من الثانية).

والتالي هو مثال لكود العزل الذي نتحدث عنه, تستطيع نسخه وإعتماد نفس المبدأ في تنفيذ فكرة الـTimer

import 'dart:io';
import 'dart:async';
import 'dart:isolate';

Isolate isolate;

void start() async {
  ReceivePort receivePort= ReceivePort(); // مدخل العازل لإسقبال الرسائل
  isolate = await Isolate.spawn(runTimer, receivePort.sendPort);
  receivePort.listen((data) {
    stdout.write('إستقبل: ' + data + ', ');
  });
}

void runTimer(SendPort sendPort) {
  int counter = 0;
  Timer.periodic(new Duration(seconds: 1), (Timer t) {
    counter++;
    String msg = 'إشعار ' + counter.toString();  
    stdout.write('أرسل: ' + msg + ' - ');  
    sendPort.send(msg);
  });
}

void stop() {  
  if (isolate != null) {
      stdout.writeln('حذف العازل');
      isolate.kill(priority: Isolate.immediate);
      isolate = null;        
  }  
}

void main() async {
  stdout.writeln('جاري إعادة بدأ العازل');
  await start();
  stdout.writeln('إضغط أي رمز للخروج...');
  await stdin.first;
  stop();
  stdout.writeln('وداعاً');
  exit(0);
}

بالتوفيق

  • 0
نشر
بتاريخ 2 ساعات قال كريم أمعطيل:

مرحباً,

بدايةً يجب توضيح أن اللغة التي بُرمج بها Flutter تُسمى Dart وهي لغة من بين عدة لغات مُعدة بنظام العرض-المترابط او المتزامن وهو نظام يُركز على تنفيذ الأوامر سطراً بسطر وحفظها سطر بسطر, كما هو الحال بالنسبة للزر الذي يحسب عدد مرات الضغط عليه

وهذا رابط لمقال مُفيد جداً يشرح الموضع بتعمق : Dart والبرمجة المتزامنة

لكن ما علاقة هذا بسؤالك؟

العلاقة هي أنه بفهم الطريقة التي بُرمج بها Flutter نستطيع إيجاد حل للمشكل 

الحل هو إعتماد خاصية العزل (Isolate) في تنفيذ الأمر الذي تريده (وفي حالتك إبقاء العداد شغال في الخلفية) , هذه الخاصية عند إضافتها في Dart ستسمح بتنفيذ أوامر في الخلفية بشكل منعزل عن باقي الأوامر التي يحتاجها التطبيق أثناء التصفح ويمكن تشغيل هذه الأوامر بصفة دورية (مثلاً كل 1000 جزء من الثانية).

والتالي هو مثال لكود العزل الذي نتحدث عنه, تستطيع نسخه وإعتماد نفس المبدأ في تنفيذ فكرة الـTimer


import 'dart:io';
import 'dart:async';
import 'dart:isolate';

Isolate isolate;

void start() async {
  ReceivePort receivePort= ReceivePort(); // مدخل العازل لإسقبال الرسائل
  isolate = await Isolate.spawn(runTimer, receivePort.sendPort);
  receivePort.listen((data) {
    stdout.write('إستقبل: ' + data + ', ');
  });
}

void runTimer(SendPort sendPort) {
  int counter = 0;
  Timer.periodic(new Duration(seconds: 1), (Timer t) {
    counter++;
    String msg = 'إشعار ' + counter.toString();  
    stdout.write('أرسل: ' + msg + ' - ');  
    sendPort.send(msg);
  });
}

void stop() {  
  if (isolate != null) {
      stdout.writeln('حذف العازل');
      isolate.kill(priority: Isolate.immediate);
      isolate = null;        
  }  
}

void main() async {
  stdout.writeln('جاري إعادة بدأ العازل');
  await start();
  stdout.writeln('إضغط أي رمز للخروج...');
  await stdin.first;
  stop();
  stdout.writeln('وداعاً');
  exit(0);
}

بالتوفيق

هلا بك الغالي 

شكرا على ردك ي غالي

وتوضيح الفكره

لدي استفسار بس لو تكرمت /هل هذا الطريقة تجعل العدد لا يتوقف حتى لو قام المستخدم باغلاق التطبيق؟

  • 0
نشر

مبدئياً نعم, يجب ان يعما العداد حتى بعد إغلاق التطبيق

لكن في حال لم ينجح الأمر معك تستطيع إعتماد مصفوفة Android_Alarm_Manager لكن هذه فقط لأجهزة الأندرويد

مُرادفها في الـIOS هو UIBackgroundModes مع إعتماد setKeepAliveTimeout:handler: لإعادة تشغيل الأمر فور إغلاق التطبيق (من طرف النظام)

 

وكإضافة وبعيداً عن موضوع العداد, إذا كنت ستحتاج مثلاً إحداثيات المستخدم في كل مرة ولديك كود يقوم بالعملية في الخلفية فستحتاج طلب موافقة (الصلاحية) من المستخدم وبالتالي النظام لن يقوم بإيقاف أوامر التطبيق حتى بعد غلقه, أنصحك بقرائة التعليمات الخاصة ببرمجة تطبيقات الهواتف التي تعمل إما Android او IOS

  • 0
نشر
بتاريخ 1 ساعة قال كريم أمعطيل:

مبدئياً نعم, يجب ان يعما العداد حتى بعد إغلاق التطبيق

لكن في حال لم ينجح الأمر معك تستطيع إعتماد مصفوفة Android_Alarm_Manager لكن هذه فقط لأجهزة الأندرويد

مُرادفها في الـIOS هو UIBackgroundModes مع إعتماد setKeepAliveTimeout:handler: لإعادة تشغيل الأمر فور إغلاق التطبيق (من طرف النظام)

 

وكإضافة وبعيداً عن موضوع العداد, إذا كنت ستحتاج مثلاً إحداثيات المستخدم في كل مرة ولديك كود يقوم بالعملية في الخلفية فستحتاج طلب موافقة (الصلاحية) من المستخدم وبالتالي النظام لن يقوم بإيقاف أوامر التطبيق حتى بعد غلقه, أنصحك بقرائة التعليمات الخاصة ببرمجة تطبيقات الهواتف التي تعمل إما Android او IOS

شكرا لك اخي كفيت وفيت ربي يزيدك من واسع فضله

  • 0
نشر
بتاريخ 15 ساعات قال كريم أمعطيل:

مرحباً,

بدايةً يجب توضيح أن اللغة التي بُرمج بها Flutter تُسمى Dart وهي لغة من بين عدة لغات مُعدة بنظام العرض-المترابط او المتزامن وهو نظام يُركز على تنفيذ الأوامر سطراً بسطر وحفظها سطر بسطر, كما هو الحال بالنسبة للزر الذي يحسب عدد مرات الضغط عليه

وهذا رابط لمقال مُفيد جداً يشرح الموضع بتعمق : Dart والبرمجة المتزامنة

لكن ما علاقة هذا بسؤالك؟

العلاقة هي أنه بفهم الطريقة التي بُرمج بها Flutter نستطيع إيجاد حل للمشكل 

الحل هو إعتماد خاصية العزل (Isolate) في تنفيذ الأمر الذي تريده (وفي حالتك إبقاء العداد شغال في الخلفية) , هذه الخاصية عند إضافتها في Dart ستسمح بتنفيذ أوامر في الخلفية بشكل منعزل عن باقي الأوامر التي يحتاجها التطبيق أثناء التصفح ويمكن تشغيل هذه الأوامر بصفة دورية (مثلاً كل 1000 جزء من الثانية).

والتالي هو مثال لكود العزل الذي نتحدث عنه, تستطيع نسخه وإعتماد نفس المبدأ في تنفيذ فكرة الـTimer


import 'dart:io';
import 'dart:async';
import 'dart:isolate';

Isolate isolate;

void start() async {
  ReceivePort receivePort= ReceivePort(); // مدخل العازل لإسقبال الرسائل
  isolate = await Isolate.spawn(runTimer, receivePort.sendPort);
  receivePort.listen((data) {
    stdout.write('إستقبل: ' + data + ', ');
  });
}

void runTimer(SendPort sendPort) {
  int counter = 0;
  Timer.periodic(new Duration(seconds: 1), (Timer t) {
    counter++;
    String msg = 'إشعار ' + counter.toString();  
    stdout.write('أرسل: ' + msg + ' - ');  
    sendPort.send(msg);
  });
}

void stop() {  
  if (isolate != null) {
      stdout.writeln('حذف العازل');
      isolate.kill(priority: Isolate.immediate);
      isolate = null;        
  }  
}

void main() async {
  stdout.writeln('جاري إعادة بدأ العازل');
  await start();
  stdout.writeln('إضغط أي رمز للخروج...');
  await stdin.first;
  stop();
  stdout.writeln('وداعاً');
  exit(0);
}

بالتوفيق

حاولت اشغل الكود الذي ارسلته اخي وتظهر لدي المشكله التاليه:

 

E/flutter (29512): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Bad state: No element
E/flutter (29512): #0      Stream.first.<anonymous closure> (dart:async/stream.dart:1294:9)
E/flutter (29512): #1      _rootRun (dart:async/zone.dart:1182:47)
E/flutter (29512): #2      _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (29512): #3      _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (29512): #4      _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:410:13)
E/flutter (29512): #5      _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:420:15)
E/flutter (29512): #6      _BufferingStreamSubscription._close (dart:async/stream_impl.dart:305:7)
E/flutter (29512): #7      _SyncStreamControllerDispatch._sendDone (dart:async/stream_controller.dart:816:19)
E/flutter (29512): #8      _StreamController._closeUnchecked (dart:async/stream_controller.dart:671:7)
E/flutter (29512): #9      _StreamController.close (dart:async/stream_controller.dart:664:5)
E/flutter (29512): #10     _Socket._onData (dart:io-patch/socket_patch.dart:2027:21)
E/flutter (29512): #11     _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (29512): #12     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (29512): #13     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (29512): #14     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
E/flutter (29512): #15     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
E/flutter (29512): #16     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:808:19)
E/flutter (29512): #17     _StreamController._add (dart:async/stream_controller.dart:682:7)
E/flutter (29512): #18     _StreamController.add (dart:async/stream_controller.dart:624:5)
E/flutter (29512): #19     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1563:35)
E/flutter (29512): #20     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1045:18)
E/flutter (29512): #21     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (29512): #22     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (29512): 

هل تعلم ما هيا المشكلة؟

  • 0
نشر
بتاريخ 59 دقائق مضت قال كريم أمعطيل:

محتوى الـLog (سجل الاخطاء) طويل ويُظهر عدة مسارات

ستساعدني كثيراً في حل المشكل لو تذكر لي محتوى الاسطر بالظبط التي تظهر فيها الاخطاء وهل احد هذه الاسطر هو الكود الذي اقترحته عليك

اهلا اخي

انا عملت مشروع جديد وعلمت كوبي بست للكود الذي ارسلته لي وظهر لي هذا الخطاء فقط

  • 0
نشر

بداية تأكد من إعتمادك اخر إصدار من Flutter ثم بعد هذا الكود الذي طرحته لا يمكن إعتماده مباشرة في المشروع, لكن سأقوم بكتابة الكود لك حتى تتمكن من إعتماده بشكل مباشر ووضعه في ملف main.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:isolate';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Isolate Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Isolates'),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  Isolate _isolate;
  bool _running = false;
  static int _counter = 0;
  String notification = "";
  ReceivePort _receivePort;
 
  void _start() async {
    _running = true;
    _receivePort = ReceivePort();
    _isolate = await Isolate.spawn(_checkTimer, _receivePort.sendPort);
    _receivePort.listen(_handleMessage, onDone:() {
        stdout.writeln('جاري إعادة بدأ العازل');
    });
  }

  static void _checkTimer(SendPort sendPort) async {
    Timer.periodic(new Duration(seconds: 1), (Timer t) {
      _counter++;
      String msg = 'إشعار ' + counter.toString();  
      stdout.write('أرسل: ' + msg + ' - ');  
      sendPort.send(msg);
    });
  }

  void _handleMessage(dynamic data) {
    stdout.write('إستقبل: ' + data + ', ');
    setState(() {      
      notification = data;
    });
  }

  void _stop() {
    if (_isolate != null) {
      setState(() {
          _running = false; 
          notification = '';   
      });
      _receivePort.close();
      _isolate.kill(priority: Isolate.immediate);
      _isolate = null;        
      }
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              notification,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _running ? _stop : _start,
        tooltip: _running ? 'إيقاف العداد' : 'بدأ العداد',
        child: _running ? new Icon(Icons.stop) : new Icon(Icons.play_arrow),
      ),
      );
  }
}

وتأكد من ان ملف dart.exe موجود في المسار, وفي النهاية نفذ ببساطة الأمر (Command) التالي "dart main.dart" ليعمل التطبيق

يجب أن تحصل على نتيجة في الـconsole مثل :

جاري إعادة بدأ العازل
أرسل: إشعار 1 - إستقبل: إشعار 1,أرسل: إشعار 2 - إستقبل: إشعار 2,أرسل: إشعار 3 - إستقبل: إشعار 3,

 

  • 0
نشر
بتاريخ 7 ساعات قال كريم أمعطيل:

بداية تأكد من إعتمادك اخر إصدار من Flutter ثم بعد هذا الكود الذي طرحته لا يمكن إعتماده مباشرة في المشروع, لكن سأقوم بكتابة الكود لك حتى تتمكن من إعتماده بشكل مباشر ووضعه في ملف main.dart


import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:isolate';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Isolate Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Isolates'),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  Isolate _isolate;
  bool _running = false;
  static int _counter = 0;
  String notification = "";
  ReceivePort _receivePort;
 
  void _start() async {
    _running = true;
    _receivePort = ReceivePort();
    _isolate = await Isolate.spawn(_checkTimer, _receivePort.sendPort);
    _receivePort.listen(_handleMessage, onDone:() {
        stdout.writeln('جاري إعادة بدأ العازل');
    });
  }

  static void _checkTimer(SendPort sendPort) async {
    Timer.periodic(new Duration(seconds: 1), (Timer t) {
      _counter++;
      String msg = 'إشعار ' + counter.toString();  
      stdout.write('أرسل: ' + msg + ' - ');  
      sendPort.send(msg);
    });
  }

  void _handleMessage(dynamic data) {
    stdout.write('إستقبل: ' + data + ', ');
    setState(() {      
      notification = data;
    });
  }

  void _stop() {
    if (_isolate != null) {
      setState(() {
          _running = false; 
          notification = '';   
      });
      _receivePort.close();
      _isolate.kill(priority: Isolate.immediate);
      _isolate = null;        
      }
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              notification,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _running ? _stop : _start,
        tooltip: _running ? 'إيقاف العداد' : 'بدأ العداد',
        child: _running ? new Icon(Icons.stop) : new Icon(Icons.play_arrow),
      ),
      );
  }
}

وتأكد من ان ملف dart.exe موجود في المسار, وفي النهاية نفذ ببساطة الأمر (Command) التالي "dart main.dart" ليعمل التطبيق

يجب أن تحصل على نتيجة في الـconsole مثل :


جاري إعادة بدأ العازل
أرسل: إشعار 1 - إستقبل: إشعار 1,أرسل: إشعار 2 - إستقبل: إشعار 2,أرسل: إشعار 3 - إستقبل: إشعار 3,

 

اشكرك الغالي 

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...