ড্যাগার বেসিক

একটি অ্যান্ড্রয়েড অ্যাপে ম্যানুয়াল নির্ভরতা ইনজেকশন বা পরিষেবা লোকেটারগুলি আপনার প্রকল্পের আকারের উপর নির্ভর করে সমস্যাযুক্ত হতে পারে। নির্ভরতা পরিচালনার জন্য ড্যাগার ব্যবহার করে আপনি আপনার প্রকল্পের জটিলতা সীমাবদ্ধ করতে পারেন কারণ এটি বৃদ্ধি পায়।

ড্যাগার স্বয়ংক্রিয়ভাবে কোড তৈরি করে যা আপনার হাতে লেখা কোডের অনুকরণ করে। যেহেতু কোডটি কম্পাইলের সময় তৈরি করা হয়, এটি Guice- এর মতো অন্যান্য প্রতিফলন-ভিত্তিক সমাধানগুলির চেয়ে খুঁজে পাওয়া যায় এবং আরও কার্যকর।

ড্যাগার ব্যবহারের সুবিধা

ড্যাগার আপনাকে ক্লান্তিকর এবং ত্রুটি-প্রবণ বয়লারপ্লেট কোড লেখা থেকে মুক্ত করে:

  • AppContainer কোড (অ্যাপ্লিকেশন গ্রাফ) তৈরি করা যা আপনি ম্যানুয়াল DI বিভাগে ম্যানুয়ালি প্রয়োগ করেছেন।

  • অ্যাপ্লিকেশন গ্রাফে উপলব্ধ ক্লাসের জন্য কারখানা তৈরি করা। এইভাবে নির্ভরশীলতা অভ্যন্তরীণভাবে সন্তুষ্ট হয়।

  • একটি নির্ভরতা পুনঃব্যবহার বা স্কোপ ব্যবহারের মাধ্যমে একটি নতুন দৃষ্টান্ত তৈরি করার সিদ্ধান্ত নেওয়া।

  • নির্দিষ্ট প্রবাহের জন্য কন্টেইনার তৈরি করা যেমন আপনি ডেগার সাবকম্পোনেন্ট ব্যবহার করে পূর্ববর্তী বিভাগে লগইন প্রবাহের সাথে করেছিলেন। এটি মেমরিতে অবজেক্ট রিলিজ করে আপনার অ্যাপের কর্মক্ষমতা উন্নত করে যখন সেগুলির আর প্রয়োজন হয় না।

যতক্ষণ না আপনি একটি শ্রেণির নির্ভরতা ঘোষণা করেন এবং টীকা ব্যবহার করে কীভাবে তাদের সন্তুষ্ট করবেন তা নির্দিষ্ট করে বিল্ড টাইমে ড্যাগার স্বয়ংক্রিয়ভাবে এই সব করে। ড্যাগার আপনি ম্যানুয়ালি যা লিখতেন তার অনুরূপ কোড তৈরি করে। অভ্যন্তরীণভাবে, ড্যাগার বস্তুর একটি গ্রাফ তৈরি করে যা এটি একটি ক্লাসের উদাহরণ প্রদানের উপায় খুঁজে বের করতে উল্লেখ করতে পারে। গ্রাফের প্রতিটি ক্লাসের জন্য, ড্যাগার একটি ফ্যাক্টরি-টাইপ ক্লাস তৈরি করে যা এই ধরনের উদাহরণ পেতে অভ্যন্তরীণভাবে ব্যবহার করে।

নির্মাণের সময়, ড্যাগার আপনার কোডের মধ্য দিয়ে চলে এবং:

  • নির্ভরতা গ্রাফ তৈরি করে এবং যাচাই করে, নিশ্চিত করে যে:

    • প্রতিটি বস্তুর নির্ভরতা সন্তুষ্ট হতে পারে, তাই কোন রানটাইম ব্যতিক্রম নেই।
    • কোন নির্ভরতা চক্র বিদ্যমান নেই, তাই কোন অসীম লুপ নেই।
  • প্রকৃত বস্তু এবং তাদের নির্ভরতা তৈরি করতে রানটাইমে ব্যবহৃত ক্লাসগুলি তৈরি করে।

ড্যাগারে একটি সাধারণ ব্যবহারের ক্ষেত্রে: একটি কারখানা তৈরি করা

