پرش به مطلب اصلی

ویجت Flutter سفارشی

با این ویجت می‌توانید کد Dart یک رابط Flutter را داخل صفحهٔ اپ‌ادیتور قرار دهید؛ مثلاً ماشین‌حساب، بازی، ابزار نمایش داده یا کنترل اختصاصی بسازید. ویجت سفارشی در چیدمان صفحه مانند دیگر ویجت‌ها قرار می‌گیرد و از طریق API ارتباطی، متغیرهای اپ را می‌خواند و عملکردهای تعریف‌شده در پنل را اجرا می‌کند.

برای استفاده از فایل‌های آمادهٔ این راهنما، کافی است فایل Dart و پارامترهای نمونه را وارد کنید. برای تغییر رفتار کد، آشنایی با Dart و Flutter لازم است.

نحوهٔ اجرا

کد هنگام ساخت خروجی اپ کامپایل می‌شود. شبیه‌ساز داخل پنل فعلاً جای ویجت و پیام ساخت خروجی را نمایش می‌دهد؛ کد سفارشی را اجرا نمی‌کند. برای دیدن نتیجه باید خروجی جدید بسازید و آن را اجرا کنید.

شروع سریع​

  1. صفحهٔ موردنظر را باز کنید و داخل یک گروه روی دکمهٔ افزودن ویجت بزنید.
  2. ویجت Flutter سفارشی را انتخاب کنید.
  3. نامی برای تشخیص ویجت در فهرست بنویسید.
  4. کد را در ویرایشگر قرار دهید یا با بارگذاری فایل دارت، فایل .dart را وارد کنید.
  5. اگر نمونه پارامتر دارد، آبجکت آن را در پارامترهای JSON بنویسید.
  6. در صورت نیاز، عملکردها را در فهرست عملکردهای همان ویجت با شناسهٔ مشخص اضافه کنید.
  7. در تنظیمات چیدمان، عرض و ارتفاع مناسب بدهید؛ برای نمونه‌های کارت‌مانند معمولاً عرض «به اندازه والد» و ارتفاع «به اندازه محتوا» مناسب است.
  8. ویجت و صفحه را ذخیره کنید، خروجی جدید بسازید و در اپ اجرا کنید.

برای اولین تجربه، ماشین‌حساب یا شمارنده را امتحان کنید.

تنظیمات فرم ویجت​

گزینهکاربرد
نام ویجتنام قابل‌شناسایی در فهرست ویجت‌های صفحه؛ عنوان داخل رابط را خود کد تعیین می‌کند
ویرایشگر کدنوشتن یا ویرایش سورس Dart همان ویجت
بارگذاری فایل دارتواردکردن محتوای یک فایل .dart به ویرایشگر
نمونه بازی 2048قراردادن سورس آمادهٔ بازی و پارامتر ارتفاع آن در فرم
بزرگ‌کردن ویرایشگربزرگ‌کردن پنجرهٔ تنظیمات برای ویرایش راحت‌تر
پارامترهای JSONتنظیمات ورودی مخصوص همین نمونه از ویجت
فهرست عملکردهاتعریف عملکردهای قابل‌فراخوانی از کد، با شناسهٔ دلخواه

تنظیمات عمومی مانند اندازه، فاصله، پس‌زمینه، شرط نمایش و انیمیشن از بخش‌های معمول تنظیمات ویجت در دسترس‌اند. تعامل‌هایی مثل دکمه و کشیدن انگشت داخل رابط سفارشی را در کد خود ویجت تعریف کنید.

قرارداد فایل Dart​

فایل باید تابعی با این نام و امضا داشته باشد:

import 'package:flutter/material.dart';
import 'package:my_app/appeditor/custom/AppEditorWidgetContext.dart';

Widget buildCustomWidget(
BuildContext context,
AppEditorWidgetContext app,
) {
return Padding(
padding: const EdgeInsets.all(16),
child: Text(app.params['title'] as String? ?? 'سلام از Flutter'),
);
}

پارامترهای این نمونه:

