<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Code Log]]></title><description><![CDATA[Code Log]]></description><link>https://code-log.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 14:43:34 GMT</lastBuildDate><atom:link href="https://code-log.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Use Dependency Injection with Hilt]]></title><description><![CDATA[Hi Kooktliners 👋
A solid application always needs strong foundations. Today, let’s talk about something essential : Dependency Injection (DI). Sounds weird, maybe even illicit ? Don’t worry, it’s perfectly legal. 😏
So, what is DI ?
DI is all about ...]]></description><link>https://code-log.com/use-dependency-injection-with-hilt</link><guid isPermaLink="true">https://code-log.com/use-dependency-injection-with-hilt</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Android]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[Clean Architecture]]></category><dc:creator><![CDATA[Patrice-dev]]></dc:creator><pubDate>Sat, 18 Oct 2025 19:58:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Ox9sNtoD9Kg/upload/43f466585bd11cc143a8215dcad5fe41.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Hi Kooktliners 👋</strong></p>
<p>A solid application always needs strong foundations. Today, let’s talk about something essential : <strong>Dependency Injection</strong> (DI). Sounds weird, maybe even illicit ? Don’t worry, it’s perfectly legal. 😏</p>
<h3 id="heading-so-what-is-di">So, what is DI ?</h3>
<p>DI is all about providing the dependencies of a class from the outside. Let’s take a simple and tastyyy analogy here:</p>
<p>You‘re a cook (obvious right 🤌🏾), and you’re preparing a homemade burger. So you buy a burger buns to the bakery, the meat to the butcher shop, the lettuce and tomato to the grocery. You go to the bakery for the buns, the butcher for the meat, and the grocery store for the veggies. You know the recipe, but you’re responsible for gathering all the ingredients yourself.</p>
<p>Now imagine this :</p>
<p>With Dependency Injection, <strong>you don't have to fetch the ingredients yourself</strong>. You have a <strong>provider</strong> that delivers top-quality products right to your kitchen 🤤. And if you don’t like one of them? You can swap it out easily. That’s the power of DI, it lets you <strong>focus on your recipe, not the ingredients</strong>.</p>
<p>With DI you don’t need to buy the ingredients by yourself, you have a provider who delivers you the best products and if you don’t like them; you can change them. That is the power of injection, you focus only on your recipe not the ingredients.</p>
<h3 id="heading-how-can-i-use-it">How can I use it ?</h3>
<p>For Android, we use <strong>Hilt</strong>, a DI library that simplifies the setup and removes most of the boilerplate code.</p>
<p>Before getting started, make sure to set up the necessary ustensiles :</p>
<p>In your top-level <strong>build-grade</strong> file, apply the <strong>KSP</strong> and <strong>Hilt</strong> plugins.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Top-level build file where you can add configuration options common to all sub-projects/modules.</span>
plugins {
   ...
    <span class="hljs-comment">//Hilt</span>
    alias(libs.plugins.ksp) apply <span class="hljs-literal">false</span>
    alias(libs.plugins.hilt) apply <span class="hljs-literal">false</span>

}
</code></pre>
<p>In your module-level file add the following :</p>
<pre><code class="lang-kotlin">plugins {
    ...
    alias(libs.plugins.ksp)
    alias(libs.plugins.hilt)
    id(<span class="hljs-string">"com.google.protobuf"</span>) version <span class="hljs-string">"0.9.5"</span> <span class="hljs-comment">// Protobuf</span>
}
...

protobuf {
    protoc {
        artifact = <span class="hljs-string">"com.google.protobuf:protoc:3.24.3"</span>
    }
    generateProtoTasks {
        all().forEach { task -&gt;
            task.builtins {
                create(<span class="hljs-string">"java"</span>) {
                    option(<span class="hljs-string">"lite"</span>)
                }
            }
        }
    }
}