আপনি কীভাবে ড্যাগারের সাথে কাজ করতে পারেন তা প্রদর্শন করতে, আসুন নিম্নলিখিত চিত্রে দেখানো UserRepository ক্লাসের জন্য একটি সাধারণ কারখানা তৈরি করি:

নিম্নলিখিত হিসাবে UserRepository সংজ্ঞায়িত করুন:

কোটলিন

class UserRepository(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }

জাভা

public class UserRepository {

    private final UserLocalDataSource userLocalDataSource;
    private final UserRemoteDataSource userRemoteDataSource;

    public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) {
        this.userLocalDataSource = userLocalDataSource;
        this.userRemoteDataSource = userRemoteDataSource;
    }

    ...
}

UserRepository কনস্ট্রাক্টরে একটি @Inject টীকা যোগ করুন যাতে Dagger জানে কিভাবে একটি UserRepository তৈরি করতে হয়:

কোটলিন

// @Inject lets Dagger know how to create instances of this object
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }

জাভা

public class UserRepository {

    private final UserLocalDataSource userLocalDataSource;
    private final UserRemoteDataSource userRemoteDataSource;

    // @Inject lets Dagger know how to create instances of this object
    @Inject
    public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) {
        this.userLocalDataSource = userLocalDataSource;
        this.userRemoteDataSource = userRemoteDataSource;
    }
}

কোডের উপরের স্নিপেটে, আপনি ড্যাগারকে বলছেন:

  1. @Inject টীকাযুক্ত কনস্ট্রাক্টরের সাথে কীভাবে একটি UserRepository উদাহরণ তৈরি করবেন।

  2. এর নির্ভরতাগুলি কী: UserLocalDataSource এবং UserRemoteDataSource

এখন ড্যাগার জানে কিভাবে UserRepository এর একটি উদাহরণ তৈরি করতে হয়, কিন্তু এটি কীভাবে তার নির্ভরতা তৈরি করতে হয় তা জানে না। আপনি যদি অন্যান্য ক্লাসগুলিও টীকা করেন, ড্যাগার জানেন কিভাবে সেগুলি তৈরি করতে হয়:

কোটলিন

// @Inject lets Dagger know how to create instances of these objects
class UserLocalDataSource @Inject constructor() { ... }
class UserRemoteDataSource @Inject constructor() { ... }

জাভা

public class UserLocalDataSource {
    @Inject
    public UserLocalDataSource() { }
}

public class UserRemoteDataSource {
    @Inject
    public UserRemoteDataSource() { }
}

ড্যাগার উপাদান

ড্যাগার আপনার প্রজেক্টের নির্ভরতাগুলির একটি গ্রাফ তৈরি করতে পারে যা এটি প্রয়োজনের সময় সেই নির্ভরতাগুলি কোথায় পাওয়া উচিত তা খুঁজে বের করতে ব্যবহার করতে পারে। ড্যাগারকে এটি করতে, আপনাকে একটি ইন্টারফেস তৈরি করতে হবে এবং এটি @Component এর সাথে টীকা করতে হবে। ড্যাগার একটি ধারক তৈরি করে যেমন আপনি ম্যানুয়াল নির্ভরতা ইনজেকশন দিয়ে করতেন।

@Component ইন্টারফেসের ভিতরে, আপনি এমন ফাংশনগুলিকে সংজ্ঞায়িত করতে পারেন যা আপনার প্রয়োজনীয় ক্লাসগুলির উদাহরণ প্রদান করে (যেমন UserRepository )। @Component ড্যাগারকে বলে যে এটি যে ধরনের প্রকাশ করে তা পূরণ করার জন্য প্রয়োজনীয় সমস্ত নির্ভরতা সহ একটি ধারক তৈরি করতে। একে ড্যাগার উপাদান বলা হয়; এটিতে এমন একটি গ্রাফ রয়েছে যা সেই বস্তুগুলি নিয়ে গঠিত যা ড্যাগার জানে কিভাবে প্রদান করতে হয় এবং তাদের নিজ নিজ নির্ভরতা।

কোটলিন

// @Component makes Dagger create a graph of dependencies
@Component
interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be provided from the container
    fun repository(): UserRepository
}

জাভা