{
"title": "اولین ویجت من"
}
  • تابع باید یک Widget برگرداند. نام تابع و نوع ورودی‌ها را تغییر ندهید.
  • به main، runApp و MaterialApp جداگانه نیاز نیست؛ صفحه و پوستهٔ اپ از قبل وجود دارند.
  • می‌توانید کلاس‌های StatelessWidget، StatefulWidget و کلاس‌های کمکی را در همان فایل تعریف کنید.
  • پروژه‌های چندفایلی را فعلاً باید در یک فایل جمع کنید؛ import فایل نسبی و part پشتیبانی نمی‌شود.
  • سقف حجم کد هر ویجت ۲۵۶ کیلوبایت است.
  • برای سازگاری با پوستهٔ اپ، از Theme.of(context) استفاده کنید. جهت متن و چیدمان را در صورت نیاز با Directionality تعیین کنید.

ویجت دارای وضعیت​

برای ورودی، شمارنده، انیمیشن یا بازی، تابع را به یک StatefulWidget وصل کنید:

import 'package:flutter/material.dart';
import 'package:my_app/appeditor/custom/AppEditorWidgetContext.dart';

Widget buildCustomWidget(BuildContext context, AppEditorWidgetContext app) {
return TapWidget(app: app);
}

class TapWidget extends StatefulWidget {
const TapWidget({super.key, required this.app});
final AppEditorWidgetContext app;


State<TapWidget> createState() => _TapWidgetState();
}

class _TapWidgetState extends State<TapWidget> {
int count = 0;


Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('تعداد لمس: $count'),
);
}
}

این شمارنده فقط در وضعیت داخلی ویجت نگه‌داری می‌شود. برای اشتراک با دیگر بخش‌های اپ و ذخیرهٔ دائمی، نمونهٔ شمارندهٔ متصل به متغیر را ببینید.

پارامترهای JSON​

پارامترها تنظیمات هر نمونه از ویجت‌اند و از app.params خوانده می‌شوند. کد یکسان می‌تواند در دو ویجت قرار بگیرد، اما عنوان، رنگ، نام متغیر و رفتار متفاوت داشته باشد.

{
"title": "شمارنده سفارش‌ها",
"step": 5,
"storeOnDevice": true,
"variable": "order_count"
}
final title = app.params['title'] as String? ?? 'شمارنده';
final step = (app.params['step'] as num?)?.toDouble() ?? 1;
final storeOnDevice = app.params['storeOnDevice'] == true;
نوع تنظیمنمونهٔ کاربرد
ظاهر و متنعنوان، متن دکمه، اندازهٔ قلم، فاصله و رنگ
رفتارگام افزایش، سرعت انیمیشن، نمایش یک کنترل یا حالت دستی
اتصال به دادهنام متغیر ورودی یا خروجی برای هر نمونهٔ ویجت
دادهٔ اولیهمقدار آغازین، گزینه‌های فهرست یا تنظیمات یک بازی

پارامتر فقط زمانی اثر دارد که کد آن را بخواند. مثلاً اضافه‌کردن allowUndo به JSON بازی 2048 فعلی، دکمهٔ برگشت را غیرفعال نمی‌کند؛ کد نمونه فقط پارامتر height را مصرف می‌کند.

نکات نوشتن JSON:

  • مقدار اصلی باید یک آبجکت باشد؛ {} برای بدون پارامتر معتبر است.
  • نام کلید و رشته‌ها را با کوتیشن دوتایی بنویسید.
  • عدد را بدون کوتیشن و بولی را به‌صورت true یا false بنویسید.
  • از کامنت، ویرگول اضافه در پایان و کوتیشن تکی استفاده نکنید.
  • نام کلیدها به بزرگی و کوچکی حروف حساس است.
  • هنگام تغییر نام متغیر در یک نمونه، مطمئن شوید کد امکان اتصال مجدد را دارد؛ نمونه‌های شمارنده، قطب‌نما و تراز این اتصال را انجام می‌دهند.

پارامترها محل نگه‌داری رمز و اطلاعات محرمانه نیستند؛ آن‌ها بخشی از دادهٔ صفحه‌اند. مقدار زنده و قابل‌تغییر مثل امتیاز را در متغیر اپ قرار دهید.

API ارتباط با اپ​

