Dependency Injection: یہ کیا ہے، iOS اور Android میں انجیکشن انحصار

مصنف: IT Sectr اشاعت: 2026-02-18 مطالعے کا وقت: 9 منٹ

انجیکشن انحصار (DI) ایک تکنیک ہے جس میں ایک آبجیکٹ اپنے انحصارات کو خود بنانے کے بجائے باہر سے حاصل کرتا ہے۔ DI، IoC (الٹا کنٹرول) اصول کا نفاذ ہے اور Dagger، Hilt اور Swinject کی بنیاد ہے۔ انجیکشن انحصار کوڈ کے جوڑے کو کم کرتا ہے، جانچ کو آسان بناتا ہے اور فن تعمیر کو لچکدار بناتا ہے۔ Android پر، DI Google کے Dagger Hilt کے ذریعے معیاری ہے؛ iOS پر، Swinject یا دستی انجیکشن کے ذریعے۔ مزید معلومات کے لیے Android DI گائیڈ دیکھیں۔

اہم نکات

  • انجیکشن انحصار — انحصارات آبجیکٹ کو باہر سے دیے جاتے ہیں، اندرونی طور پر نہیں بنائے جاتے
  • الٹا کنٹرول — DI، IoC اصول کو نافذ کرتا ہے، کنٹرول کا بہاؤ کنٹینر کو منتقل ہو جاتا ہے
  • Dagger Hilt — Android کے لیے DI معیار، Google کے Dagger پر مبنی
  • Swinject — iOS اور Swift کے لیے ایک مقبول DI فریم ورک
  • کم جوڑا — ایک کلاس ٹھوس نفاذات کے بجائے تجریدوں پر منحصر ہوتی ہے

Dependency Injection کیا ہے: جوہر اور DI کی اقسام

انجیکشن انحصار ایک تکنیک ہے جس میں ایک آبجیکٹ کنسٹرکٹر، سیٹر یا انٹرفیس کے ذریعے انحصارات (خدمات، ذخیرے، ترتیبات) حاصل کرتا ہے، بجائے اس کے کہ خود new سے بنائے۔ DI کا مقصد کلاسوں کے درمیان جوڑے کو کم کرنا ہے۔ اگر کوئی کلاس خود انحصارات بناتی ہے، تو وہ مخصوص نفاذات سے مضبوطی سے جڑ جاتی ہے، جس سے جانچ اور ترمیم مشکل ہو جاتی ہے۔ DI کے ساتھ، کلاس ایک تجرید (پروٹوکول/انٹرفیس) کے ساتھ کام کرتی ہے، اور ٹھوس نفاذ باہر سے فراہم کیا جاتا ہے۔

انجیکشن کے تین طریقے — کنسٹرکٹر انجیکشن (init/constructor کے ذریعے)، سیٹر انجیکشن (پراپرٹی/setter کے ذریعے)، انٹرفیس انجیکشن (انٹرفیس کے طریقہ کار کے ذریعے)۔ کنسٹرکٹر انجیکشن ترجیحی طریقہ ہے: انحصارات دستخط میں واضح طور پر نظر آتے ہیں اور آبجیکٹ ہمیشہ درست حالت میں بنایا جاتا ہے۔ سیٹر انجیکشن ڈیفالٹ ویلیو والے اختیاری انحصارات کے لیے استعمال ہوتا ہے۔ انٹرفیس انجیکشن نایاب ہے، بنیادی طور پر DI کنٹینرز کے لیے۔

DI کی قسمطریقہکب استعمال کریںمثال
کنسٹرکٹرانیشیالائزر پیرامیٹرزلازمی انحصاراتinit(service: ServiceProtocol)
پراپرٹیکلاس پراپرٹیاختیاری انحصاراتvar service: ServiceProtocol?
طریقہطریقہ کار کا پیرامیٹرعارضی انحصاراتfunc doWork(with service: Service)