// @Component makes Dagger create a graph of dependencies
@Component
public interface ApplicationGraph {
    // The return type  of functions inside the component interface is
    // what can be consumed from the graph
    UserRepository userRepository();
}

আপনি যখন প্রকল্পটি তৈরি করেন, ড্যাগার আপনার জন্য ApplicationGraph ইন্টারফেসের একটি বাস্তবায়ন তৈরি করে: DaggerApplicationGraph । এর টীকা প্রসেসরের সাহায্যে, ড্যাগার একটি নির্ভরতা গ্রাফ তৈরি করে যা তিনটি শ্রেণীর মধ্যে সম্পর্ক নিয়ে গঠিত ( UserRepository , UserLocalDatasource , এবং UserRemoteDataSource ) শুধুমাত্র একটি এন্ট্রি পয়েন্ট সহ: একটি UserRepository ইনস্ট্যান্স পাওয়া। আপনি নিম্নলিখিত হিসাবে এটি ব্যবহার করতে পারেন:

কোটলিন

// Create an instance of the application graph
val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()
// Grab an instance of UserRepository from the application graph
val userRepository: UserRepository = applicationGraph.repository()

জাভা

// Create an instance of the application graph
ApplicationGraph applicationGraph = DaggerApplicationGraph.create();

// Grab an instance of UserRepository from the application graph
UserRepository userRepository = applicationGraph.userRepository();

প্রতিবার অনুরোধ করা হলে ড্যাগার UserRepository এর একটি নতুন উদাহরণ তৈরি করে।

কোটলিন

val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()

val userRepository: UserRepository = applicationGraph.repository()
val userRepository2: UserRepository = applicationGraph.repository()

assert(userRepository != userRepository2)

জাভা

ApplicationGraph applicationGraph = DaggerApplicationGraph.create();

UserRepository userRepository = applicationGraph.userRepository();
UserRepository userRepository2 = applicationGraph.userRepository();

assert(userRepository != userRepository2)

কখনও কখনও, আপনার একটি পাত্রে নির্ভরতার একটি অনন্য উদাহরণ থাকতে হবে। আপনি বিভিন্ন কারণে এটি চাইতে পারেন:

  1. আপনি একই ধরনের ইনস্ট্যান্স শেয়ার করার জন্য নির্ভরতা হিসাবে এই ধরনের অন্যান্য ধরনের চান, যেমন একই LoginUserData ব্যবহার করে লগইন প্রবাহে একাধিক ViewModel অবজেক্ট।

  2. একটি বস্তু তৈরি করা ব্যয়বহুল এবং প্রতিবার এটিকে নির্ভরতা হিসাবে ঘোষণা করা হলে আপনি একটি নতুন উদাহরণ তৈরি করতে চান না (উদাহরণস্বরূপ, একটি JSON পার্সার)।

উদাহরণে, আপনি গ্রাফে UserRepository এর একটি অনন্য উদাহরণ পেতে চাইতে পারেন যাতে আপনি যখনই একটি UserRepository জন্য জিজ্ঞাসা করেন, আপনি সর্বদা একই উদাহরণ পান। এটি আপনার উদাহরণে উপযোগী কারণ একটি বাস্তব-জীবনের অ্যাপ্লিকেশনে আরও জটিল অ্যাপ্লিকেশন গ্রাফ সহ, আপনার কাছে UserRepository এর উপর নির্ভর করে একাধিক ViewModel অবজেক্ট থাকতে পারে এবং প্রতিবার UserRepository প্রদান করার প্রয়োজন হলে আপনি UserLocalDataSource এবং UserRemoteDataSource এর নতুন উদাহরণ তৈরি করতে চান না। .

ম্যানুয়াল ডিপেন্ডেন্সি ইনজেকশনে, আপনি ViewModel ক্লাসের কনস্ট্রাক্টরদের কাছে UserRepository এর একই উদাহরণে পাস করে এটি করেন; কিন্তু ড্যাগারে, যেহেতু আপনি সেই কোডটি ম্যানুয়ালি লিখছেন না, আপনাকে ড্যাগারকে জানাতে হবে যে আপনি একই উদাহরণ ব্যবহার করতে চান। এটি সুযোগ টীকা দিয়ে করা যেতে পারে।

ড্যাগার সঙ্গে স্কোপিং