APIکاربرد
app.paramsخواندن آبجکت پارامترهای همین ویجت؛ این Map در سطح اول فقط‌خواندنی است
app.getVar(name)خواندن مقدار خام یک متغیر، با زمینهٔ همان صفحه و ردیف لیست پویا
app.hasVar(name)بررسی وجود متغیر
await app.setVar(name, value)تغییر مقدار متغیری که قبلاً ساخته شده است
await app.addVar(name: ..., value: ...)ساخت متغیر؛ پیش‌فرض موقت و بدون بازنویسی مقدار قبلی
app.watchVar(name)Stream مقدار فعلی و تغییرات بعدی
app.hasAction(name)بررسی تعریف‌شدن شناسهٔ عملکرد در همین ویجت
await app.runAction(name)فراخوانی عملکرد نام‌دار با زمینهٔ همان صفحه
app.showMessage(text)نمایش پیام کوتاه
app.pageIdشناسهٔ صفحهٔ میزبان؛ ممکن است null باشد
app.mountedفعال‌بودن نمونه و صفحهٔ میزبان
app.previewتشخیص حالت پیش‌نمایش؛ پیش‌نمایش فعلی کد سفارشی را اجرا نمی‌کند

خواندن متغیر​

final name = app.getVar('customer_name')?.toString() ?? 'کاربر';
final rawScore = app.getVar('score');
final score = rawScore is num ? rawScore.toDouble() : 0.0;

مقدار متغیر لزوماً رشته نیست؛ ممکن است عدد، بولی، Map، List یا null باشد. خواندن با getVar به‌تنهایی رابط را هنگام تغییر مقدار بازسازی نمی‌کند؛ برای نمایش زنده از watchVar استفاده کنید.

ساخت، تغییر و ذخیرهٔ متغیر​

await app.addVar(name: 'score', value: 0);
await app.setVar('score', 10);

await app.addVar(
name: 'best_score',
value: 120,
storeOnDevice: true,
overwrite: true,
);
  • storeOnDevice: false، پیش‌فرض: مقدار موقت است و برای حفظ بین اجراهای اپ مناسب نیست.
  • storeOnDevice: true: مقدار روی همان دستگاه ذخیره می‌شود؛ به‌معنای ذخیره در سرور یا همگام‌شدن حساب کاربر نیست.
  • overwrite: false، پیش‌فرض: اگر متغیر در همان نوع ذخیره وجود داشته باشد، مقدار قبلی حفظ می‌شود.
  • overwrite: true: مقدار جدید جایگزین می‌شود.
  • setVar متغیر جدید نمی‌سازد. ابتدا با پنل یا addVar آن را ایجاد کنید.
  • برای addVar نام ساده مانند calculator_result انتخاب کنید؛ نقطه، مسیر آرایه و نام سیستمی برای ساخت متغیر مناسب نیست.
  • نام متغیرهای اپ مشترک است. دو نمونه با نام یکسان، دادهٔ یکدیگر را می‌بینند. برای استقلال، نام‌های متفاوت بدهید.
  • یک نام را هم‌زمان برای متغیر موقت و دستگاه استفاده نکنید. تغییر پارامتر نوع ذخیره، دادهٔ قبلی را به نوع جدید منتقل نمی‌کند.

نمایش زنده با StreamBuilder​

final values = app.watchVar('score');
// داخل build یک StatefulWidget که values را در initState نگه داشته است:
return StreamBuilder<dynamic>(
stream: values,
builder: (context, snapshot) {
return Text('امتیاز: ${snapshot.data ?? 0}');
},
);

در یک StatefulWidget، Stream را در initState بسازید و در فیلد نگه دارید؛ در هر build یک Stream جدید نسازید. اگر نام متغیر یا شیء app تغییر کرد، در didUpdateWidget اتصال را به‌روز کنید. StreamBuilder هنگام تعویض Stream یا حذف ویجت، اشتراک قبلی را لغو می‌کند. نمونه‌های آماده این الگو را نشان می‌دهند.

اجرای عملکردهای پنل​

  1. در فهرست عملکردهای ویجت، یک عملکرد اضافه کنید؛ مثلاً بازکردن صفحه، نمایش پیام یا تغییر متغیر.
  2. در ستون شناسه، نامی مانند onResult بنویسید.
  3. همین نام را با رعایت حروف بزرگ و کوچک در کد فراخوانی کنید.