DI کنٹینر — ایک لائبریری جو انحصارات کی تخلیق اور زندگی کے چکر کا انتظام کرتی ہے۔ کنٹینر میں قسم کی رجسٹریشنز (ہر تجریدی قسم ایک ٹھوس نفاذ سے نقشہ شدہ) اور حل شدہ انحصارات کے ساتھ آبجیکٹ بنانے کے لیے ایک فیکٹری ہوتی ہے۔ Android پر — Dagger/Hilt، iOS پر — Swinject، Needle، Dip۔ کنٹینر دائرہ کار (Scope) کا انتظام کر سکتا ہے: سنگلٹن (ایپلیکیشن کے لیے ایک مثال)، فیچر اسکوپ (اسکرین کے مطابق) یا ہر درخواست پر نیا آبجیکٹ۔

Dagger Hilt: کوڈ جنریشن کے ساتھ Android کے لیے DI

Dagger Hilt Google کے Dagger کے اوپر ایک ریپر ہے، Android کے لیے معیاری DI لائبریری۔ Hilt Dagger کو آسان بناتا ہے: یہ دستی اجزاء کی تخلیق کو ہٹاتا ہے، @HiltAndroidApp، @AndroidEntryPoint اور @Module شامل کرتا ہے۔ Hilt Android کی زندگی کے چکر کے ساتھ مربوط ہوتا ہے: ViewModel، Activity، Fragment، Service، BroadcastReceiver تشریحات کے ذریعے انحصارات حاصل کر سکتے ہیں۔ کوڈ جنریشن مرتب وقت پر ہوتی ہے — Dagger اجزاء کے نفاذات تیار کرتا ہے، جو صفر runtime اوور ہیڈ دیتا ہے۔

kotlin
// ایپلیکیشن کلاس
@HiltAndroidApp
class MyApp : Application()

// ماڈیول — اس کی وضاحت کرتا ہے کہ انحصار کیسے بنائے جائیں
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder().build()

    @Provides
    @Singleton
    fun provideApiService(client: OkHttpClient): ApiService {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com")
            .client(client)
            .build()
            .create(ApiService::class.java)
    }
}

// ViewModel کنسٹرکٹر کے ذریعے انحصار حاصل کرتا ہے
@HiltViewModel
class MainViewModel @Inject constructor(
    private val apiService: ApiService
) : ViewModel() {
    private val _state = MutableStateFlow(MainState.Loading)
    val state: StateFlow<MainState> = _state.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _state.value = MainState.Success(apiService.getData())
        }
    }
}

// Activity — @AndroidEntryPoint DI کو فعال کرتا ہے
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

Dagger اجزاء اور دائرہ کار — @Singleton (پوری ایپلیکیشن)، @ActivityScoped (Activity کے مطابق)، @FragmentScoped (Fragment کے مطابق)، @ViewModelScoped (ViewModel کے مطابق)۔ دائرہ کار کا انتخاب آبجیکٹ کی زندگی کا تعین کرتا ہے۔ @Singleton — فی عمل ایک مثال، OkHttpClient اور ڈیٹا بیس کے لیے موزوں۔ @ActivityScoped — آبجیکٹ اس وقت تک زندہ رہتا ہے جب تک Activity زندہ ہے، اسکرین سطح کے انحصارات کے لیے۔ @ViewModelScoped — Hilt 2.45+ میں نیا، آبجیکٹ اس وقت تک زندہ رہتا ہے جب تک ViewModel زندہ ہے، کوریوٹین اسکوپس کے لیے آسان۔

Swinject: Swift میں iOS کے لیے DI

Swinject iOS کے لیے ایک مقبول اوپن سورس DI فریم ورک ہے۔ Swinject Container، Assemblies اور مختلف دائرہ کار فراہم کرتا ہے۔ Dagger کے برعکس، Swinject رن ٹائم پر کام کرتا ہے — انحصارات کوڈ جنریشن کے بغیر متحرک طور پر حل ہوتے ہیں۔ یہ Swinject کو ترتیب دینا آسان بناتا ہے، لیکن ڈیبگ کرنا مشکل ہے: حل نہ ہونے والے انحصار کی خرابی صرف رن ٹائم پر ظاہر ہوتی ہے۔ Swinject کنسٹرکٹر انجیکشن، پراپرٹی انجیکشن اور میتھڈ انجیکشن کو سپورٹ کرتا ہے۔

