نحوه کار بر روی یک پروژه چند کتابخانه ای در اندروید – به صورت محلی و از راه دور

در این مقاله قصد داریم در مورد پروژه های چند کتابخانه ای در اندروید صحبت کنیم. این یک چیز معمولی نیست، اما چیزی غیرعادی هم نیست.
ممکن است در خط کاری خود با پروژه های چند کتابخانه ای مواجه شده باشید، یا ممکن است به دنبال تبدیل کتابخانه خود به ماژول های فرعی برای ساختار و سازماندهی بهتر باشید. مهم نیست، قبل از غواصی باید به خوبی از آنچه در مقابل شما قرار دارد آگاه باشید.
نوشتن کتابخانه خود در اندروید بسیار ساده است. شما فرصتی برای نوشتن کدی دارید که می تواند به توسعه دهندگان دیگر (یا حتی خودتان) کمک کند.
از آنجایی که کتابخانه ها به تنهایی نمی توانند یک پروژه مستقل باشند، معمولا همیشه در یک پروژه با یک برنامه کاربردی جفت می شوند. این اجازه می دهد تا توسعه کتابخانه یک فرآیند ساده باشد که در آن یک ویژگی را اضافه می کنید/یک اشکال را برطرف می کنید و سپس می توانید آن را مستقیماً با برنامه ای که در پروژه دارید آزمایش کنید. پس ، شبیه سازی (به روش محلی) که چگونه یک توسعه دهنده کتابخانه شما را یکپارچه می کند.
اما، اگر کتابخانه شما به کتابخانه دیگری که در حال توسعه آن هستید متکی باشد، چه؟
اگر از آن آگاه نیستید، باید بدانید که یک کتابخانه (بخوانید aar) نمی تواند کتابخانه محلی دیگری را در خود داشته باشد. می تواند از راه دور به کتابخانه ها (از طریق وابستگی ها) تکیه کند، اما نه به چیزی محلی.
این در اندروید پشتیبانی نمیشود، و در حالی که برخی از راهحلها در طول سالها ظاهر میشوند ( FatAar )، اینها همیشه مشکل را حل نمیکنند و بهروز نیستند. حتی یک Google Issue Tracker وجود دارد که این ویژگی را درخواست می کند که مدت زیادی است باز شده است و توجه زیادی را از طرف جامعه دریافت می کند. اما بیایید تشخیص دهیم که کدام دیوارها را می توانیم بشکنیم و کدام را نمی توانیم.
تصور کنید سلسله مراتب پروژه شما به شکل زیر است:
-- App | -- OuterLib | --- InnerLib
پس ، از آنجایی که InnerLib نمی تواند بخشی از پروژه اصلی شما باشد، کجا می تواند اقامت داشته باشد؟ و همچنین چگونه می توانید هنگام توسعه ویژگی های داخل InnerLib به صورت محلی کار کنید؟
در این مقاله قصد داریم به این سوالات پاسخ دهیم.
زیر ماژول Git
برای اکثر مشکلات فنی، همیشه تنها یک راه حل وجود ندارد. معمولاً موارد بیشتری وجود دارد، اما هر راه حل دارای معایبی است. این همه این سوال است که در پایان روز با کدام معایب زندگی راحتتری دارید.
برای پاسخ به سوال اول ما، که InnerLib در کجا می تواند اقامت داشته باشد، چندین گزینه داریم:
اگر از زیر ماژول ها در Git آگاه نیستید، مستندات Git مکان خوبی برای آشنایی با آنها است. به نقل از آن (بند اول):
اغلب اتفاق می افتد که در حین کار بر روی یک پروژه، باید از پروژه دیگری از درون آن استفاده کنید. 👉 شاید این کتابخانه ای باشد که شخص ثالثی آن را توسعه داده یا شما به طور جداگانه در حال توسعه آن هستید و در چندین پروژه والدین از آن استفاده می کنید. 👈 یک مسئله رایج در این سناریوها به وجود می آید: شما می خواهید بتوانید دو پروژه را جداگانه در نظر بگیرید اما همچنان بتوانید از یکی از داخل دیگری استفاده کنید.
این پاراگراف به ما نشان می دهد که این دقیقاً مورد استفاده م است. استفاده از ساب ماژول مزایای خود را دارد. همه کدهای شما در یک مکان هستند، مدیریت آن آسان است و به راحتی قابل توسعه به صورت محلی است.
اما ساب ماژول ها نقاط ضعفی دارند. یکی این واقعیت است که شما همیشه باید آگاه باشید که زیر ماژول شما به کدام شاخه اشاره می کند. سناریویی را تصور کنید که در یک شاخه انتشار در مخزن اصلی خود هستید و ماژول فرعی شما در یک شاخه ویژگی قرار دارد. اگر متوجه نشدید، نسخه ای از کد خود را با چیزی که برای تولید آماده نیست منتشر می کنید. اوف
اکنون در تیمی از توسعه دهندگان به این موضوع فکر کنید. یک اشتباه بی دقت می تواند گران تمام شود.
اگر گزینه اول برای شما مشکل ساز به نظر می رسد، میزبانی کتابخانه خود در مخزن دیگری انتخاب دوم شم است. راه اندازی مخزن بسیار ساده است، اما اکنون چگونه به صورت محلی کار می کنید؟
کار به صورت محلی
اکنون که پروژه خود را به درستی تنظیم کرده ایم، احتمالاً خطی شبیه به آن در فایل OuterLib build.gradle خود خواهیم داشت:
dependencies { implementation 'url_to_remote_inner_lib_repository' }
چگونه می توانیم چرخه توسعه را کارآمد و کار با آن آسان کنیم؟ اگر آپشن های ی را در InnerLib توسعه دهیم، چگونه چیزها را در OuterLib آزمایش کنیم؟ یا در برنامه ما؟
یکی از راه حل هایی که ممکن است پیش بیاید این است که InnerLib خود را به صورت محلی به پروژه OuterLib خود وارد کنیم، در حالی که InnerLib .gitigned در پروژه OuterLib ما وجود دارد. با کلیک راست روی نام پروژه در منوی سمت چپ در اندروید استودیو و رفتن به New → Module می توانید این کار را به راحتی انجام دهید.