if (app.hasAction('onResult')) {
await app.runAction('onResult');
}

شناسه، نام اتصال داخل همین ویجت است؛ لازم نیست کد Dart تنظیمات عملکرد را بداند. مثلاً در ماشین‌حساب، پس از نوشتن نتیجه در متغیر، onResult اجرا می‌شود. با تغییر عملکرد پنل، می‌توانید نتیجه را در صفحهٔ دیگری نمایش دهید.

شرط‌ها و زمینهٔ صفحه در مسیر عادی اجرای عملکرد اعمال می‌شوند. عملکردی که شرطش برقرار نباشد ممکن است اجرا نشود. فراخوانی نام تعریف‌نشده خطا ایجاد می‌کند؛ برای عملکرد اختیاری از hasAction استفاده کنید. await فراخوانی را مرتب می‌کند، اما لزوماً به‌معنای پایان همهٔ اثرهای بعدی مثل انیمیشن یا کارهای پس‌زمینهٔ آن عملکرد نیست.

try {
await app.runAction('onResult');
} catch (error) {
app.showMessage('اجرای عملکرد ممکن نشد.');
}

امکانات تکمیلی Context​

APIرفتار
app.interpolate(text)جایگذاری متغیرهای متن با زمینهٔ صفحه و ردیف فعلی
await app.removeVar(name)حذف متغیر؛ متغیر سیستمی حذف نمی‌شود
await app.openPage(id, query: ..., replace: false)بازکردن صفحه؛ پشتیبانی از removeUntil، displayMode: 'dialog' / 'sheet'، widthRatio، heightRatio و dismissible
app.closePage()بستن صفحه یا لایهٔ دیالوگ/شیت فعلی
await app.openLink(url, inner: false, useCustomTab: false)بازکردن لینک با جایگذاری متغیرها
await app.showDialog(title: ..., message: ..., buttonText: ...)دیالوگ ساده
await app.copyText(text)، await app.pasteText()نوشتن و خواندن کلیپ‌بورد؛ خواندن ممکن است null برگرداند
await app.shareText(text)اشتراک متن
await app.vibrate(duration: 500)لرزش با مدت میلی‌ثانیه
await app.openDialer(number)بازکردن شماره‌گیر؛ نتیجهٔ bool
await app.openEmail(email, subject: ..., body: ...)بازکردن برنامهٔ ایمیل؛ نتیجهٔ bool
await app.openImage(src, shareAble: true)نمایش تصویر
await app.openVideo(src, position: ..., shareAble: true, saveAble: true)نمایش ویدئو؛ position از نوع Duration
app.previewآیا برنامه در حالت پیش‌نمایش است

این توابع از عملکردهای موجود Act استفاده می‌کنند و محدودیت پلتفرم همان عملکردها را دارند؛ مثلاً کپی و اشتراک متن در وب توسط Act اجرا نمی‌شود. عملیات پس از dispose اجرا نمی‌شوند؛ ارسال درخواست در این وضعیت StateError می‌دهد. درخواست شروع‌شده با dispose لغو نمی‌شود؛ پیش از تغییر UI بعد از await، app.mounted و mounted ویجت خودتان را بررسی کنید.

ارسال درخواست​

request از Requester مشترک اپ استفاده می‌کند و sys.rest.loading را به‌روز می‌کند. مقدار پیش‌فرض متد GET و نوع بدنه JSON است. متدهای RequestType.Get، Post، Put، Patch و Delete پشتیبانی می‌شوند. این نوع‌ها و MyResponse، ResponseErrorType، FormData و MultipartFile از فایل Context export شده‌اند.

final result = await app.request(
'https://example.com/api/items',
method: RequestType.Post,
queryParameters: {'page': 1},
headers: {'Authorization': 'Bearer ${app.getVar('token')}'},
data: {'title': 'عنوان جدید'},
);
if (!app.mounted) return;
if (result.success) {
await app.setVar('items', result.data);
} else {
app.showMessage('خطای درخواست: ${result.errorType}');
}