dependencies {
    ...

    <span class="hljs-comment">// DataStore preference</span>
    implementation(<span class="hljs-string">"androidx.datastore:datastore-preferences:1.1.7"</span>)

    <span class="hljs-comment">// Hilt</span>
    implementation(<span class="hljs-string">"com.google.dagger:hilt-android:2.52"</span>)
    implementation(<span class="hljs-string">"androidx.hilt:hilt-navigation-compose:1.2.0"</span>)
    implementation(<span class="hljs-string">"androidx.hilt:hilt-work:1.2.0"</span>)
    ksp(<span class="hljs-string">"com.google.dagger:hilt-compiler:2.52"</span>)

    <span class="hljs-comment">// Protobuf</span>
    implementation(<span class="hljs-string">"com.google.protobuf:protobuf-javalite:3.24.3"</span>)
    implementation(<span class="hljs-string">"androidx.datastore:datastore:1.1.7"</span>)


}
</code></pre>
<p>Here’s your 5-steps recipe:</p>
<ol>
<li><p><strong>Create a file in the root package</strong></p>
<p> Create your Application file in “app/(kotlin|java)/your/company/package/YourApplicationNameApplication.kt” :</p>
<pre><code class="lang-css"> <span class="hljs-selector-tag">app</span>/
 ├── <span class="hljs-selector-tag">src</span>/
 │   └── <span class="hljs-selector-tag">main</span>/
 │       ├── <span class="hljs-selector-tag">java</span>/
 │       │   └── <span class="hljs-selector-tag">com</span>/
 │       │       └── <span class="hljs-selector-tag">yourcompany</span>/
 │       │           └── <span class="hljs-selector-tag">yourapp</span>/
 │       │               └── <span class="hljs-selector-tag">YourApplicationNameApplication</span><span class="hljs-selector-class">.kt</span>
 │       └── <span class="hljs-selector-tag">res</span>/
 │           └── ...
 ├── <span class="hljs-selector-tag">build</span><span class="hljs-selector-class">.gradle</span>
 └── ...
</code></pre>
<p> YourApplicationNameApplication.kt :</p>
<pre><code class="lang-kotlin"> <span class="hljs-meta">@HiltAndroidApp</span>
 <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">YourApplicationNameApplication</span> : <span class="hljs-type">Application</span></span>() {
 }
</code></pre>
</li>
<li><p><strong>Add your Application class to the AndroidManifest.xml</strong></p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">application</span>
     <span class="hljs-attr">android:name</span>=<span class="hljs-string">".YourApplicationNameApplication"</span>
     <span class="hljs-attr">android:icon</span>=<span class="hljs-string">"@mipmap/ic_launcher"</span>
     <span class="hljs-attr">android:label</span>=<span class="hljs-string">"@string/app_name"</span>
     <span class="hljs-attr">...</span> &gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">application</span>&gt;</span>
</code></pre>
</li>
<li><p><strong>Establish an entry point in your MainActivity with</strong> <strong>@AndroidEntryPoint</strong></p>
<p> Now that your Application class is set up, it’s time to tell Hilt where to start injecting things.</p>
<p> To do that, you need to annotate your <strong>MainActivity</strong> (or any activity where you want to inject dependencies) with the <strong>@AndroidEntryPoint</strong> annotation.</p>
<p> Here’s how it looks:</p>
<pre><code class="lang-kotlin"> <span class="hljs-keyword">import</span> dagger.hilt.android.AndroidEntryPoint

 <span class="hljs-meta">@AndroidEntryPoint</span>
 <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>() {
     <span class="hljs-comment">// Your code here</span>
 }
</code></pre>
<p> This makes <strong>MainActivity</strong> a valid entry point for Hilt. Without this annotation, Hilt won’t know it’s allowed to inject anything into this activity, so don’t skip it!</p>
</li>
<li><p><strong>Create your Module file</strong></p>
<p> Now it’s time to tell Hilt how to create the objects (dependencies) your app needs. This is done in a Module, a Kotlin file where you define how to provide certain instances.</p>
<p> Think of it as your <strong>kitchen assistant's cheat sheet</strong>: you write down how to prepare each ingredient, and they handle the rest.</p>
<p> Here’s an example of a basic module:</p>
<pre><code class="lang-kotlin"> <span class="hljs-keyword">import</span> dagger.Module
 <span class="hljs-keyword">import</span> dagger.Provides
 <span class="hljs-keyword">import</span> dagger.hilt.InstallIn
 <span class="hljs-keyword">import</span> dagger.hilt.android.qualifiers.ApplicationContext
 <span class="hljs-keyword">import</span> dagger.hilt.components.SingletonComponent
 <span class="hljs-keyword">import</span> javax.inject.Singleton

 <span class="hljs-meta">@Module</span>
 <span class="hljs-meta">@InstallIn(SingletonComponent::class)</span>
 <span class="hljs-keyword">object</span> AppModule {

     <span class="hljs-meta">@Provides</span>
     <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideBurgerService</span><span class="hljs-params">()</span></span>: BurgerService {
         <span class="hljs-keyword">return</span> BurgerServiceImpl()
     }

     <span class="hljs-meta">@Provides</span>
     <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideTomato</span><span class="hljs-params">()</span></span>: Tomato {
         <span class="hljs-keyword">return</span> Tomato(fresh = <span class="hljs-literal">true</span>)
     }
 }