আপনি স্কোপ টীকা ব্যবহার করতে পারেন একটি বস্তুর জীবনকালকে তার উপাদানের জীবদ্দশায় সীমাবদ্ধ করতে। এর মানে হল যে টাইপ প্রদান করার প্রয়োজন হলে প্রতিবার নির্ভরতার একই উদাহরণ ব্যবহার করা হয়।

আপনি যখন ApplicationGraph এ রিপোজিটরির জন্য জিজ্ঞাসা করেন একটি UserRepository এর একটি অনন্য উদাহরণ পেতে, @Component ইন্টারফেস এবং UserRepository জন্য একই সুযোগের টীকা ব্যবহার করুন। আপনি @Singleton টীকাটি ব্যবহার করতে পারেন যা ইতিমধ্যে javax.inject প্যাকেজের সাথে আসে যা Dagger ব্যবহার করে:

কোটলিন

// Scope annotations on a @Component interface informs Dagger that classes annotated
// with this annotation (i.e. @Singleton) are bound to the life of the graph and so
// the same instance of that type is provided every time the type is requested.
@Singleton
@Component
interface ApplicationGraph {
    fun repository(): UserRepository
}

// Scope this class to a component using @Singleton scope (i.e. ApplicationGraph)
@Singleton
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) { ... }

জাভা

// Scope annotations on a @Component interface informs Dagger that classes annotated
// with this annotation (i.e. @Singleton) are scoped to the graph and the same
// instance of that type is provided every time the type is requested.
@Singleton
@Component
public interface ApplicationGraph {
    UserRepository userRepository();
}

// Scope this class to a component using @Singleton scope (i.e. ApplicationGraph)
@Singleton
public class UserRepository {

    private final UserLocalDataSource userLocalDataSource;
    private final UserRemoteDataSource userRemoteDataSource;

    @Inject
    public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) {
        this.userLocalDataSource = userLocalDataSource;
        this.userRemoteDataSource = userRemoteDataSource;
    }
}

বিকল্পভাবে, আপনি একটি কাস্টম স্কোপ টীকা তৈরি এবং ব্যবহার করতে পারেন। আপনি নিম্নলিখিত হিসাবে একটি সুযোগ টীকা তৈরি করতে পারেন:

কোটলিন

// Creates MyCustomScope
@Scope
@MustBeDocumented
@Retention(value = AnnotationRetention.RUNTIME)
annotation class MyCustomScope

জাভা

// Creates MyCustomScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomScope {}

তারপর, আপনি এটি আগের মত ব্যবহার করতে পারেন:

কোটলিন

@MyCustomScope
@Component
interface ApplicationGraph {
    fun repository(): UserRepository
}

@MyCustomScope
class UserRepository @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val service: UserService
) { ... }

জাভা

@MyCustomScope
@Component
public interface ApplicationGraph {
    UserRepository userRepository();
}

@MyCustomScope
public class UserRepository {

    private final UserLocalDataSource userLocalDataSource;
    private final UserRemoteDataSource userRemoteDataSource;

    @Inject
    public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) {
        this.userLocalDataSource = userLocalDataSource;
        this.userRemoteDataSource = userRemoteDataSource;
    }
}

উভয় ক্ষেত্রেই, অবজেক্টটি @Component ইন্টারফেস টীকা করতে ব্যবহৃত একই সুযোগ প্রদান করা হয়। সুতরাং, যতবার আপনি applicationGraph.repository() কল করবেন, আপনি UserRepository এর একই উদাহরণ পাবেন।

কোটলিন

val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()

val userRepository: UserRepository = applicationGraph.repository()
val userRepository2: UserRepository = applicationGraph.repository()

assert(userRepository == userRepository2)

জাভা

ApplicationGraph applicationGraph = DaggerApplicationGraph.create();

UserRepository userRepository = applicationGraph.userRepository();
UserRepository userRepository2 = applicationGraph.userRepository();

assert(userRepository == userRepository2)

উপসংহার

আপনি আরও জটিল পরিস্থিতিতে এটি ব্যবহার করার আগে ড্যাগারের সুবিধা এবং এটি কীভাবে কাজ করে তার মূল বিষয়গুলি সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ।

পরের পৃষ্ঠায় , আপনি শিখবেন কিভাবে একটি অ্যান্ড্রয়েড অ্যাপ্লিকেশনে ড্যাগার যোগ করতে হয়।