queryParameters برای همهٔ متدها قابل استفاده است و کلیدهای هم‌نام در URL را جایگزین می‌کند. URL باید کامل و HTTP/HTTPS باشد؛ متغیرهای URL با زمینهٔ صفحه جایگذاری می‌شوند. مقادیر بدنه و هدر را مستقیماً با getVar یا interpolate بسازید. توکن ورود اپ خودکار به سرویس مقصد ارسال نمی‌شود.

برای فرم معمولی contentType: 'application/x-www-form-urlencoded' و data بدهید. برای آپلود، formData: FormData.fromMap({...}) بدهید؛ نوع محتوا خودکار multipart می‌شود و نباید هم‌زمان data بدهید. پارامتر responseType یکی از json (پیش‌فرض؛ آبجکت یا آرایه)، raw (دادهٔ پردازش‌شدهٔ Dio) یا xml است. پاسخ شامل data، success، hasError، errorType و response است؛ کد HTTP در result.response?.statusCode قرار دارد. خطاهای شبکه و HTTP در همین نتیجه برمی‌گردند. خطاهای آرگومان استثنا می‌دهند.

زمان‌های انتظار مثبت و برحسب ثانیه‌اند: connectTimeoutSeconds: 10، sendTimeoutSeconds: 10 و receiveTimeoutSeconds: 30. در خروجی وب، سرویس مقصد باید CORS مناسب داشته باشد.

نمونه‌های آماده​

هر نمونه فایل مستقل Dart، پارامترهای پیشنهادی و روش استفاده دارد:

نمونهچه چیزی یاد می‌گیرید؟وضعیت
ماشین‌حسابورودی، محاسبه، نوشتن نتیجه و اجرای عملکردبدون وابستگی جدید
شمارندهخواندن زنده، متغیر مشترک و ذخیره روی دستگاهبدون وابستگی جدید
قطب‌نمانمایش زاویه، اتصال به متغیر و کنترل دستیحالت دستی و سنسور
ترازدو ورودی زنده، آستانه و نمایش شیبحالت دستی و سنسور
سنسورهادادهٔ زنده، وضعیت، شروع و توقف و خطامتصل به عملکرد سنسور پنل
بازی 2048تبدیل بازی به ویجت، امتیاز، رکورد و رویدادهانمونهٔ آمادهٔ پنل

پکیج‌ها، پلاگین‌ها و سنسورها​

نسخهٔ فعلی فقط اجازهٔ استفاده از پکیج‌های موجود در همان خروجی و با همان نسخه‌ها را می‌دهد. این ویجت تنظیمی برای افزودن پکیج یا تغییر pubspec، Gradle، Manifest و فایل‌های بومی ندارد.

  • import کتابخانه‌های Dart مانند dart:math و dart:async و APIهای Flutter مجاز است.
  • از پکیج موجود می‌توانید استفاده کنید؛ مثلاً dio، shared_preferences یا flutter_svg، اگر در همان خروجی حاضر باشد.
  • برای پکیج‌های شرطی، فعال‌بودن قابلیت مربوط در خروجی اهمیت دارد.
  • از فایل‌های داخلی اپ‌ادیتور فقط SDK ویجت با مسیر معرفی‌شده قابل import است.
  • import نسبی، part و پکیج نصب‌نشده پذیرفته نمی‌شود.
  • موجودبودن یک پکیج به‌معنای پشتیبانی تمام قابلیت‌های آن روی همهٔ پلتفرم‌ها نیست. قابلیتی که به تنظیم بومی جدید نیاز دارد در این مرحله قابل اضافه‌کردن نیست.
سنسورها در خروجی جدید

sensors_plus: 6.1.2 فعال است. عملکردهای «شروع سنسور» و «توقف سنسور» دادهٔ شتاب‌سنج، شتاب حرکت، ژیروسکوپ و تکان را در متغیر موقت می‌نویسند؛ با watchVar آن را بخوانید یا عملکرد را با runAction اجرا کنید. Context متد مستقلی مثل startSensor ندارد. تراز این راهنما به خروجی شتاب‌سنج وصل می‌شود و قطب‌نما در حالت sensor: true مستقیماً مغناطیس‌سنج پکیج را می‌خواند.

پکیج‌های فعال در خروجی​