</code></pre>
<p> A few things to note:</p>
<ul>
<li><p><strong>@Module</strong> : tells Hilt this file contains dependency instructions.</p>
</li>
<li><p><strong>@InstallIn(SingletonComponent::class)</strong> : defines the <em>scope</em> (how long the object lives).</p>
</li>
<li><p><strong>@Provides</strong> : tells Hilt how to create the object when needed.</p>
</li>
</ul>
</li>
</ol>
<p>    Now when you need one of these dependencies (like <strong>BurgerService</strong>) in your activity or class, just use <strong>@Inject</strong>, and voilà!</p>
<ol start="5">
<li><p><strong>Annotate your ViewModel with @HiltViewModel</strong></p>
<p> When using ViewModels, you also need to let Hilt know that it should handle the injection for you.</p>
<p> To do that:</p>
<ul>
<li><p>Annotate your ViewModel class with <strong>@HiltViewModel</strong>.</p>
</li>
<li><p>Use <strong>@Inject</strong> on the constructor to specify the dependencies it needs.</p>
</li>
</ul>
</li>
</ol>
<p>    Here’s an example:</p>
<pre><code class="lang-kotlin">    <span class="hljs-keyword">import</span> dagger.hilt.android.lifecycle.HiltViewModel
    <span class="hljs-keyword">import</span> javax.inject.Inject

    <span class="hljs-meta">@HiltViewModel</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BurgerViewModel</span> <span class="hljs-meta">@Inject</span> <span class="hljs-keyword">constructor</span></span>(
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> burgerService: BurgerService
    ) : ViewModel() {

        <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">cookBurger</span><span class="hljs-params">()</span></span> {
            burgerService.makeBurger()
        }
    }
</code></pre>
<p>    And in your <strong>Activity or Fragment</strong>, use the: <strong>by viewModels()</strong> delegate to get your ViewModel:</p>
<pre><code class="lang-kotlin">    <span class="hljs-meta">@AndroidEntryPoint</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>() {

        <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> viewModel: BurgerViewModel <span class="hljs-keyword">by</span> viewModels()

        <span class="hljs-comment">// Now you can use viewModel.cookBurger()</span>
    }
</code></pre>
<p>    And that’s it!</p>
<p>    I hope this was useful! And Happy <strong>Kooktding</strong> !</p>
<p>    ⚠️ <em>Want to see this in action ? Check out my DataStore article, I show how to use Dependency Injection there too !</em> <a target="_blank" href="https://code-log.hashnode.dev/how-to-implement-datastore-in-kotlin-applications">[Link to article]</a></p>
]]></content:encoded></item><item><title><![CDATA[How to Implement DataStore in Kotlin Applications]]></title><description><![CDATA[Hi Kooktliners 👋
You're probably almost finished with your app and need something to store your user settings. DataStore is perfect for that !
Jetpack DataStore is a modern data storage solution that lets you store user settings or typed objects. It...]]></description><link>https://code-log.com/how-to-implement-datastore-in-kotlin-applications</link><guid isPermaLink="true">https://code-log.com/how-to-implement-datastore-in-kotlin-applications</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Patrice-dev]]></dc:creator><pubDate>Sat, 18 Oct 2025 19:52:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/t0SlmanfFcg/upload/85e7507fd08c9451bf739a18c3a0bcf1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi <strong>Kooktliners 👋</strong></p>
<p>You're probably almost finished with your app and need something to store your user settings. <strong>DataStore</strong> is perfect for that !</p>
<p><strong>Jetpack DataStore</strong> is a modern data storage solution that lets you store user settings or typed objects. It uses <strong>Coroutines</strong> and <strong>Flow</strong> to store data:</p>
<ul>
<li><p><strong>Asynchronously</strong>: Read and write operations are done in the background, off the main thread, so there's no risk of <a target="_blank" href="https://developer.android.com/topic/performance/vitals/anr">ANR</a>.</p>
</li>
<li><p><strong>Consistent</strong>: Ensures that your data remains accurate, even in case of failures or interruptions.</p>
</li>
<li><p><strong>Transactionally</strong>: When multiple values are changed, all changes are applied together, or none are. This prevents partial updates and inconsistent states.</p>
</li>
</ul>
<p><strong>Pretty cool, right?</strong> 😎<br />DataStore comes in two types:</p>
<ul>
<li><p><strong>Preferences DataStore</strong>: Stores simple key-value pairs without a predefined schema. Note: it doesn't offer type safety.</p>
</li>
<li><p><strong>Proto DataStore</strong>: Allows you to persist typed objects but requires a predefined schema.</p>
</li>
</ul>
<p>Alright, enough theory, <strong>let’s Koockt!</strong> 👨‍🍳</p>
<h3 id="heading-preference-datastore">Preference Datastore</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PreferenceDSManager</span> </span>( <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> context: Context) {

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> Context.dataStore: DataStore&lt;Preferences&gt; <span class="hljs-keyword">by</span> preferencesDataStore(name =<span class="hljs-string">"settings"</span>)
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">savePreference</span><span class="hljs-params">(key: <span class="hljs-type">Preferences</span>.<span class="hljs-type">Key</span>&lt;<span class="hljs-type">T</span>&gt;, value:<span class="hljs-type">T</span>)</span></span> {
        context.dataStore.edit { prefs-&gt;
            prefs[key] = value
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">getPreference</span><span class="hljs-params">(key: <span class="hljs-type">Preferences</span>.<span class="hljs-type">Key</span>&lt;<span class="hljs-type">T</span>&gt;)</span></span>: Flow&lt;T?&gt; {
        <span class="hljs-keyword">return</span>  context.dataStore.<span class="hljs-keyword">data</span>.map { prefs-&gt; prefs[key] }

    }

    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">getPreferenceValue</span><span class="hljs-params">(key: <span class="hljs-type">Preferences</span>.<span class="hljs-type">Key</span>&lt;<span class="hljs-type">T</span>&gt;, default: <span class="hljs-type">T</span>)</span></span> : T {
        <span class="hljs-keyword">return</span> getPreference(key).first() ?:default
    }

}