swift
import Swinject

// Assembly — رجسٹریشنز کا گروپ
class NetworkAssembly: Assembly {
    func assemble(container: Container) {
        container.register(NetworkServiceProtocol.self) { _ in
            NetworkService()
        }.inObjectScope(.container) // singleton

        container.register(UserRepositoryProtocol.self) { r in
            UserRepository(
                networkService: r.resolve(NetworkServiceProtocol.self)!
            )
        }
    }
}

// ViewModel کنسٹرکٹر انجیکشن کے ذریعے
class ProfileViewModel: ObservableObject {
    private let repository: UserRepositoryProtocol

    init(repository: UserRepositoryProtocol) {
        self.repository = repository
    }

    @Published var user: User?
    func loadUser() {
        repository.fetchUser { [weak self] user in
            self?.user = user
        }
    }
}

// AppDelegate یا App میں DI سیٹ اپ
let assembler = Assembler([NetworkAssembly(), ServiceAssembly()])
let viewModel = assembler.resolver.resolve(ProfileViewModel.self)!

// UIKit ViewController کے لیے پراپرٹی انجیکشن
container.register(UserViewController.self) { r in
    let vc = UserViewController()
    vc.viewModel = r.resolve(ProfileViewModel.self)
    return vc
}

Swinject دائرہ کار — .transient (ہر بار نیا آبجیکٹ)، .container (فی کنٹینر سنگلٹن)، .graph (ڈیفالٹ — آبجیکٹ ایک ہی انحصار گراف میں شیئر کیا جاتا ہے)۔ iOS ایپلیکیشنز کے لیے، .container اور .transient کافی ہیں۔ Swinject Assembler کو بھی سپورٹ کرتا ہے — ماڈیولر فن تعمیر کے لیے Assembly کی گروپ بندی۔ ٹیسٹ کے لیے، Assembly کو MockAssembly سے بدل دیا جاتا ہے، جو پروڈکشن کوڈ کو تبدیل کیے بغیر انحصار کی تبدیلی کی اجازت دیتا ہے۔

Service Locator اور دستی انجیکشن کے ساتھ DI کا موازنہ

DI بمقابلہ Service Locator — دونوں نمونے انحصار کے انتظام کے مسئلے کو حل کرتے ہیں، لیکن مختلف طریقوں سے۔ DI آبجیکٹ میں انحصارات داخل کرتا ہے؛ Service Locator ایک عالمی رجسٹری فراہم کرتا ہے جس سے آبجیکٹ خود انحصارات کی درخواست کرتا ہے۔ DI کنسٹرکٹر (یا سیٹر) کے ذریعے انحصارات کو واضح طور پر ظاہر کرتا ہے۔ Service Locator انحصارات کو چھپاتا ہے — وہ طریقہ کار کے اندر درخواست کیے جاتے ہیں، جس سے دستخط کم معلوماتی ہو جاتے ہیں۔ DI کی جانچ آسان ہے: کنسٹرکٹر میں mock پاس کرنا کافی ہے۔ Service Locator کو ہر ٹیسٹ کے لیے عالمی رجسٹری کی ترتیب درکار ہوتی ہے۔

خصوصیتانجیکشن انحصارService Locatorدستی انجیکشن
انحصار کی وضاحتکنسٹرکٹر میںطریقہ کار کے جسم میں چھپےواضح
جانچکنسٹرکٹر میں MockLocator کی ترتیبکنسٹرکٹر میں Mock
ترتیب کی پیچیدگیDI کنٹینر درکارعالمی رجسٹریدستی تخلیق
Runtime اوور ہیڈDagger — مرتب وقتRuntime تلاشکوئی نہیں