سپس در پنجره ای که باز می شود، می توانید گزینه Import را در پایین سمت چپ انتخاب کنید:

این تا اینجای کار آسان و ساده به نظر می رسد، اما چه چیزی است؟
هر بار که فایلی را که متعلق به InnerLib است تغییر می دهید، تغییرات در InnerLib منعکس نمی شود زیرا نادیده گرفته می شود. پس ، هر تغییری که میخواهید انجام دهید باید در داخل InnerLib اتفاق بیفتد و سپس باید آن را دوباره در OuterLib وارد کنید تا تغییرات را ببینید.
این درست به نظر نمی رسد. باید راه بهتری برای این کار وجود داشته باشد.
تنها با چند خط در فایل settings.gradle ، میتوانیم مطمئن شویم که فایلهایمان هنگام ایجاد تغییرات در InnerLib همگام میمانند.
هنگامی که InnerLib را به پروژه خود وارد کردیم، Android Studio یک کپی از InnerLib تهیه کرد و آن را کش کرد. به همین دلیل است که باید کتابخانه را برای هر تغییری که در آن ایجاد میکردیم دوباره وارد کنیم. با استفاده از ویژگی projectDir میتوانیم به Android Studio بگوییم که کجا به فایلها ارجاع دهد.
settings.gradle ما ممکن است چیزی شبیه به این باشد:
include ':outerLib', ':innerLib', ':app'
برای ارجاع به InnerLib به صورت محلی، باید settings.gradle را به این تغییر دهیم:
include ':outerLib', ':innerLib', ':app' project('innerLib').projectDir = new File('PATH_TO_INNER_LIB')
با استفاده از این رویکرد، فایل های InnerLib ما به دایرکتوری کاری ما پیوند داده می شوند، پس هر تغییری که ایجاد می کنیم بلافاصله منعکس می شود.
اما، هنگام کار به صورت محلی روی OuterLib با یک نسخه از راه دور InnerLib، انعطاف پذیری می خواهیم. آنچه در بالا در فایل settings.gradle نوشتیم فقط به ما اجازه می دهد به صورت محلی کار کنیم و مطمئناً نمی خواهیم آن را همانطور که هست انجام دهیم.
Maven محلی
اگر رویکرد بالا کاملاً با شما سازگار نیست، می توانید روش دیگری را انتخاب کنید. همانطور که کتابخانه خود را به صورت عمومی با maven منتشر می کنید، می توانید همین کار را به صورت محلی با maven local انجام دهید. Maven local مجموعه ای از مخازن است که به صورت محلی روی دستگاه شما قرار دارند.
در زیر مسیرهای mavenLocal بسته به سیستم عامل دستگاه شما آمده است:
Mac → /Users/YOUR_USERNAME/.m2
Linux → /home/YOUR_USERNAME/.m2
Windows → C:\Users\YOUR_USERNAME\.m2
در اصل شما می توانید کتابخانه خود را به صورت محلی منتشر کنید و سپس در پروژه خود به آن پیوند دهید. با انجام این کار، می توانیم پروژه خود را به InnerLib پیوند دهیم.
برای اجازه دادن به این پیکربندی در پروژه خود، باید کارهای زیر را انجام دهیم:
mavenLocal() را به عنوان یک مخزن در داخل عبارت مخازن خود اضافه کنید. این به پروژه ما امکان جستجوی مخازن به صورت محلی را می دهد
buildscript { repositories { mavenLocal() } } ... allprojects { repositories { mavenLocal() } }
2. خط پیادهسازی خود را در بند وابستگیها تغییر دهید تا به InnerLib ما ارجاع داده شود، گویی از راه دور به آن ارجاع میدهیم.
3. برای انتشار InnerLib به صورت محلی، فایلی به نام publishingLocally.gradle ایجاد می کنیم که حاوی موارد زیر است:
apply plugin: 'maven-publish' project.afterEvaluate { publishing { publications { library(MavenPublication) { setGroupId groupId //your library package setArtifactId artifactId version versionName //IE 1.0 artifact bundleDebugAar pom.withXml { def dependenciesNode = asNode().appendNode('dependencies') def dependencyNode = dependenciesNode.appendNode('dependency') dependencyNode.appendNode('groupId', 'your_group_id') dependencyNode.appendNode('artifactId', 'your_artificat_id') dependencyNode.appendNode('version', 'your_version') } } } } }
4. داخل فایل build.gradle سطح برنامه خود، این خط را اضافه کنید:
apply from: '/.publishingLocally.gradle
اگر این گزینه برای درست بودن کمی خیلی خوب به نظر می رسد، این است . در حالی که از یک طرف، میتوانیم چیزها را به صورت محلی توسعه دهیم، درست مثل اینکه با یک کتابخانه راه دور کار میکنیم. از سوی دیگر، اگر در حین کار به صورت محلی، تغییری در داخل InnerLib ایجاد کنیم، باید آن را دوباره به صورت محلی منتشر کنیم. اگرچه این کار پرهزینه ای نیست، اما نیاز به انجام کارهای خسته کننده را بارها و بارها ایجاد می کند.
راه حلی برای کار محلی و از راه دور
ما قصد داریم از نیاز دائمی به انتشار مجدد بسته InnerLib خود هر زمان که تغییری به صورت محلی ایجاد می کنیم اجتناب کنیم. ما باید راهی پیدا کنیم تا پروژه خود را از این تغییرات آگاه کنیم.
در بخش Working Locally متوجه شدیم که چگونه این کار را انجام دهیم، اما در اجرای فایل settings.gradle مشکل داشتیم. برای حل این مشکل تا بتوانیم هم به صورت محلی و هم از راه دور با InnerLib خود کار کنیم، از پارامتری استفاده خواهیم کرد که در فایل gradle.properties خود تعریف خواهیم کرد.
فایل gradle.properties مکانی است که می توانید تنظیمات سطح پروژه را که محیط توسعه شما را پیکربندی می کند، ذخیره کنید. این کمک می کند مطمئن شوید که همه توسعه دهندگان یک تیم دارای یک محیط توسعه سازگار هستند.
برخی از تنظیماتی که ممکن است با آنها آشنا باشید و در داخل این فایل یافت می شوند عبارتند از پشتیبانی AndroidX (android.useAndroidX=true) یا آرگومان های JVM (org.gradle.jvmargs=-Xmx1536m).
برای کمک به حل وضعیت خود، میتوانیم پارامتری را در اینجا اضافه کنیم که نشان دهد میخواهیم به صورت محلی کار کنیم یا نه. چیزی در راستای این موارد:
workingLocally = false
این پارامتر به ما این توانایی را می دهد که بین تنظیماتی که با آنها کار می کنیم، چه به صورت محلی و چه با کد تولید، تشخیص دهیم. ابتدا، اجازه دهید آنچه را که در فایل settings.gradle خود داریم با قرار دادن آن در شرایطی تغییر دهیم که تحلیل کند آیا پارامتر ما درست است یا خیر:
include ':outerLib', ':innerLib', ':app' if (workingLocally.booleanValue()) { project('innerLib').projectDir = new File('PATH_TO_INNER_LIB') }
به این ترتیب، ما به پروژه نشان میدهیم که فایلهای InnerLib را به صورت محلی از دستگاه ما دریافت کند.
جای دیگری که باید منطق خود را تغییر دهیم، فایل build.gradle است. در اینجا، به جای دریافت کد از راه دور به کتابخانه خود در بلوک وابستگیها، میتوانیم مشخص کنیم که آیا به صورت محلی به آن وابسته هستیم یا خیر.
dependencies { if (workingLocally.booleanValue()) { implementation 'innerLib' } else { implementation 'url_to_remote_repository' } }
⚠️ هشدار: هرگز نباید فایل gradle.properties را هنگام کار به صورت محلی commit کنید.
سفر طولانی بود و ممکن است کاملا طاقت فرسا به نظر برسد. اما اکنون ما یک راه اندازی کامل برای کار به صورت محلی و از راه دور روی یک پروژه کتابخانه چندگانه داریم.
اگر با مشکلی مواجه شدید یا مایلید نظر خود را در این مورد بیان کنید، در نظر بگیرید.
ارسال نظر