ساخت ویجت با React Native برای iOS و اندروید – از صفر تا صد


در این مقاله با شیوه ساخت یک ویجت صفحه اصلی با React Native و اشتراک اطلاعات با اپلیکیشن ریاکت نیتیو آشنا میشویم. گرچه برای مطالعه این راهنما نیاز به پیشزمینه خاصی وجود ندارد، اما داشتن مقداری تجربه در زمینه توسعه اندروید و iOS به درک بهتر مطالب کمک خواهد کرد.
افزودن یک ویجت به اپلیکیشن حائز اهمیت بالایی است و عموماً تقاضای بالایی برای این قابلیت وجود دارد. متأسفانه امکان ساخت ویجت با استفاده مستقیم از ریاکت نیتیو وجود ندارد. دلیل این امر آن است که iOS محدودیت 16 مگابایت حافظه برای اکستنشنهای اپلیکیشن دارد و ریاکت نیتیو اغلب این مقدار را از همان آغاز مصرف میکند.
بنابراین به طور جایگزین باید هر ویجت را به صورت نیتیو با جاوا روی اندروید یا با سوئیفت روی iOS بسازیم. به طور معمول ویجت باید بتواند اطلاعت را با اپلیکیشن به اشتراک بگذارد که در این مورد یک اپلیکیشن ریاکت نیتیو خواهد بود. در این راهنما شیوه اجرای این وظیفه را نیز توضیح خواهیم داد.
ما نام پروژه خود را ReactNativeCreateWidgetTutorial گذاشتهایم و ظاهر آن روی هر دو پلتفرم مانند زیر است:
iOS
ابتدا بخش iOS را توضیح میدهیم.
ایجاد فایلهای ویجت
با باز کردن فایل workspace روی Xcode و رفتن به منوی File > New > Target ویجت را ایجاد میکنیم.
توجه داشته باشید که روی iOS به نام Today Extension خوانده میشود:
Today Extension را انتخاب کرده و روی Next کلیک کنید:
یک نام به آن بدهید و زبان ترجیحی خود را انتخاب کنید. در این مورد، از سوئیفت استفاده میکنیم. روی Finish کلیک کنید:
اگر Xcode از شما خواست scheme را فعال کنید، روی Activate کلیک کنید. اکنون باید پوشه ویجت را در پروژه خود ببیند:
در این مرحله ویجت باید روی صفحه نیز دیده شود و در واقع آن را هم اینک فعال کردهاید:
اینک ساختار ویجت را بررسی میکنیم. به پوشه Widget بروید و روی فایل استوریبورد کلیک کنید. سپس روی دکمه assistant-editor یعنی دکمهای به صورت دو دایره تودرتو در گوشه راست-بالای صفحه کلیک کنید.
چنان که میبینید دو تابع viewDidLoad و widgetPerformUpdate وجود دارند. تابع viewDidLoad هر بار که کاربر به صفحه ویجت سوئیچ میکند، اجرا خواهد شد. بنابراین جایی است که باید متغیرها، برچسب (Label)-ها و نما (View)-ها مقداردهی شوند. تابع widgetPerformUpdate هر زمان که نیاز باشد محتوای ویجت بهروزرسانی شود، فراخوانی میشود.
سفارشیسازی UI ویجت
چنان که میبینید یک برچسب با عنوان Hello World وجود دارد و این برچسب را با کشیدن روی کد سفارشیسازی میکنیم. روی برچسب راست-کلیک کنید و Referencing Outlet جدید را مستقیماً روی کد و درون کلاس بکشید.
بدین ترتیب رفرنس در کد به صورت زیر دیده میشود:
متن برچسب را درون تابع viewDidLoad ویرایش میکنیم:
اگر اپلیکیشن را اجرا کنید، میبینید که برچسب به طرز صحیحی مقداردهی شده است:
نکته: ویجت را بدون اجرای کل اپلیکیشن از سوی Xcode و انتخاب کردن ویجت به عنوان هدف و سپس کلیک روی run اجرا میکنیم:
ایجاد کانال ارتباطی بین ویجت و اپلیکیشن ریاکت نیتیو
اینک بخش جالب ماجرا فرا رسیده است. تلاش میکنیم نمایش ویجت از سوی اپلیکیشن ریاکت نیتیو کنترل شود. به این منظور باید روشی برای ارتباط بین اپلیکیشن ریاکت نیتیو با ویجت پیادهسازی کنیم. قصد داریم این کار را از طریق یک حافظه مشترک بین ویجت و اپلیکیشن ریاکت نیتیو اجرا کنیم. این کار با استفاده از ماژول نیتیو iOS به نام UserDefaults میسر است.
بدین ترتیب از اپلیکیشن ریاکت نیتیو میخواهیم که مقادیر مورد نظر را در UserDefaults بنویسد. ویجت نیز از آن بخواند. مشکل نخست این است که هیچ روش رسمی برای ریاکت نیتیو جهت تعامل با UserDefaults معرفی نشده است و کتابخانه مناسبی نیز به این منظور وجود ندارد. بنابراین تلاش میکنیم این مورد را خودمان با استفاده از ایجاد پلی بین ریاکت نیتیو و iOS نیتیو پیادهسازی کنیم.
ابتدا یک فضای مشترک درون اپلیکیشن خود ایجاد میکنیم که امکان ارتباط بین ویجت و اپلیکیشن را میدهد. این کار از طریق App Groups ممکن است که در زبانه Capabilities قرار دارد.
آن را فعال میکنیم و سپس گروه را انتخاب میکنیم و یا در صورت خالی بودن، آن را اضافه میکنیم:
اکنون که App Groups فعال شده است، روشی پیادهسازی میکنیم که ریاکت نیتیو با ایجاد پل نیتیو در UserDefaults بنویسد. پروژه خود را انتخاب کرده و روی افزودن فایل جدید کلیک کنید:
سپس Cocoa Touch Class را انتخاب کرده و روی Next کلیک کنید:
از آنجا که این حافظهای است که از سوی ویجت و اپلیکیشن ریاکت نیتیو به اشتراک گذاشته شده است، آن را SharedStorage مینامیم. در ادامه گزینه Objective-C را انتخاب کرده و روی Next کلیک کنید:
اکنون باید فایلهای جدید را در پروژه خود ببینید:
در این مرحله فایلها را ویرایش میکنیم. ابتدا کد زیر را در فایل SharedStorage.h کپی کنید:
کد زیر را نیز به فایل SharedStorage.m اضافه کنید:
نکته مهم: نام گروه را از group.com.createwidget.pimenta به نامی که در زمان ایجاد App Groups وارد کردید، عوض کنید.
اکنون باید بتوانید SharedStorage را روی ریاکت نیتیو فراخوانی کنید. چنان که در کد میبینید، تنها کاری که انجام میدهد، این است که یک JSON دریافت و آن را روی حافظه UserDefaults ذخیره میکند.
کنترل محتوای ویجت با اپلیکیشن ریاکت نیتیو
در سمت ریاکت نیتیو، ماژول را ایمپورت میکنیم:
سپس برخی دادهها را به حافظه اضافه میکنیم:
این کار، برای نمونه روی App.js، یا هر جای دیگری که برای تعیین دادهها در کد ریاکت نیتیو مناسب تشخیص دهید قابل انجام است:
اکنون تنها کاری که مانده این است که از ویجت بخواهیم دادهها را خوانده و آنها را در UI درج کند. ما قصد داریم ویجت را به UserDefaults وصل کنیم، دادههایش را بخوانیم و سپس دادهها را روی برچسب textLabel با نام Hello World نمایش دهیم. به این منظور به فایل TodayViewController.swift در پوشه ویجت بروید و تابع viewDidLoad را به صورت زیر ویرایش کنید:
اینک کل فایل TodayViewController.swift باید به صورت زیر در آمده باشد:
نکته مهم: نام گروه group.com.createwidget.pimenta را به نامی که در زمان ایجاد App Groups وارد کردید، عوض کنید.
اینک اپلیکیشن را اجرا میکنیم و ویجت را مورد بررسی قرار میدهیم. توجه کنید که باید اپلیکیشن را اجرا کرده و باز کنید تا بتوانید در SharedStorage بنویسد:
اینک بخش iOS ما به پایان رسیده است.
اندروید
در این بخش به کدنویسی بخش اندروید میپردازیم.
ایجاد فایلهای ویجت
پوشه اندروید را در اندروید استودیو باز کنید. سپس به اندروید استودیو بروید و روی res > New > Widget > App Widget راست-کلیک کنید:
ویجت خود را نامگذاری و پیکربندی کرده و سپس روی Finish کلیک کنید:
پنجره بعدی چندین فایل را نمایش میدهد که باید به پروژه اضافه شوند. فایل Widget.java جایی است که رفتار ویجت را کدنویسی میکنیم. بقیه فایل نیز به پیادهسازی کامپوننتهای UI ویجت اختصاص دارد. روی Add کلیک کنید:
اکنون اگر اپلیکیشن را اجرا کنید تا ویجت را ببینید. توجه کنید که اگر ابتدا بخش iOS را اجرا کرده باشید، خطوطی که در کد ریاکت نیتیو اقدام به فراخوانی SharedStorage میکنند را کامنت کنید، زیرا هنوز در اندروید پیادهسازی نشده است و موجب خطا میشود.
اینک ویجت ما اجرا شده است. در ادامه آن را اندکی سفارشیسازی میکنیم.
سفارشیسازی UI ویجت
در اندروید استودیو، پوشه اپلیکیشن را باز کنید و فایل زیر را انتخاب کنید:
res -> layout -> widget.xml
بدین ترتیب لیآوت ویجت باز میشود. چنان که میبینید، یک نمای متنی با عبارت EXAMPLE است. در صورتی که روی آن کلیک کنید، میتوانید جزییات بیشتری ببینید:
متن برچسب را عوض میکنیم. چنان که در مشخصات برچسب میبینید، متن به string/appwidget_text@ ارجاع میدهد. این مقدار در res > values > strings.xml قرار دارد. این فایل را باز کنید و متن تعریف شده را بیابید:
اینک این متن را از EXAMPLE به HELLO عوض کنید. سپس فایل را ذخیره کرده و اپلیکیشن را بار دیگر اجرا کنید. این وضعیت در ویجت به صورت زیر بازتاب مییابد:
اکنون میدانیم که چگونه ویجت را سفارشیسازی کنیم. در بخش بعدی روشی برای انجام این کار از طریق اپلیکیشن ریاکت نیتیو پیادهسازی میکنیم.
ایجاد کانال ارتباطی بین ویجت و اپلیکیشن ریاکت نیتیو
در این بخش کاری انجام میدهیم که نمایش ویجت از سوی اپلیکیشن ریاکت نیتیو کنترل شود. به این منظور باید روشی پیادهسازی کنیم که اپلیکیشن ریاکت نیتیو با ویجت ارتباط بگیرد. ما قصد داریم این کار را از طریق یک فضای مشترک بین ویجت و اپلیکیشن ریاکت نیتیو انجام دهیم این کار با استفاده از یک ماژول نیتیو اندروید به نام SharedPreferences انجام مییابد.
ابتدا کاری میکنیم که اپلیکیشن ریاکت نیتیو در SharedPreferences بنویسد و ویجت از آن بخواند. مشکل نخست این است که هیچ روش رسمی در ریاکت نیتیو برای تعامل با SharedPreferences وجود ندارد. کتابخانه مناسبی نیز به این منظور وجود ندارد. بنابراین مجبور هستیم خودمان یک روش پیادهسازی کنیم. برای فراخوانی SharedPreferences یک پل بین ریاکت نیتیو و اندروید نیتیو میسازیم. همچنین دو فایل در پروژه در کنار MainActivity.java به نامهای SharedStorage.java و SharedStoragePackager.java ایجاد میکنیم:
کد زیر را به فایل SharedStoragePackager.java کپی کنید:
کد زیر را نیز به فایل SharedStorage.java اضافه کنید:
نکته مهم: نام پکیج را از com.reactnativecreatewidgettutorial به نام مورد نظر خود تغییر دهید. همچنین نام Widget.class را به نام کلاس ویجت خود عوض کنید. اکنون میتوانید SharedStorage را روی ریاکت نیتیو فراخوانی کنید. چنان که در کد میبینید، تنها کاری که انجام میدهد، دریافت JSON و ذخیره آن در فضای SharedPreferences و سپس اعلان بهروزرسانی به ویجت است. برای این که اندروید بداند ماژولهای شما وجود دارند، باید آنها را به لیست پکیجها در فایل MainActivity.java اضافه کنید:
new SharedStoragePackager()
کنترل محتوای ویجت با اپلیکیشن ریاکت نیتیو
در سمت ریاکت نیتیو باید ماژول را ایمپورت کنیم.
نکته: اگر کد ریاکت نیتیو را از قبل ویرایش کردهاید، میتوانید این بخش را رد کنید:
سپس دادههایی به فضای ذخیرهسازی اضافه میکنیم:
این کار برای نمونه میتواند در فایل App.js یا هر جای دیگری که برای تعیین دادهها روی کد ریاکت نیتیو مناسب تشخیص میدهید، انجام شود:
اینک تنها بخش باقیمانده این است که کاری کنیم ویجت، دادهها را بخواند و آن را در UI درج کند. ما میخواهیم ویجت با SharedPreferences متصل شود، دادههای آن را بخواند و سپس دادهها را روی برچسب HELLO پرینت کند.
به این منظور به فایل Widget.java در پوشه Widget بروید و ماژولهای زیر را ایمپورت کنید:
سپس تابع updateAppWidget را به صورت زیر ویرایش کنید:
کد کامل فایل Widget.java به صورت زیر است:
تابع updateAppWidget را که مسئول بهروزرسانی محتوای ویجت است را ویرایش میکنیم تا ویجت بتواند دادهها را از پایگاه داده SharedPreferences بخواند و دادهها را بروی برچسب متنی نمایش دهد. اینک اپلیکیشن ریاکت نیتیو، محتوای ویجت را کنترل میکند. در این مرحله اپلیکیشن را اجرا میکنیم و ویجت را مورد بررسی قرار میدهیم. توجه کنید که باید اپلیکیشن را اجرا کرده و باز کنید تا بتواند در SharedStorage بنویسد.
اینک کدنویسی ما به پایان رسیده است. در این مرحله شما مبنایی به دست آوردهاید که میتوانید بقیه بخشهای ویجت را بر پایه آن بنویسید. نتیجه نهایی به صورت زیر است.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- مجموعه آموزشهای برنامهنویسی اندروید
- آموزش مقدماتی فریمورک React Native برای طراحی نرم افزارهای اندروید و iOS با زبان جاوا اسکریپت
- آموزش سوئیفت (Swift) — مجموعه مقالات مجله فرادرس
- کتابخانه React Native Navigation — راهنمای شروع به استفاده
==
من میخواستم یه برنامه درست کنم
که یه ویجت داشته باشه و اون ویجت از توی دیتابیس متن بگیره و متن توی ویجت هر ۲۴ ساعت یک بار تغییر کنه
ممنون میشم کمکم کنید