DI بمقابلہ دستی انجیکشن — DI کنٹینر کے بغیر، انحصارات فیکٹریوں یا AppDelegate میں دستی طور پر بنائے جاتے ہیں۔ 5-10 کلاسوں کے لیے، دستی انجیکشن آسان ہے — Dagger یا Swinject سیکھنے کی ضرورت نہیں۔ 50+ کلاسوں کے لیے، دستی انجیکشن مشکل ہو جاتا ہے: 5-6 پیرامیٹرز والے کنسٹرکٹر، پیچیدہ تخلیق کا ترتیب، کوڈ کی نقل۔ DI کنٹینر ان عملوں کو خودکار بناتا ہے اور واضح زندگی کے چکر کا انتظام فراہم کرتا ہے۔ کنٹینر کے بغیر دستی انجیکشن چھوٹے منصوبوں اور پروٹوٹائپ کے لیے ایک اچھا انتخاب ہے۔

انجیکشن انحصار کے بہترین طریقے

کنسٹرکٹر انجیکشن — معیار۔ لازمی انحصارات کے لیے ہمیشہ کنسٹرکٹر انجیکشن استعمال کریں۔ یہ انحصارات کو واضح بناتا ہے اور آبجیکٹ ہمیشہ کام کرنے کے لیے تیار رہتا ہے۔ سیٹر انجیکشن — صرف اختیاری انحصارات کے لیے (مثلاً، delegate یا listener)۔ انٹرفیس انجیکشن — استعمال نہ کریں جب تک کہ آپ اپنی DI لائبریری نہیں لکھ رہے۔ کنسٹرکٹر انجیکشن اس بات کی ضمانت دینے کا واحد طریقہ ہے کہ آبجیکٹ درست حالت میں بنایا گیا ہے۔

ایک کلاس — ایک ذمہ داری۔ اگر کسی کلاس کے کنسٹرکٹر کو 5+ پیرامیٹرز درکار ہیں، تو کلاس ممکنہ طور پر واحد ذمہ داری کے اصول کی خلاف ورزی کر رہی ہے۔ کلاس کو کم انحصار والی متعدد کلاسوں میں تقسیم کریں۔ ایک نشانی: اگر آپ 6 مختلف خدمات کے ساتھ ServiceManager کلاس لکھ رہے ہیں — یہ God Object مخالف نمونہ ہے۔ کاروباری منطق کو Use Cases (Interactors) میں نکالیں، ہر ایک میں 1-2 انحصار ہوں۔

kotlin
// ❌ برا: 6 انحصار — God Object
class ProfileViewModel @Inject constructor(
    private val api: ApiService,
    private val db: Database,
    private val analytics: Analytics,
    private val prefs: Preferences,
    private val location: LocationProvider,
    private val notification: NotificationManager
)

// ✅ اچھا: 1-2 انحصار والے Use Cases
class ProfileViewModel @Inject constructor(
    private val loadProfileUseCase: LoadProfileUseCase,
    private val trackAnalyticsUseCase: TrackAnalyticsUseCase
)

دائرہ کار اور زندگی کا چکر — ہر انحصار کے لیے صحیح دائرہ کار منتخب کریں۔ سنگلٹن: OkHttpClient، ڈیٹا بیس، SharedPreferences۔ فیچر اسکوپ: ذخیرے، Use Cases (اگر وہ بغیر حالت کے ہیں)۔ Transient: Value Objects، DateFormatter، پارسر۔ دائرہ کار کی غلطیاں ایک عام مسئلہ ہیں: اسکرین کی حالت ذخیرہ کرنے والا سنگلٹن رساؤ کا سبب بنتا ہے۔ Android میں، Hilt کا @ActivityScoped اسے حل کرتا ہے؛ Swinject میں، .container کو احتیاط سے استعمال کریں۔

اکثر پوچھے گئے سوالات

اگر میں صرف new استعمال کر سکتا ہوں تو مجھے DI کیوں چاہیے؟