فهرست زیر از تنظیمات سازندهٔ فعلی اپ‌ادیتور استخراج شده است؛ نسخه‌ها نسخهٔ خروجی هستند، نه الزاماً آخرین انتشار پکیج. در خروجی قدیمی ممکن است متفاوت باشند. SDKهای Dart و Flutter (از جمله material.dart، widgets.dart، services.dart، dart:async، dart:math و dart:convert) نیز در دسترس‌اند. برای هر پکیج، import عمومی خود آن را بنویسید؛ برای مثال:

import 'package:sensors_plus/sensors_plus.dart';
import 'package:flutter_svg/flutter_svg.dart';
پکیج فعالنسخه در سازنده
cupertino_icons1.0.8
path_provider2.1.5
dio5.9.0
xml6.6.1
webfeed_plus1.1.2
flutter_widget_from_html0.17.1
flutter_widget_from_html_core0.17.0
flutter_inappwebview6.1.5
validators3.0.0
cached_network_image3.4.1
flutter_svg2.2.2
flutter_sequence_animation4.0.0-nullsafety
shared_preferences2.5.3
flutter_spinkit5.2.2
flutter_xlider3.5.0
photo_view0.15.0
card_swiper3.0.1
flutter_custom_tabs2.4.0
mime2.0.0
internet_connection_checker_plus3.1.1
connectivity_plus7.3.1
just_audio0.10.5
audio_session0.2.2
audio_service0.18.18
rxdart0.28.0
percent_indicator4.2.5
device_info_plus11.5.0
simple_barcode_scanner0.6.0
wakelock_plus1.4.0
video_player2.10.1
chewie1.13.0
sqflite2.4.3
pinput1.2.2
image4.5.4
image_picker1.1.2
image_cropper11.0.0
flutter_secure_storage9.2.4
shamsi_date1.1.1
timeago3.7.1
intl0.19.0
encrypt5.0.3
archive4.0.7
substring_highlight1.0.33
page_route_animator1.0.4
share_plus12.0.1
permission_handler12.0.3
vibration3.2.1
sensors_plus6.1.2
flutter_local_notifications22.2.0
flutter_timezone5.0.1
timezone0.11.1
flutter_js0.8.7
sqflite_common_ffi2.4.1
sqflite_common_ffi_web1.1.2
syncfusion_flutter_pdfviewer30.2.7
window_manager0.5.1

پکیج‌های زیر شرطی هستند و صرفِ وجود ویجت سفارشی آن‌ها را فعال نمی‌کند:

پکیجنسخهشرط فعال‌شدن
adivery4.9.0تبلیغات ادیوری در خروجی فعال باشد
tapsell_plus2.3.2تبلیغات تپسل در خروجی فعال باشد
firebase_core، firebase_messaging4.13.0، 16.5.0قابلیت اعلان مربوط در سازنده فعال و خروجی Android باشد
flutter_poolakey2.2.0+1.0.0پرداخت درون‌برنامه‌ای بازار با سیستم پرداخت فروشگاه
myket_iap1.1.12پرداخت درون‌برنامه‌ای مایکت با سیستم پرداخت فروشگاه

flutter_compass در این فهرست نیست. برای مثال قطب‌نما از مغناطیس‌سنج sensors_plus استفاده شده است. وابستگی‌های غیرمستقیم و پکیج‌های تست را قرارداد ثابت ویجت در نظر نگیرید. حضور پکیج به‌معنای آماده‌بودن تنظیمات بومی، مجوزها یا پشتیبانی همهٔ APIها در وب/Windows نیست. نمونهٔ سنسورها و راهنمای رسمی نسخهٔ پکیج محدودیت‌های سنسور را توضیح می‌دهند.

چیدمان و چرخهٔ عمر​

  • برای ابزارهای کارت‌مانند، ارتفاع «به اندازه محتوا» را انتخاب کنید.
  • برای بازی یا رابطی با صفحهٔ کامل، ارتفاع مشخص یا اندازهٔ مناسب والد بدهید؛ Expanded داخل ارتفاع نامحدود خطا ایجاد می‌کند.
  • پیش از استفاده از LayoutBuilder یا اندازهٔ صفحه، محدودیت‌های والد را در نظر بگیرید؛ نمونهٔ 2048 برای ارتفاع آزاد مقدار جایگزین دارد.
  • متغیر را داخل build تغییر ندهید و از آنجا عملکرد اجرا نکنید؛ بازسازی‌های رابط ممکن است این کار را چندبار تکرار کنند.
  • کار آغازین را در initState و در صورت نیاز پس از اولین frame انجام دهید.
  • پس از await، قبل از setState یا ادامهٔ کار رابط، mounted را بررسی کنید.
  • Timer، StreamSubscription، TextEditingController و AnimationControllerهای خودتان را در dispose آزاد کنید.