<span class="hljs-keyword">object</span> Keys {
    <span class="hljs-keyword">val</span> KEY_BOOLEAN = booleanPreferencesKey(<span class="hljs-string">"key_boolean"</span>)
    <span class="hljs-keyword">val</span> KEY_STRING = stringPreferencesKey(<span class="hljs-string">"key_string"</span>)
    <span class="hljs-keyword">val</span> KEY_INT = intPreferencesKey(<span class="hljs-string">"key_int"</span>)
}
</code></pre>
<h3 id="heading-proto-datastore"><strong>Proto DataStore</strong></h3>
<p>You need 3 ingredients:</p>
<h3 id="heading-1-a-schema">1. A schema</h3>
<p>Create a <code>.proto</code> file in the <code>app/src/main/proto/</code> directory. It defines the type of your persisted variables.<br /><a target="_blank" href="https://protobuf.dev/programming-guides/proto3/">(See the Protocol Buffers language guide for details.)</a></p>
<pre><code class="lang-kotlin">syntax = <span class="hljs-string">"proto3"</span>;

option java_package = <span class="hljs-string">"com.codelog.datastorerecipe.datastore"</span>;
option java_multiple_files = <span class="hljs-literal">true</span>;

<span class="hljs-comment">//User preferences</span>
message Userpreferences {

  <span class="hljs-comment">// Hour format</span>
 bool boolPref = <span class="hljs-number">1</span>;

 string strField = <span class="hljs-number">2</span>;

 int32 numField = <span class="hljs-number">3</span>;

  <span class="hljs-comment">// Contrast level</span>
  <span class="hljs-keyword">enum</span> ContrastLevel {
    MIN = <span class="hljs-number">0</span>;
    MEDIUM = <span class="hljs-number">1</span>;
    HARD  = <span class="hljs-number">2</span>;
  }

  ContrastLevel contrast_level = <span class="hljs-number">4</span>;

}
</code></pre>
<h3 id="heading-2-a-serializer">2. A <strong>Serializer</strong></h3>
<p>It's like a <em>translator</em> , it basically converts your Kotlin data into a format that matches your schema file.</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Serializer implementation for `Userpreferences` protocol buffer messages.
 *
 * This object provides methods to serialize and deserialize `Userpreferences` data
 * for use with Jetpack's DataStore. It ensures that all protocol buffer data
 * is properly handled, including setting a default value and managing error scenarios
 * when parsing from an input stream.
 *
 * The `defaultValue` property provides a way to define the initial default proto state,
 * while the serialization and deserialization logic is handled by overriding
 * the `readFrom` and `writeTo` methods.
 */</span>
