এই আর্টিকেলে, আমরা Android-এ মাল্টি-লাইব্রেরি প্রজেক্ট সম্পর্কে কথা বলব। এটি কিছু সাধারণ নয়, কিন্তু অসম্ভবও নয়।
আপনি আপনার কাজের লাইনে মাল্টি-লাইব্রেরি প্রজেক্টের সাথে مواجه হয়ে থাকতে পারেন, অথবা আপনি আপনার লাইব্রেরিকে সাব-মডিউলে রূপান্তর করতে চাইছেন ভালো স্ট্রাকচার এবং সংগঠনের জন্য। কেস যেটো হোক, আপনাকে ভালোভাবে জানা উচিত আপনার সামনে কী আছে ডুবতে যাওয়ার আগে।
Android-এ নিজের লাইব্রেরি লিখা মজার। আপনি কিছু কোড লিখতে পান যা অন্যান্য ডেভেলপারকে (অথবা নিজেই) সাহায্য করতে পারে।
যেহেতু লাইব্রেরি নিজে থেকে একটি স্বতন্ত্র প্রজেক্ট হতে পারে না, সেগুলো প্রায়শই একটি অ্যাপ্লিকেশনের সাথে একটি প্রজেক্টে জোড়া থাকে। এটি লাইব্রেরি ডেভেলপমেন্টকে একটি সহজ প্রক্রিয়া বানায় যেখানে আপনি একটি ফিচার যোগ করেন/একটি বাগ ফিক্স করেন এবং তারপর সরাসরি আপনার প্রজেক্টের অ্যাপ্লিকেশন দিয়ে টেস্ট করতে পারেন। যেভাবে একজন ডেভেলপার আপনার লাইব্রেরি ইন্টিগ্রেট করবে সেটি সিমুলেট করে (একটি লোকাল উপায়ে)।
কিন্তু, কি হয় যদি আপনার লাইব্রেরি অন্য একটি লাইব্রেরির ওপর নির্ভরশীল থাকে যা আপনি ডেভেলপ করছেন?
আপনি যদি এটিকে না জানেন, তবে জানা উচিত যে একটি লাইব্রেরি (aar পড়ুন) অন্য একটি লোকাল লাইব্রেরি ধারণ করতে পারে না। এটি রিমোট লাইব্রেরির ওপর নির্ভর করতে পারে (ডিপেন্ডেন্সি এর মাধ্যমে), কিন্তু লোকাল কিছুতে নয়।
এটি Android-এ সাপোর্টেড নয়, এবং যাৎ বছরগুলোতে কিছু সমাধান এসেছে (FatAar), সেগুলো সবসময় সমস্যা সমাধান করত না এবং আপডেটড নয়। এমন একটি Google Issue Tracker রয়েছে এই ফিচার রিকোয়েস্টের জন্য যা די lâu সময় ধরে খোলা আছে এবং কমিউনিটি থেকে প্রচুর মনোযোগ পাচ্ছে। কিন্তু চলুন চিহ্নিত করি আমরা কোন দেওয়াল ভাঙতে পারি এবং কোনটি না।
কল্পনা করুন আপনার প্রজেক্ট হায়ারার্কি এমন দেখায়:
-- App | -- OuterLib | --- InnerLib
তাহলে, InnerLib যেহেতু আপনার মূল প্রজেক্টের অংশ হতে পারে না, সেটি কোথায় থাকতে পারে? এবং কীভাবে আপনি লোকালি কাজ করতে পারবেন InnerLib-এ ফিচার ডেভেলপ করার সময়?
এই আর্টিকেলে আমরা এই প্রশ্নগুলোর উত্তর দেব।
Git Submodule
অধিকাংশ টেকনিক্যাল সমস্যার জন্য, সবসময় শুধু একটি সমাধান নয়। সাধারণত আরও আছে, কিন্তু প্রতিটি সমাধানের নিজস্ব ড্রব্যাক রয়েছে। সেটি প্রশ্ন যে দিনশেষে আপনি কোন ড্রব্যাক সহ সহজে বসে থাকতে পারেন।
আমাদের প্রথম প্রশ্নের উত্তর দিতে, InnerLib কোথায় থাকতে পারে, আমাদের কয়েকটি অপশন রয়েছে:
- InnerLib কে আমাদের মূল প্রজেক্টের একটি সাবমডিউল বানান
- InnerLib কে নিজস্ব একটি রিমোট ডিপেন্ডেন্সি বানান
আপনি যদি Git-এ সাবমডিউল সম্পর্কে না জানেন, Git-এর ডকুমেন্টেশন সেটি কনজ থাকার জন্য একটি ভালো জায়গা। সেটি থেকে উদ্ধৃতি (প্রথম প্যারাগ্রাফ):
It often happens that while working on one project, you need to use another project from within it. 👉 Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects. 👈 A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.
এই প্যারাগ্রাফটি আমাদের দেখাচ্ছে যে এটি ঠিক আমাদের ইউজ কেস। একটি সাবমডিউল ব্যবহার করার সুবিধা রয়েছে। আপনার সব কোড এক জায়গায়, ম্যানেজ করা সহজ, এবং লোকালি ডেভেলপ করা সহজ।
কিন্তু সাবমডিউলগুলোর কিছু দুর্বলতা রয়েছে। একটি হলো সেটি যে আপনাকে সবসময় সচেতন থাকতে হবে আপনার সাবমডিউল কোন ব্রাঞ্চে পয়েন্ট করছে। কল্পনা করুন একটি সিনেরিও যেখানে আপনি আপনার মেইন রিপোজিটরিতে একটি রিলিজ ব্রাঞ্চে আছেন এবং আপনার সাব-মডিউল একটি ফিচার ব্রাঞ্চে। আপনি যদি লক্ষ্য না করেন, আপনি আপনার কোডের একটি ভার্সন রিলিজ করবেন কিছুটা যা প্রোডাকশনের জন্য রেডি নয়। Whoops.
এখন একটি ডেভেলপার টিমের মধ্যে এই বিষয়টি চিন্তা করুন। একজনের অসাবধান ভুল ব্যয়বহুল হতে পারে।
যদি প্রথম অপশনটি আপনার জন্য সমস্যা দায়ক মনে হয়, তবে আপনার লাইব্রেরিকে অন্য একটি রিপোজিটরিতে হোস্ট করা আপনার দ্বিতীয় পছন্দ। রিপোজিটরি সেট আপ করা খুব সহজ, কিন্তু এখন আপনি লোকালি কীভাবে কাজ করবেন?
লোকালি কাজ করা
এখন আমরা আমাদের প্রজেক্ট সঠিকভাবে সেট আপ করেছি, আমাদের প্রয়াবস্থায় OuterLib build.gradle ফাইলে এই লাইনটির মতো কিছু থাকবে:
dependencies { implementation 'url_to_remote_inner_lib_repository' }
আমরা ডেভেলপমেন্ট সাইকেলকে কীভাবে দক্ষ এবং সহজ করে তোলব? আমরা যদি InnerLib-এ কোনো ফিচার ডেভেলপ করি, তবে আমরা OuterLib-এ কীভাবে টেস্ট করব? অথবা আমাদের অ্যাপ্লিকেশনে?
একটি সমাধান যা মনে হতে পারে হলো InnerLib-কে লোকালি আমাদের OuterLib প্রজেক্টে ইম্পোর্ট করা, যখন InnerLib .gitignored থাকবে OuterLib প্রজেক্টে। আপনি এটি সহজে করতে পারেন Android Studio-এ বাম পাশের মেনুতে প্রজেক্টের নামের ওপর রাইট ক্লিক করে New → Module-এ যেতে।
মডিউল ইম্পোর্ট করা (স্টেপ ১)
তারপর খুলা উইন্ডোতে, নিচে বাম পাশে Import অপশনটি বেছে নিন:
মডিউল ইম্পোর্ট করা (স্টেপ ২)
এটা শুনতে সহজ এবং সিম্পল লাগছে, কিন্তু ক্যাচটি কী?
প্রতিবার আপনি InnerLib-এ принадлежащий একটি ফাইল মডিফাই করলে, পরিবর্তনগুলো InnerLib-এ প্রতিফলিত হবে না যেহেতু এটি ignored। তাই, আপনি যে প্রতিটি পরিবর্তন করতে চান সেটি InnerLib-এ করতে হবে এবং তারপর আবার OuterLib-এ ইম্পোর্ট করতে হবে পরিবর্তনগুলো দেখার জন্য।
এটা সঠিক লাগছে না। এতে অবশ্যই একটি ভালো উপায় থাকতে হবে।
settings.gradle ফাইলে শুধু কয়েক লাইন দিয়ে, আমরা নিশ্চিত করতে পারি আমাদের ফাইলগুলো সিঙ্কড থাকে InnerLib-এ পরিবর্তন করার সময়।
যখন আমরা InnerLib ইম্পোর্ট করলাম আমাদের প্রজেক্টে, Android Studio InnerLib-র একটি কপি বানালো এবং ক্যাশ করলো। সেটিই কারণ যে আমাদের লাইব্রেরি রি-ইম্পোর্ট করতে হতো প্রতিবার আমরা InnerLib-এ পরিবর্তন করলে। আমরা Android Studio-কে বোঝাতে পারি কোথা থেকে ফাইলগুলো রেফারেন্স করতে হবে projectDir অ্যাট্রিবিউট ব্যবহার করে।
আমাদের 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 Local
যদি উপরের পদ্ধতিটি আপনার কাছে একদম সঠিক না লাগে, তবে আপনি একটি ভিন্ন পদ্ধতি নিতে পারেন। ঠিক যেমন আপনি maven দিয়ে আপনার লাইব্রেরি পাবলিকলি পাবলিশ করবেন, আপনি একই জিনিস লোকালি maven local দিয়ে করতে পারেন। Maven local হলো রিপোজিটরির একটি সেট যা আপনার মেশিনে লোকালি বসে।
অপারেটিং সিস্টেম অনুযায়ী mavenLocal-এর পাথগুলো নিচে দেওয়া হলো:
- Mac → /Users/YOUR_USERNAME/.m2
- Linux → /home/YOUR_USERNAME/.m2
- Windows → C:\Users\YOUR_USERNAME.m2
সারসংক্ষেপে, আপনি আপনার লাইব্রেরি লোকালি পাবলিশ করতে পারেন এবং তারপর আপনার প্রজেক্টে সেটি লিঙ্ক করতে পারেন। এই পদ্ধতিতে, আমরা আমাদের প্রজেক্টকে InnerLib-এর সাথে লিঙ্ক করতে পারি।
এই কনফিগারেশন আমাদের প্রজেক্টে অনুমতি দিতে, আমাদের নিচের কাজগুলো করতে হবে:
- mavenLocal() যোগ করুন repositories clause-এ একটি রিপোজিটরি হিসেবে। এটি আপনার প্রজেক্টকে লোকালি রিপোজিটরি সার্চ করার ক্ষমতা দেবে
buildscript { repositories { mavenLocal() } } ... allprojects { repositories { mavenLocal() } }
আমাদের dependencies clause-এ implementation লাইনটি পরিবর্তন করুন InnerLib-কে রেফারেন্স করার জন্য যেন এটি রিমোটলি রেফারেন্স করা হচ্ছে
InnerLib লোকালি পাবলিশ করতে, আমরা একটি ফাইল তৈরি করব publishingLocally.gradle নামে যেটিতে নিচের কন্টেন্ট থাকবে:
apply plugin: 'maven-publish' project.afterEvaluate { publishing { publications { library(MavenPublication) { setGroupId groupId //your library package setArtifactId artifactId version versionName //I.E. 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') } } } } }
- আপনার অ্যাপ্লিকেশন লেভেল build.gradle ফাইলে, লাইনটি যোগ করুন:
apply from: '/.publishingLocally.gradle
এই অপশনটি যদি একটু too good to be true লাগে, এটা সত্যি। এক পাশে, আমরা লোকালি ডেভেলপ করতে পারি ঠিক রিমোট লাইব্রেরির সাথে কাজ করার মত। অন্য পাশে, আমরা InnerLib-এ লোকালি কাজ করার সময় কোনো পরিবর্তন করলে, আবার লোকালি পাবলিশ করতে হয়। যদিও এটি একটি ব্যয়বহুল টাস্ক নয়, এটি ತcutaneous কাজগুলো বারবার করার প্রয়োজন তৈরি করে।
লোকালি এবং রিমোটligen কাজ করার জন্য একটি সমাধান
আমরা InnerLib প্যাকেজ পুনরায় পাবলিশ করার ধারাবাহিক প্রয়োজন থেকে বাঁচতে চাই। আমাদের একটি উপায় খুঁজে বের করতে হবে আমাদের প্রজেক্টকে সেই পরিবর্তনগুলো সম্পর্কে অবগত করার জন্য।
Working Locally সেকশনে, আমরা সেটি কীভাবে করব সেটি বের করলাম, কিন্তু settings.gradle ফাইল কমিট করার সমস্যা ছিল। এই সমস্যাটি সমাধান করতে যাতে আমরা InnerLib-এ লোকালি এবং রিমোটligen দুভাবেই কাজ করতে পারি, আমরা একটি প্যারামিটার ব্যবহার করব যা আমরা ডিফাইন করব আমাদের gradle.properties ফাইলে।
gradle.properties ফাইলটি একটি জায়গা যেখানে আপনি প্রজেক্ট লেভেল সেটিংস সংরক্ষণ করতে পারেন যা আপনার ডেভেলপমেন্ট এনভায়রনমেন্ট কনফিগার করে। এটি নিশ্চিত করে যে একটি টিমের সব ডেভেলপারের একটি কনসিস্টেন্ট ডেভেলপমেন্ট এনভায়রনমেন্ট থাকে।
কিছু সেটিংস যা আপনি এই ফাইলে খুঁজে পেতে পারেন সেগুলো হলো AndroidX সাপোর্ট (android.useAndroidX=true) বা JVM আর্গুমেন্টস (org.gradle.jvmargs=-Xmx1536m)।
আমাদের পরিস্থিতি সমাধান করতে, আমরা এখানে একটি প্যারামিটার যোগ করতে পারি যা ইঙ্গিত দেবে আমরা লোকালি কাজ করতে চাই কিনা। কিছু এভাবে:
workingLocally = false
এই প্যারামিটার আমাদের দেবে সেটিংস ওই ডistingish করার ক্ষমতা, আমরা লোকালি কাজ করছি নাকি প্রোডাকশন কোডের সাথে। প্রথম, আমরা আমাদের settings.gradle-এ যা আছে সেটি পরিবর্তন করি একটি কন্ডিশন দিয়ে র্যাপ করে যেটি চেক করবে আমাদের প্যারামিটার true কিনা:
include ':outerLib', ':innerLib', ':app' if (workingLocally.booleanValue()) { project('innerLib').projectDir = new File('PATH_TO_INNER_LIB') }
এইভাবে, আমরা প্রজেক্টকে ইঙ্গিত দিচ্ছি InnerLib-র ফাইলগুলো আমাদের মেশিন থেকে লোকালি নেওয়ার জন্য।
এক আর জায়গা যেখানে আমাদের লজিক পরিবর্তন করতে হবে সেটি আমাদের build.gradle ফাইল। এখানে, dependencies ব্লকে রিমোটলি আমাদের লাইব্রেরির কোড পাওয়ার বদলে, আমরা ইঙ্গিত দিতে পারি আমরা লোকালি ডিপেন্ড করছি কিনা।
dependencies { if (workingLocally.booleanValue()) { implementation 'innerLib' } else { implementation 'url_to_remote_repository' } }
⚠️ সতর্কবাণী: আপনি কখনও gradle.properties ফাইল কমিট করবেন না লোকালি কাজ করার সময়।
যাত্রাটি দীর্ঘ ছিল এবং khá ক্লান্তিকর মনে হতে পারে। কিন্তু এখন আমাদের একটি ফুল-প্রুফ সেটআপ আছে মাল্টিপল লাইব্রেরি প্রজেক্টে লোকালি এবং রিমোটligen কাজ করার জন্য।
আপনি যদি কোনো সমস্যায় পড়েন বা আপনার মতামত দিতে চান, তবে কমেন্টে জানাতে পারেন।
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started