ذخیره، انتشار آنلاین و ساخت خروجی​

تغییرآیا خروجی جدید لازم است؟
تغییر کد Dart، حتی عنوانی که داخل سورس نوشته شدهبله
تغییر مقدار پارامتری که کد موجود از قبل مصرف می‌کندخیر؛ ذخیره و انتشار صفحه کافی است، به‌شرط دریافت نسخهٔ جدید صفحه توسط اپ
تغییر عملکردهای نام‌دارمعمولاً خیر؛ اگر قابلیت یا منابع لازم در خروجی قبلی موجود باشد
تغییر مقدار متغیر در اپخیر
افزودن پکیج یا تنظیم بومی جدیددر این قابلیت پشتیبانی نمی‌شود

متن سورس با تنظیمات ویجت در پنل ذخیره می‌شود. در خروجی ساخته‌شده، کد به فایل Dart تبدیل می‌شود و دادهٔ صفحه فقط شناسهٔ کد کامپایل‌شده را دارد. انتشار آنلاین سورس جدید، آن را روی نسخهٔ قدیمی نصب‌شده قابل‌اجرا نمی‌کند؛ اپ برای کد ناشناخته پیام ساخت خروجی جدید نمایش می‌دهد.

چند ویجت با سورس یکسان از یک فایل کامپایل‌شده استفاده می‌کنند. وضعیت معمول StatefulWidget و پارامترهای هر نمونه جداست، اما متغیرهای سراسری و static در فایل Dart مشترک‌اند؛ برای دادهٔ مخصوص یک نمونه از آن‌ها استفاده نکنید.

رفع اشکال​

مشکلبررسی پیشنهادی
شبیه‌ساز فقط پیام نشان می‌دهدرفتار فعلی است؛ نمونه را در خروجی ساخته‌شده اجرا کنید
«کد این ویجت در این نسخه از اپ وجود ندارد»سورس صفحه با خروجی نصب‌شده متفاوت است؛ خروجی جدید بسازید
خطای تابع buildCustomWidgetنام، امضا و نوع بازگشتی را با نمونهٔ قرارداد مقایسه کنید
خطای وابستگی نامجازپکیج باید از قبل در همان خروجی موجود باشد؛ import نسبی و part را حذف کنید
خطای کامپایل Dartگزارش ساخت را بخوانید؛ امضاها، نوع داده‌ها و API پکیج‌ها را بررسی کنید
پارامتر اثر نداردکلید و نوع مقدار را بررسی کنید و مطمئن شوید کد آن را مصرف می‌کند
متغیر نمایش داده نمی‌شودنام دقیق، ایجادشدن متغیر، نوع داده و استفاده از watchVar را بررسی کنید
عملکرد اجرا نمی‌شودشناسه، تعریف آن در همان ویجت، شرط عملکرد و فعال‌بودن صفحه را بررسی کنید
خطای اندازه یا overflowمحدودیت والد، ارتفاع آزاد، Expanded و اندازهٔ ثابت را بررسی کنید
قطب‌نما یا تراز با حرکت گوشی تغییر نمی‌کندبرای تراز sensorVariable و عملکرد شروع سنسور، برای قطب‌نما sensor: true و وجود مغناطیس‌سنج دستگاه را بررسی کنید

خطا در ساخت اولیهٔ ویجت ممکن است با پیام خطا نمایش داده شود؛ خطاهای فرزندان، callbackها و عملیات غیرهم‌زمان همچنان به رسیدگی داخل کد نیاز دارند. کد سفارشی بخشی از خود اپ است و محیط اجرای جدا و محدودشده ندارد؛ فایل‌هایی را وارد کنید که رفتارشان را می‌شناسید.

مطالب مرتبط​