<span class="hljs-keyword">object</span> PreferenceProtoSerializer : Serializer&lt;Userpreferences&gt; {

    <span class="hljs-comment">/**
     * Provides the default value for the preferences model `Userpreferences`.
     *
     * This property returns an instance of `Userpreferences` that represents the default
     * state as defined by the `getDefaultInstance` method. It is typically used as the
     * initial or fallback value when no specific preference data has been set or when
     * retrieving the default state of the preferences object in the absence of user-defined data.
     *
     * The returned instance serves as a baseline for the preference data and ensures
     * consistency across the application whenever the default configuration is required.
     */</span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> defaultValue: Userpreferences
        <span class="hljs-keyword">get</span>() = Userpreferences.getDefaultInstance()

    <span class="hljs-comment">/**
     * Reads and deserializes a Userpreferences object from the provided InputStream.
     *
     * This method parses the InputStream to create an instance of Userpreferences using the
     * `parseFrom` method. If the InputStream cannot be parsed, an InvalidProtocolBufferException
     * is thrown to indicate the error.
     *
     * <span class="hljs-doctag">@param</span> input The InputStream containing the serialized data to be read and parsed.
     * <span class="hljs-doctag">@return</span> A Userpreferences instance deserialized from the provided InputStream.
     * <span class="hljs-doctag">@throws</span> InvalidProtocolBufferException If the InputStream cannot be parsed into a Userpreferences object.
     */</span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">readFrom</span><span class="hljs-params">(input: <span class="hljs-type">InputStream</span>)</span></span>: Userpreferences {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> Userpreferences.parseFrom(input)
        } <span class="hljs-keyword">catch</span> (e: InvalidProtocolBufferException) {
            <span class="hljs-keyword">throw</span> InvalidProtocolBufferException(<span class="hljs-string">"Cannot read proto."</span>, e)
        }
    }

    <span class="hljs-comment">/**
     * Writes the provided `UserPreferences` object to the specified `OutputStream`.
     *
     * <span class="hljs-doctag">@param</span> t The `UserPreferences` instance to be written to the output stream.
     * <span class="hljs-doctag">@param</span> output The `OutputStream` to which the `UserPreferences` instance will be serialized.
     */</span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">writeTo</span><span class="hljs-params">(
        t: <span class="hljs-type">Userpreferences</span>,
        output: <span class="hljs-type">OutputStream</span>
    )</span></span> {
        t.writeTo(output)
    }

}
</code></pre>
<h3 id="heading-3-and-finally-your-class-manager">3. And finally your class manager :</h3>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * A manager class for handling user preferences using Proto DataStore.
 *
 * This class provides functionality to save and retrieve strongly-typed user preferences
 * such as boolean, string, integer fields, and enums. The user preferences are stored
 * in a Proto DataStore file named "user_prefs.pb", utilizing a protobuf-based serialization mechanism.
 *
 * It is designed to efficiently manage user-specific customization settings persistently while providing
 * an interface for easy and straightforward operations.
 *
 * <span class="hljs-doctag">@constructor</span> Initializes the manager with the given application context.
 * <span class="hljs-doctag">@param</span> context The application context used for accessing the DataStore.
 */</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PreferenceProtoDSManager</span>  </span>( <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> context: Context) {

    <span class="hljs-comment">/**
     * Extension property providing a `DataStore` instance configured to work with protobuf-based user preferences.
     * This property is scoped to a `Context` and utilizes the `PreferenceProtoSerializer` for serialization.
     *
     * The `userPreferencesDataStore` is used to manage persistent storage and retrieval of user-specific
     * preferences, including various fields such as boolean, string, integer, and enum types. The preferences
     * are stored in a file named "user_prefs.pb".
     *
     * - To read data, use the associated `data` property on the `DataStore` instance, which provides a flow of
     *   the `Userpreferences` object.
     * - To update data, use the `updateData` function on the `DataStore` instance with the current builder
     *   instance of `Userpreferences`.
     *
     * Example purposes include storing user customization settings, such as theme preferences or contrast levels.
     *
     * Errors during data reading are handled by emitting the default instance of `Userpreferences`.
     */</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> Context.userPreferencesDataStore: DataStore&lt;Userpreferences&gt; <span class="hljs-keyword">by</span> dataStore(
        fileName = <span class="hljs-string">"user_prefs.pb"</span>,
        serializer = PreferenceProtoSerializer
    )

    <span class="hljs-comment">/**
     * A Flow that emits the user preferences data stored in the `userPreferencesDataStore`.
     *
     * This flow listens to changes in the underlying Proto DataStore and emits updated
     * `Userpreferences` objects whenever the data changes. In case of an exception during
     * data retrieval, it emits the default `Userpreferences` instance and logs the exception.
     *
     * The default instance of `Userpreferences` is provided by the `getDefaultInstance()` method.
     * Exceptions are caught and logged using `Log.e` to ensure seamless operations and handling
     * of fallback scenarios.
     */</span>
    <span class="hljs-keyword">val</span> userPreferencesFlow: Flow&lt;Userpreferences&gt; =context.userPreferencesDataStore.<span class="hljs-keyword">data</span>
        .<span class="hljs-keyword">catch</span> {  exception -&gt;

            emit(Userpreferences.getDefaultInstance())
            Log.e (<span class="hljs-string">"Error"</span>,<span class="hljs-string">" PreferenceProtoDSManager::userPreferencesFlow message "</span>+exception.message)
        }


    <span class="hljs-comment">/**
     * Saves the given boolean preference value to the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@param</span> boolPref The boolean value to be stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveBoolPref</span><span class="hljs-params">(boolPref: <span class="hljs-type">Boolean</span>)</span></span> {
        context.userPreferencesDataStore.updateData {
            it.toBuilder().setBoolPref(boolPref).build()
        }
    }

    <span class="hljs-comment">/**
     * Retrieves the boolean preference value from the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@return</span> The boolean value stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getBoolPref</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Boolean</span> {
        <span class="hljs-keyword">return</span> context.userPreferencesDataStore.<span class="hljs-keyword">data</span>.first().boolPref
    }

    <span class="hljs-comment">/**
     * Saves the given string field value to the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@param</span> strField The string value to be stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveStrField</span><span class="hljs-params">(strField:<span class="hljs-type">String</span>)</span></span> {
        context.userPreferencesDataStore.updateData {
            it.toBuilder().setStrField(strField).build()
        }
    }

    <span class="hljs-comment">/**
     * Retrieves the string field value from the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@return</span> The string value stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getStrField</span><span class="hljs-params">()</span></span> : String {
        <span class="hljs-keyword">return</span> context.userPreferencesDataStore.<span class="hljs-keyword">data</span>.first().strField
    }

    <span class="hljs-comment">/**
     * Saves the given integer field value to the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@param</span> numField The integer value to be stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveNumField</span><span class="hljs-params">(numField:<span class="hljs-type">Int</span>)</span></span> {
        context.userPreferencesDataStore.updateData {
            it.toBuilder().setNumField(numField).build()
        }
    }

    <span class="hljs-comment">/**
     * Retrieves the integer value of the numField from the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@return</span> The integer value stored in the numField preference.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getNumField</span><span class="hljs-params">()</span></span> : <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">return</span> context.userPreferencesDataStore.<span class="hljs-keyword">data</span>.first().numField
    }

    <span class="hljs-comment">/**
     * Saves the specified contrast level value to the UserPreferences DataStore.
     *
     * <span class="hljs-doctag">@param</span> contrastLevel The contrast level value to be stored in the preferences.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveContrastLevel</span><span class="hljs-params">(contrastLevel: <span class="hljs-type">Userpreferences</span>.<span class="hljs-type">ContrastLevel</span>)</span></span> {
        context.userPreferencesDataStore.updateData {
            it.toBuilder().setContrastLevel(contrastLevel).build()

        }
    }

    <span class="hljs-comment">/**
     * Retrieves the contrast level preference value from the UserPreferences DataStore.
     * This function suspends while it fetches the data.
     *
     * <span class="hljs-doctag">@return</span> The contrast level value stored in the UserPreferences DataStore.
     */</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getContrastLevel</span><span class="hljs-params">()</span></span> : Userpreferences.ContrastLevel {
        <span class="hljs-keyword">return</span> context.userPreferencesDataStore.<span class="hljs-keyword">data</span>.first().contrastLevel
    }



}
</code></pre>
<p>Thank you for reading.</p>
<p>I hope this was useful! And Happy <strong>Kooktding</strong> !</p>
<p>⚠️ <em>For this recipe, I’m using Hilt for dependency injection.</em> <a target="_blank" href="https://code-log.hashnode.dev/use-dependency-injection-with-hilt">[Link to article]</a></p>
<p>You can find the source code here :</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/patrice-dev/DataStoreRecipe">https://github.com/patrice-dev/DataStoreRecipe</a></div>
]]></content:encoded></item></channel></rss>