new کلاسوں کے درمیان مضبوط جوڑا بناتا ہے — آپ کوڈ تبدیل کیے بغیر نفاذ نہیں بدل سکتے۔ جانچ مشکل ہو جاتی ہے: آپ حقیقی سروس کی جگہ mock داخل نہیں کر سکتے۔ SRP کی خلاف ورزی ہوتی ہے: کلاس کاروباری منطق اور انحصار کی تخلیق دونوں کی ذمہ دار ہوتی ہے۔ DI باہر سے انحصار داخل کرکے اور تجریدوں کے ساتھ کام کرکے ان مسائل کو حل کرتا ہے۔

Dagger Hilt یا Koin — Android کے لیے کیا منتخب کریں؟

Dagger Hilt Google کا معیار ہے، کوڈ جنریشن کے ساتھ مرتب وقت DI، بہتر کارکردگی اور Jetpack انضمام۔ Koin رن ٹائم DI ہے، ترتیب دینے میں آسان، لیکن سست اور رن ٹائم خرابیوں کے ساتھ۔ پروڈکشن پروجیکٹس کے لیے Hilt منتخب کریں۔ Koin پروٹوٹائپ اور چھوٹی ایپلیکیشنز کے لیے موزوں ہے۔

کیا Swinject iOS کے لیے واحد DI آپشن ہے؟

نہیں۔ iOS کے لیے دستیاب ہیں: Swinject (رن ٹائم، مقبول)، Needle (Uber سے مرتب وقت)، Dip (ہلکا)، Weaver (Sourcery پر مبنی)۔ Apple کوئی بلٹ ان DI کنٹینر فراہم نہیں کرتا، لیکن init کے ذریعے دستی انجیکشن معیاری عمل ہے۔ SwiftUI کے لیے، بیرونی لائبریریوں کے بغیر Environment یا @StateObject کے ذریعے دستی DI اکثر کافی ہوتا ہے۔

کیا DI بغیر فریم ورک کے استعمال کیا جا سکتا ہے؟

جی ہاں۔ کنسٹرکٹر کے ذریعے دستی انجیکشن بغیر فریم ورک کے DI ہے۔ Service Locator بغیر فریم ورک کے ایک متبادل ہے۔ فیکٹریاں اور Factory Method بھی DI کی شکلیں ہیں۔ فریم ورک (Dagger, Swinject) معمول کی رجسٹریشن اور انحصار کے حل کو خودکار بناتا ہے، لیکن 10-20 کلاسوں کے لیے، دستی DI کافی ہے۔

DI ایک نمونہ ہے یا اصول؟

DI ایک تکنیک (سانچہ) ہے جو الٹا کنٹرول کے اصول کو نافذ کرتی ہے۔ GoF نمونوں کے برعکس، DI کی کوئی سخت 3-4 کلاس ساخت نہیں ہے۔ DI انحصارات کو منظم کرنے کا ایک طریقہ ہے، ڈیزائن پیٹرن نہیں۔ DI کنٹینر (Dagger, Swinject) فریم ورک ہیں جو اس تکنیک کو خودکار بناتے ہیں۔

خلاصہ

  • DI — کنسٹرکٹر، سیٹر یا طریقہ کار کے ذریعے باہر سے انحصار داخل کرنے کی تکنیک
  • Dagger Hilt — مرتب وقت کوڈ جنریشن اور @HiltViewModel کے ساتھ Android کے لیے DI معیار
  • Swinject — Container، Assembly اور دائرہ کار کے ساتھ iOS کے لیے رن ٹائم DI
  • کنسٹرکٹر انجیکشن — لازمی انحصار کے لیے ترجیحی طریقہ
  • دائرہ کار — بغیر حالت کی خدمات کے لیے سنگلٹن، اسکرین سطح کے انحصار کے لیے فیچر اسکوپ
  • جانچ — DI کوڈ تبدیل کیے بغیر انحصار کو mock سے بدلنا آسان بناتا ہے

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں