<?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[Satyajit Das]]></title><description><![CDATA[Satyajit Das]]></description><link>https://satyajitdas.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 22 Oct 2026 21:54:25 GMT</lastBuildDate><atom:link href="https://satyajitdas.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Blockstore: Hassle-Free Account Migration]]></title><description><![CDATA[Blockstore: Secure, encrypted Android account migration for improved user experience and app retention]]></description><link>https://satyajitdas.hashnode.dev/blockstore-hassle-free-account-migration</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/blockstore-hassle-free-account-migration</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[android app development]]></category><category><![CDATA[blockstore]]></category><category><![CDATA[androidmigration]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Thu, 22 Jun 2023 15:39:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687448067980/ffa7dbd6-d049-49c3-a082-cd188bedf84c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whenever you purchase a new Android device and upgrade from an older one, you typically migrate all your data, such as images, contacts, and even previously installed apps.</p>
<p>However, the real challenge begins when you attempt to use an app and have to log in. In some cases, it's more than just a simple login. Users may forget their login email, username, or password.</p>
<p>In today's digital world, people use different passwords for various purposes, which can lead to confusion. This issue sometimes results in users either creating a new account or abandoning the app altogether.</p>
<p>Block Store can solve this problem. The Block Store API aims to make logging back into users' applications on a new device as simple as restoring from a backup during the setup process.</p>
<p>This allows users to return to their apps just as they left them. Read on to learn more about Block Store, its benefits, and how to provide users with a seamless experience!</p>
<h2 id="heading-how-blockstore-works">How BlockStore Works?</h2>
<p>Blockstore is a Google Play Services API that allows developers to store and restore small amounts of data on an Android device. This data can be anything important to the current user session, such as an authentication token, a user preference, or a small piece of file data.</p>
<p>Blockstore data is stored in an encrypted file on the device. This file is only accessible to the app that created it, and it cannot be accessed by other apps.</p>
<p>When a user signs into your app, you can save their authentication token to Blockstore. This token will then be stored on the device and will be available when the user signs in again on a different device.</p>
<p>Blockstore data can also be used to transfer data between devices. For example, if a user has your app installed on two devices, you can use Blockstore to transfer their user preferences from one device to the other.</p>
<p>This allows for a seamless user experience, as the user will not have to re-enter their preferences when they switch devices.</p>
<p>Here is how Blockstore works in more detail:</p>
<ol>
<li><p>When a developer wants to store data in Blockstore, they call the <code>putBytes()</code> method. This method takes two parameters: the data to be stored, and a unique identifier for the data.</p>
</li>
<li><p>The <code>putBytes()</code> the method encrypts the data and stores it in the Blockstore file. The unique identifier is used to associate the data with the app that created it.</p>
</li>
<li><p>When a developer wants to retrieve data from Blockstore, they call the <code>retrieveBytes()</code> method. This method takes the unique identifier for the data as a parameter and returns the encrypted data.</p>
</li>
<li><p>The developer can then decrypt the data and use it as they see fit.</p>
</li>
</ol>
<p>Example of Saving a Token -</p>
<pre><code class="lang-kotlin"> <span class="hljs-keyword">val</span> client = Blockstore.getClient(<span class="hljs-keyword">this</span>)

  <span class="hljs-keyword">val</span> bytes1 = byteArrayOf(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>) <span class="hljs-comment">// Store one data block.</span>
  <span class="hljs-keyword">val</span> key1 = <span class="hljs-string">"com.example.app.key1"</span>
  <span class="hljs-keyword">val</span> storeRequest1 = StoreBytesData.Builder()
    .setBytes(bytes1) <span class="hljs-comment">// Call this method to set the key value with which the data should be associated with.</span>
    .setKeys(Arrays.asList(key1))
    .build()
  client.storeBytes(storeRequest1)
    .addOnSuccessListener { result: <span class="hljs-built_in">Int</span> -&gt;
      Log.d(TAG,
            <span class="hljs-string">"Stored <span class="hljs-variable">$result</span> bytes"</span>)
    }
  .addOnFailureListener { e -&gt;
      Log.e(TAG, <span class="hljs-string">"Failed to store bytes"</span>, e)
    }
</code></pre>
<p>Source: 2021 Google LLC.</p>
<p>Example of retrieving a token -</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> client = Blockstore.getClient(<span class="hljs-keyword">this</span>)

<span class="hljs-comment">// Retrieve data associated with certain keys.</span>
<span class="hljs-keyword">val</span> key1 = <span class="hljs-string">"com.example.app.key1"</span>
<span class="hljs-keyword">val</span> key2 = <span class="hljs-string">"com.example.app.key2"</span>
<span class="hljs-keyword">val</span> key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY <span class="hljs-comment">// Used to retrieve data stored without a key</span>

<span class="hljs-keyword">val</span> requestedKeys = Arrays.asList(key1, key2, key3) <span class="hljs-comment">// Add keys to array</span>

<span class="hljs-keyword">val</span> retrieveRequest = RetrieveBytesRequest.Builder()
  .setKeys(requestedKeys)
  .build()

client.retrieveBytes(retrieveRequest)
  .addOnSuccessListener { result: RetrieveBytesResponse -&gt;
    <span class="hljs-keyword">val</span> blockstoreDataMap =
      result.blockstoreDataMap
    <span class="hljs-keyword">for</span> ((key, value) <span class="hljs-keyword">in</span> blockstoreDataMap) {
      Log.d(ContentValues.TAG, String.format(
        <span class="hljs-string">"Retrieved bytes %s associated with key %s."</span>,
        String(value.bytes), key))
    }
  }
  .addOnFailureListener { e: Exception? -&gt;
    Log.e(ContentValues.TAG,
          <span class="hljs-string">"Failed to store bytes"</span>,
          e)
  }
</code></pre>
<p>Source: 2021 Google LLC.</p>
<hr />
<p>In conclusion, Blockstore offers a seamless and secure solution for storing and transferring app-specific data on Android devices.</p>
<p>By leveraging this API, developers can enhance user experience and reduce the hassle of logging in or setting up preferences across multiple devices. As users increasingly rely on multiple devices, integrating Blockstore into your app can significantly improve user satisfaction and retention.</p>
<p>That's all for now. To learn more check out the <a target="_blank" href="https://developers.google.com/identity/blockstore/android">documentation</a>.</p>
<p>If you enjoyed the article, please give it a thumbs up. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Exploring the OkHttp Interceptor]]></title><description><![CDATA[Explore OkHttp Interceptor's potential in Android development for logging, authentication, caching, and error handling, boosting app performance]]></description><link>https://satyajitdas.hashnode.dev/exploring-the-okhttp-interceptor</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/exploring-the-okhttp-interceptor</guid><category><![CDATA[Android]]></category><category><![CDATA[networking]]></category><category><![CDATA[okhttp]]></category><category><![CDATA[#http interceptor]]></category><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Mon, 19 Jun 2023 13:58:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687182803455/893ff601-28d4-4dc2-b225-ee5a80637a69.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the world of Android development, networking is an essential part of building robust and feature-rich applications. OkHttp, a popular open-source HTTP client library, simplifies network operations and offers powerful features.</p>
<p>One such feature is interceptors, which allow developers to modify and observe HTTP requests and responses. In this blog post, we will explore interceptors in OkHttp and understand how they can be used effectively in Android applications.</p>
<h2 id="heading-what-are-interceptors">What are Interceptors?</h2>
<p>An interceptor in OkHttp is a powerful mechanism that sits between the application and the network. It intercepts and modifies HTTP requests and responses, enabling developers to perform various tasks like logging, authentication, caching, and more.</p>
<blockquote>
<p><strong><em>According to documentation, Interceptors are a powerful mechanism that can monitor, rewrite, and retry the API call. So basically, when we do some API call, we can monitor the call or perform some tasks.</em></strong></p>
</blockquote>
<p>It acts as a middleware, providing a way to intercept and manipulate network communication without modifying the existing codebase.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687181734224/a46dfdcd-6c76-44cc-936c-25e5bdc8f8d8.png" alt class="image--center mx-auto" /></p>
<p>Working Principle: When an HTTP request is made using OkHttp, interceptors come into action. OkHttp allows you to add interceptors to the client, which will be executed in the order they are added.</p>
<p>Each interceptor has the opportunity to inspect and modify the request before it is sent to the server and the response before it reaches the application.</p>
<p>Types of Interceptors: OkHttp provides two types of interceptors: application interceptors and network interceptors.</p>
<ol>
<li><p>Application Interceptors: Application interceptors work on the application layer and have access to both the request and response. They are ideal for tasks like adding headers, logging, request/response modification, and authentication. These interceptors are executed first, allowing them to observe the entire network interaction.</p>
</li>
<li><p>Network Interceptors: Network interceptors operate on the network layer and have access to the raw network response. They are useful for tasks like caching, transparently decompressing responses, and rewriting responses. Network interceptors are executed after the application interceptors, enabling them to modify the response coming from the server.</p>
</li>
</ol>
<p>Using Interceptors in OkHttp: To use interceptors in your OkHttp client, follow these steps:</p>
<ol>
<li><p>Create an Interceptor: First, create a class that implements the <code>Interceptor</code> interface. This class will define the logic you want to execute when the interceptor intercepts a request or response.</p>
</li>
<li><p>Implement Interceptor Logic: Inside the interceptor class, override the <code>intercept</code> method. This method receives an <code>Chain</code> object that allows you to access and modify the request and response.</p>
</li>
<li><p>Add Interceptors to the OkHttp Client: Create an OkHttp <code>OkHttpClient</code> instance and add your interceptors using the <code>addInterceptor</code> or <code>addNetworkInterceptor</code> methods. Application interceptors should be added using, and network interceptors should be added using <code>addNetworkInterceptor</code>.</p>
</li>
<li><p>Make HTTP Requests: With the interceptors added to the client, you can now make HTTP requests using OkHttp as usual. The interceptors will automatically intercept the requests and responses, executing the logic you defined.</p>
</li>
</ol>
<hr />
<p><strong>Here are a few examples of what you can do with interceptors in Kotlin using the OkHttp library:</strong></p>
<h2 id="heading-logging-interceptor">Logging Interceptor:</h2>
<p>You can create an interceptor that logs the details of your network requests and responses.</p>
<p>This can help debug or monitor network activity. You can log information like request method, URL, headers, and response code.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> loggingInterceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .build()
</code></pre>
<h2 id="heading-authentication-interceptor">Authentication Interceptor:</h2>
<p>This interceptor can be used to add authentication headers to your requests. For example, if your API requires an access token, you can check if the token is present in the request and add it if needed. If the token is expired, you can refresh it and retry the request.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> authInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">val</span> originalRequest = chain.request()
    <span class="hljs-keyword">val</span> authenticatedRequest = originalRequest.newBuilder()
        .header(<span class="hljs-string">"Authorization"</span>, <span class="hljs-string">"&lt;your_access_token&gt;"</span>)
        .build()
    chain.proceed(authenticatedRequest)
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addInterceptor(authInterceptor)
    .build()
</code></pre>
<h2 id="heading-header-interceptor">Header Interceptor:</h2>
<p>You can use this interceptor to add or modify headers in your requests. This can be useful for adding custom headers required by your server, such as API keys or user agent information.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> headerInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">val</span> originalRequest = chain.request()
    <span class="hljs-keyword">val</span> modifiedRequest = originalRequest.newBuilder()
        .header(<span class="hljs-string">"Custom-Header"</span>, <span class="hljs-string">"value"</span>)
        .build()
    chain.proceed(modifiedRequest)
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addInterceptor(headerInterceptor)
    .build()
</code></pre>
<h2 id="heading-caching-interceptor">Caching Interceptor:</h2>
<p>This interceptor can implement caching strategies. You can intercept the responses and cache them locally based on specific criteria like response headers or URLs.</p>
<p>This can improve performance by reducing network requests for resources that are already cached.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> cache = Cache(context.cacheDir, CACHE_SIZE)

<span class="hljs-keyword">val</span> cacheInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">val</span> originalResponse = chain.proceed(chain.request())
    <span class="hljs-keyword">val</span> cacheControl = originalResponse.header(<span class="hljs-string">"Cache-Control"</span>)

    <span class="hljs-keyword">if</span> (cacheControl == <span class="hljs-literal">null</span> || cacheControl.contains(<span class="hljs-string">"no-store"</span>) ||
        cacheControl.contains(<span class="hljs-string">"no-cache"</span>) || cacheControl.contains(<span class="hljs-string">"must-revalidate"</span>) ||
        cacheControl.contains(<span class="hljs-string">"max-age=0"</span>)
    ) {
        originalResponse.newBuilder()
            .header(<span class="hljs-string">"Cache-Control"</span>, <span class="hljs-string">"public, max-age=<span class="hljs-subst">${CACHE_MAX_AGE}</span>"</span>)
            .build()
    } <span class="hljs-keyword">else</span> {
        originalResponse
    }
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addNetworkInterceptor(cacheInterceptor)
    .cache(cache)
    .build()
</code></pre>
<h2 id="heading-offline-mode-interceptor">Offline Mode Interceptor:</h2>
<p>You can create an interceptor that checks if the device is offline and returns cached responses instead of making network requests. This can help your app work offline by serving data from the cache when there is no internet connectivity.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> offlineInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">var</span> request = chain.request()
    <span class="hljs-keyword">if</span> (!isOnline()) {
        request = request.newBuilder()
            .header(<span class="hljs-string">"Cache-Control"</span>, <span class="hljs-string">"public, only-if-cached"</span>)
            .build()
    }
    chain.proceed(request)
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addInterceptor(offlineInterceptor)
    .build()

<span class="hljs-comment">// Helper method to check network connectivity</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">isOnline</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Boolean</span> {
    <span class="hljs-keyword">val</span> connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) <span class="hljs-keyword">as</span> ConnectivityManager
    <span class="hljs-keyword">val</span> networkInfo = connectivityManager.activeNetworkInfo
    <span class="hljs-keyword">return</span> networkInfo != <span class="hljs-literal">null</span> &amp;&amp; networkInfo.isConnected
}
</code></pre>
<h2 id="heading-error-handling-interceptor">Error Handling Interceptor:</h2>
<p>This interceptor can handle specific HTTP error codes and perform actions accordingly. For example, if you receive a 401 Unauthorized response, you can automatically redirect the user to the login screen.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> errorInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">val</span> response = chain.proceed(chain.request())
    <span class="hljs-keyword">if</span> (!response.isSuccessful &amp;&amp; response.code == <span class="hljs-number">401</span>) {
        <span class="hljs-comment">// Handle 401 Unauthorized error here</span>
        <span class="hljs-comment">// For example, redirect the user to the login screen</span>
    }
    response
}

<span class="hljs-keyword">val</span> client = OkHttpClient.Builder()
    .addInterceptor(errorInterceptor)
    .build()
</code></pre>
<h2 id="heading-rewriting-responses"><strong>Rewriting Responses</strong></h2>
<p>Interceptors can modify the headers of a response and change the content of the response itself. However, this action can be riskier compared to modifying request headers because it might go against what the web server expects.</p>
<p>In challenging situations, if you are willing to accept the potential consequences, rewriting response headers can be a powerful solution to overcome issues. For instance, you can correct a server's misconfigured Cache-Control response header to improve response caching.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> rewriteCacheControlInterceptor = Interceptor { chain -&gt;
    <span class="hljs-keyword">val</span> originalResponse = chain.proceed(chain.request())
    <span class="hljs-keyword">val</span> modifiedResponse = originalResponse.newBuilder()
        .header(<span class="hljs-string">"Cache-Control"</span>, <span class="hljs-string">"max-age=60"</span>)
        .build()
    modifiedResponse
}
</code></pre>
<hr />
<h2 id="heading-conclusion">conclusion</h2>
<p>interceptors in OkHttp are powerful tools that enable developers to efficiently handle various tasks like logging, authentication, caching, and error handling in Android applications.</p>
<p>By understanding the working principles and types of interceptors, developers can enhance their applications' performance and functionality while maintaining a clean and modular codebase.</p>
]]></content:encoded></item><item><title><![CDATA[Essential Data Structures for your upcoming Android interview - Part 2]]></title><description><![CDATA[Master arrays, lists, hashmaps, sets, queues, stacks, trees, and graphs for efficient Android app development, optimizing code and performance]]></description><link>https://satyajitdas.hashnode.dev/essential-data-structures-for-your-upcoming-android-interview-part-2</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/essential-data-structures-for-your-upcoming-android-interview-part-2</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[data structures]]></category><category><![CDATA[DSA]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Sun, 18 Jun 2023 19:10:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687115017289/608439eb-4979-4c84-8475-deab7838edeb.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you haven't read Part One yet, click <a target="_blank" href="https://satyajitdas.tech/essential-data-structures-for-your-upcoming-android-interview">here</a> to read it.</p>
<h1 id="heading-4-sets">4. Sets</h1>
<p>In simple terms, a set is a data structure that represents a collection of unique elements. It's like a container that can hold different objects, but it only keeps track of each object once, even if it appears multiple times in the collection.</p>
<p>Think of it like a bag where you can put various items. However, in a set, you won't find any duplicates. If you try to add the same item to the set again, it won't change because the set already contains that item.</p>
<p>Sets are useful when you want to keep track of a group of distinct elements without worrying about their order or how many times they appear. You can perform operations on sets like adding elements, removing elements, or checking if a specific element is present in the set.</p>
<p>For example, imagine you have a set of fruits that includes an apple, a banana, and an orange. If you try to add another apple to the set, it won't make a difference because the set already has an apple. However, if you add a strawberry, it will be included because it's a new element. Similarly, if you remove the banana, it will no longer be part of the set.</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Creating a set of fruits</span>
    <span class="hljs-keyword">val</span> fruitSet = mutableSetOf(<span class="hljs-string">"apple"</span>, <span class="hljs-string">"banana"</span>, <span class="hljs-string">"orange"</span>)

    <span class="hljs-comment">// Adding an element to the set</span>
    fruitSet.add(<span class="hljs-string">"strawberry"</span>)

    <span class="hljs-comment">// Trying to add a duplicate element</span>
    fruitSet.add(<span class="hljs-string">"apple"</span>)

    <span class="hljs-comment">// Removing an element from the set</span>
    fruitSet.remove(<span class="hljs-string">"banana"</span>)

    <span class="hljs-comment">// Checking if an element is present in the set</span>
    <span class="hljs-keyword">val</span> containsOrange = fruitSet.contains(<span class="hljs-string">"orange"</span>)
    <span class="hljs-keyword">val</span> containsGrapes = fruitSet.contains(<span class="hljs-string">"grapes"</span>)

    <span class="hljs-comment">// Printing the set</span>
    println(fruitSet)

    <span class="hljs-comment">// Printing the results of the membership checks</span>
    println(<span class="hljs-string">"Contains orange: <span class="hljs-variable">$containsOrange</span>"</span>)
    println(<span class="hljs-string">"Contains grapes: <span class="hljs-variable">$containsGrapes</span>"</span>)
}
</code></pre>
<p>Output -</p>
<pre><code class="lang-kotlin">[strawberry, apple, orange]
Contains orange: <span class="hljs-literal">true</span>
Contains grapes: <span class="hljs-literal">false</span>
</code></pre>
<p>Sets are often used in programming to solve problems involving uniqueness and membership checks efficiently.</p>
<h1 id="heading-5queue">5.Queue</h1>
<p>a queue is a data structure that represents a collection of elements arranged in a specific order. It follows the principle of "first in, first out" (FIFO), which means that the element that enters the queue first will be the first one to be removed.</p>
<p>Think of a queue as a line of people waiting for something, such as waiting in line at a ticket counter or a bus stop. The person who arrives first is the first to be served or get on the bus, and as more people join the line, they stand behind the others. Similarly, in a queue data structure, elements are added at one end and removed from the other end.</p>
<p>You can perform two main operations on a queue:</p>
<ol>
<li><p>Enqueue: This operation adds an element to the end of the queue. It represents joining the line or adding a new person to the back of the line.</p>
</li>
<li><p>Dequeue: This operation removes the element from the front of the queue. It represents serving the first person in line or the person who has been waiting the longest.</p>
</li>
</ol>
<p>Queues are useful when you need to manage a sequence of elements where the order of insertion is important. They are commonly used in scenarios where elements arrive or need to be processed in a specific order, such as task scheduling, message processing, or breadth-first search algorithms.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> java.util.LinkedList

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Create a queue</span>
    <span class="hljs-keyword">val</span> queue: Queue&lt;String&gt; = LinkedList()

    <span class="hljs-comment">// Enqueue elements</span>
    queue.offer(<span class="hljs-string">"Element 1"</span>)
    queue.offer(<span class="hljs-string">"Element 2"</span>)
    queue.offer(<span class="hljs-string">"Element 3"</span>)

    <span class="hljs-comment">// Dequeue elements</span>
    <span class="hljs-keyword">val</span> dequeuedElement = queue.poll()

    <span class="hljs-comment">// Print the dequeued element</span>
    println(<span class="hljs-string">"Dequeued element: <span class="hljs-variable">$dequeuedElement</span>"</span>)

    <span class="hljs-comment">// Peek at the front element without dequeuing</span>
    <span class="hljs-keyword">val</span> frontElement = queue.peek()

    <span class="hljs-comment">// Print the front element</span>
    println(<span class="hljs-string">"Front element: <span class="hljs-variable">$frontElement</span>"</span>)

    <span class="hljs-comment">// Print the entire queue</span>
    println(<span class="hljs-string">"Queue: <span class="hljs-variable">$queue</span>"</span>)
}
</code></pre>
<p>Output -</p>
<pre><code class="lang-kotlin">Dequeued element: Element <span class="hljs-number">1</span>
Front element: Element <span class="hljs-number">2</span>
Queue: [Element <span class="hljs-number">2</span>, Element <span class="hljs-number">3</span>]
</code></pre>
<p>In this example, we use the <code>LinkedList</code> class from the Java standard library to implement the queue. We create a queue called <code>queue</code> using the <code>Queue</code> interface.</p>
<p>We enqueue elements into the queue using the <code>offer</code> function, which adds elements to the rear of the queue.</p>
<p>Next, we dequeue an element from the front of the queue using the <code>poll</code> function, which also removes the element from the queue. The dequeued element is stored in the <code>dequeuedElement</code> variable.</p>
<p>We then use the <code>peek</code> function to access the front element of the queue without removing it. The front element is stored in the <code>frontElement</code> variable.</p>
<p>Finally, we print the dequeued element, the front element, and the entire queue.</p>
<p>Note that we're using the <code>Queue</code> interface, which provides basic queue operations like <code>offer</code>, <code>poll</code>, and <code>peek</code>. The <code>LinkedList</code> class is used as the concrete implementation of the queue, but you can also use other implementations such as <code>ArrayDeque</code>.</p>
<h1 id="heading-6stack">6.Stack</h1>
<p>A Stack is a data structure that represents a collection of elements in a specific order. It follows the principle of "last in, first out" (LIFO), which means that the element that enters the stack last will be the first one to be removed.</p>
<p>Think of a stack like a stack of plates. When you add a new plate, you place it on top of the stack. Similarly, when you remove a plate, you take the one from the top. The last plate you put on the stack is the first one you can access or remove.</p>
<p>You can perform two main operations on a stack:</p>
<ol>
<li><p>Push: This operation adds an element to the top of the stack. It represents placing a new plate on top of the stack.</p>
</li>
<li><p>Pop: This operation removes the element from the top of the stack. It represents taking the plate from the top of the stack.</p>
</li>
</ol>
<p>Stacks are useful when you need to manage elements in a last-in, first-out manner. They are commonly used in scenarios where you want to keep track of the order of operations or process elements in reverse order, such as function call stacks, undo/redo functionality, or parsing expressions.</p>
<p>This is how to stack internal implementation looks like</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span>&lt;<span class="hljs-type">T</span>&gt; </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> stackList = mutableListOf&lt;T&gt;()

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">push</span><span class="hljs-params">(element: <span class="hljs-type">T</span>)</span></span> {
        stackList.add(element)
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">pop</span><span class="hljs-params">()</span></span>: T? {
        <span class="hljs-keyword">if</span> (stackList.isEmpty()) {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
        }
        <span class="hljs-keyword">val</span> lastIndex = stackList.size - <span class="hljs-number">1</span>
        <span class="hljs-keyword">return</span> stackList.removeAt(lastIndex)
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">peek</span><span class="hljs-params">()</span></span>: T? {
        <span class="hljs-keyword">if</span> (stackList.isEmpty()) {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
        }
        <span class="hljs-keyword">val</span> lastIndex = stackList.size - <span class="hljs-number">1</span>
        <span class="hljs-keyword">return</span> stackList[lastIndex]
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">isEmpty</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Boolean</span> {
        <span class="hljs-keyword">return</span> stackList.isEmpty()
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">size</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Int</span> {
        <span class="hljs-keyword">return</span> stackList.size
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> stack = Stack&lt;<span class="hljs-built_in">Int</span>&gt;()

    stack.push(<span class="hljs-number">1</span>)
    stack.push(<span class="hljs-number">2</span>)
    stack.push(<span class="hljs-number">3</span>)

    println(<span class="hljs-string">"Stack size: <span class="hljs-subst">${stack.size()}</span>"</span>)
    println(<span class="hljs-string">"Top element: <span class="hljs-subst">${stack.peek()}</span>"</span>)

    <span class="hljs-keyword">val</span> poppedElement = stack.pop()
    println(<span class="hljs-string">"Popped element: <span class="hljs-variable">$poppedElement</span>"</span>)

    println(<span class="hljs-string">"Is the stack empty? <span class="hljs-subst">${stack.isEmpty()}</span>"</span>)
}
</code></pre>
<p>Output -</p>
<pre><code class="lang-kotlin">
Stack size: <span class="hljs-number">3</span>
Top element: <span class="hljs-number">3</span>
Popped element: <span class="hljs-number">3</span>
Is the stack empty? <span class="hljs-literal">false</span>
</code></pre>
<p>In Android development, the stack data structure is commonly used in various scenarios, including:</p>
<ol>
<li><p>Activity Stack: Android uses a stack to manage the activity lifecycle. When a new activity is launched, it is placed on top of the activity stack. When the user navigates back, the top activity is popped from the stack and the previous activity is resumed. This allows for a hierarchical flow of activities, with the back button behaviour following a stack-like structure.</p>
</li>
<li><p>Fragment Back Stack: Fragments in Android can also be managed using a stack-like structure. Fragments are added to a back stack, and when the user navigates back, the top fragment is popped and the previous fragment is shown. This enables navigation within a single activity using the Fragment Manager.</p>
</li>
<li><p>Undo/Redo Functionality: Android apps often provide undo and redo functionality for user actions. A stack data structure can be used to store the history of actions, allowing users to revert or redo their actions by popping or pushing elements onto the stack.</p>
</li>
<li><p>Navigation History: Navigation within Android apps, especially those using navigation components like Navigation Architecture Component, often relies on a stack-like structure. As users navigate through different screens or destinations, the app maintains a navigation stack, allowing users to navigate back through the history of visited screens.</p>
</li>
<li><p>Input Events: In certain cases, the stack data structure can be utilized to manage input events or tasks that need to be processed in a specific order. For example, if an app receives a stream of user inputs, the inputs can be pushed onto a stack and processed in reverse order, ensuring that the most recent input is handled first.</p>
</li>
</ol>
<p>These are just a few examples of how the stack data structure is used in Android development. Stacks are particularly useful in scenarios involving hierarchical or sequential operations where the last item processed or accessed needs to be prioritized.</p>
<h1 id="heading-7tree">7.Tree</h1>
<p>Certainly! Think of a tree data structure as a visual representation of a hierarchical relationship between elements. Just like a tree in nature, a tree data structure has a root at the top, branches that extend downwards and leaves at the bottom.</p>
<ul>
<li><p>Root: The root is the starting point of the tree. It is the topmost node and has no parent. Think of it as the base of the tree.</p>
</li>
<li><p>Node : Each element in the tree is called a node. A node can have some associated data and can be connected to other nodes.</p>
</li>
<li><p>Parent and Child: Nodes in a tree have parent-child relationships. A parent node is connected to its child nodes, and child nodes are connected to their parent. A node can have multiple child nodes but only one parent.</p>
</li>
<li><p>Leaf: A leaf is a node that does not have any children. It is at the bottom of the tree.</p>
</li>
<li><p>Branch: A branch is a connection between a parent node and its child node. It represents the path from one node to another.</p>
</li>
<li><p>Depth: The depth of a node is the number of edges from the root to that node. The depth of the root node is 0, and the depth of other nodes increases as you move down the tree.</p>
</li>
<li><p>Height: The height of a tree is the length of the longest path from the root to any leaf node. It represents the overall height of the tree.</p>
</li>
<li><p>Subtree: A subtree is a smaller tree within the main tree, consisting of a node and all its descendants (children, grandchildren, and so on).</p>
</li>
</ul>
<p>Tree data structures are useful for organizing hierarchical data, such as file systems, organization charts</p>
<p>Here's an example of implementing a basic tree data structure in Kotlin:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TreeNode</span>&lt;<span class="hljs-type">T</span>&gt;</span>(<span class="hljs-keyword">val</span> <span class="hljs-keyword">data</span>: T) {
    <span class="hljs-keyword">val</span> children: MutableList&lt;TreeNode&lt;T&gt;&gt; = mutableListOf()

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">addChild</span><span class="hljs-params">(child: <span class="hljs-type">TreeNode</span>&lt;<span class="hljs-type">T</span>&gt;)</span></span> {
        children.add(child)
    }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Create a tree</span>
    <span class="hljs-keyword">val</span> root = TreeNode(<span class="hljs-string">"A"</span>)

    <span class="hljs-keyword">val</span> nodeB = TreeNode(<span class="hljs-string">"B"</span>)
    <span class="hljs-keyword">val</span> nodeC = TreeNode(<span class="hljs-string">"C"</span>)
    <span class="hljs-keyword">val</span> nodeD = TreeNode(<span class="hljs-string">"D"</span>)

    <span class="hljs-keyword">val</span> nodeE = TreeNode(<span class="hljs-string">"E"</span>)
    <span class="hljs-keyword">val</span> nodeF = TreeNode(<span class="hljs-string">"F"</span>)

    root.addChild(nodeB)
    root.addChild(nodeC)
    root.addChild(nodeD)

    nodeB.addChild(nodeE)
    nodeB.addChild(nodeF)

    <span class="hljs-comment">// Traverse the tree</span>
    traverseTree(root)
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">traverseTree</span><span class="hljs-params">(node: <span class="hljs-type">TreeNode</span>&lt;<span class="hljs-type">String</span>&gt;)</span></span> {
    println(node.<span class="hljs-keyword">data</span>)

    <span class="hljs-keyword">for</span> (child <span class="hljs-keyword">in</span> node.children) {
        traverseTree(child)
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-kotlin">A
B
E
F
C
D
</code></pre>
<p>In this example, we define a <code>TreeNode</code> class that represents a node in the tree. Each node contains some data and a list of child nodes.</p>
<p>We create a tree by creating instances of <code>TreeNode</code> and connecting them using the <code>addChild</code> function. The root node is "A", and we add nodes "B", "C", and "D" as its children. Node "B" has children "E" and "F".</p>
<p>To traverse the tree, we define a <code>traverseTree</code> function that takes a <code>TreeNode</code> as a parameter. It prints the data of the current node and then recursively calls itself on each child of the node, traversing the tree in a depth-first manner.</p>
<p>In the <code>main</code> function, we create the tree and initiate the traversal by calling <code>traverseTree</code> with the root node.</p>
<hr />
<h3 id="heading-the-tree-data-structure-in-the-jetpack-compose">The Tree data structure in the <strong>Jetpack compose</strong>-</h3>
<p>Jetpack Compose uses a tree data structure internally to represent the composition of its UI. This allows Compose to efficiently manage the layout and rendering of its UI, as well as to support features such as hot reload and state management.</p>
<p>Here is an example of how Jetpack Compose uses a tree data structure to represent a simple UI:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">RootUI</span><span class="hljs-params">()</span></span> {
    Column {
        Button(onClick = { <span class="hljs-comment">/*TODO*/</span> }) {
            Text(text = <span class="hljs-string">"Button 1"</span>)
        }

        Button(onClick = { <span class="hljs-comment">/*TODO*/</span> }) {
            Text(text = <span class="hljs-string">"Button 2"</span>)
        }
    }
}
</code></pre>
<p>When Compose renders this UI, it will first create a visual tree based on the tree data structure. This visual tree will then be used to render the UI on the screen.</p>
<pre><code class="lang-kotlin">RootUINode
  |
  ColumnNode
    |
    ButtonNode(<span class="hljs-string">"Button 1"</span>)
    |
    ButtonNode(<span class="hljs-string">"Button 2"</span>)
</code></pre>
<p>Jetpack Compose's use of a tree data structure makes it a very efficient UI framework. This is because Compose can easily update the visual tree when the state of its UI changes. This is what allows Compose to support features such as hot reloading, which allows you to see changes to your UI without having to rebuild your app.</p>
<p>Here is an example of how Compose uses a tree data structure to support hot reload:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">MyApp</span><span class="hljs-params">()</span></span> {
  <span class="hljs-comment">// Create a root node.</span>
  <span class="hljs-keyword">val</span> root = ComposeNode()

  <span class="hljs-comment">// Add a Text node to the root node.</span>
  root.add(Text(<span class="hljs-string">"Hello, world!"</span>))

  <span class="hljs-comment">// Set a state variable.</span>
  <span class="hljs-keyword">val</span> text = mutableStateOf(<span class="hljs-string">"Hello, world!"</span>)

  <span class="hljs-comment">// Update the Text node when the state variable changes.</span>
  LaunchedEffect(key1 = text) {
    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
      <span class="hljs-comment">// Update the Text node with the current value of the state variable.</span>
      root.update(<span class="hljs-number">0</span>, Text(text.value))

      <span class="hljs-comment">// Wait for a change to the state variable.</span>
      text.awaitChange()
    }
  }

  <span class="hljs-comment">// Return the root node.</span>
  <span class="hljs-keyword">return</span> root
}
</code></pre>
<p>When the state variable <code>text</code> changes, Compose will update the Text node in the visual tree. This will cause the UI to be updated without having to rebuild the app.</p>
<p>Jetpack Compose's use of a tree data structure is a powerful feature that makes it a very efficient and flexible UI framework.</p>
<h1 id="heading-8-graph">8. Graph</h1>
<p>Imagine you have a group of friends and you want to represent their relationships using a graph. Each person is a node, and the connections between them are represented by edges.</p>
<p>In a graph, you have nodes (also called vertices) and edges. Nodes represent individual entities, like people, while edges represent the relationships or connections between them.</p>
<p>For example, let's say we have three friends named Alice, Bob, and Carol. We can represent them as nodes in the graph. If Alice is friends with Bob and Carol, and Bob is friends with Carol, we can connect these nodes with edges to represent their relationships.</p>
<p>Here's a simple visual representation:</p>
<pre><code class="lang-markdown"><span class="hljs-code">        Alice
        /   \
      Bob   Carol</span>
</code></pre>
<p>In this graph, we have three nodes (Alice, Bob, and Carol) connected by two edges. Alice is connected to both Bob and Carol, while Bob is connected to Carol.</p>
<p>In a graph:</p>
<ul>
<li><p>Nodes (vertices): These are entities or objects represented as points in the graph. Each node can contain additional data or attributes.</p>
</li>
<li><p>Edges: These are the connections between nodes. Edges can be directed (one-way) or undirected (two-way). They represent the relationships or connections between nodes.</p>
</li>
<li><p>Weight: Edges can also have weights or costs associated with them. These weights can represent various properties, such as distance, cost, or any other relevant metric.</p>
</li>
</ul>
<p>Graphs can be classified into two main types based on the presence or absence of directed edges:</p>
<ol>
<li><p>Directed Graph (Digraph): In a directed graph, each edge has a specific direction. The edges indicate a one-way relationship between nodes.</p>
</li>
<li><p>Undirected Graph: In an undirected graph, edges have no direction. The relationships between nodes are bidirectional.</p>
</li>
</ol>
<p>Graphs can have various structures, including:</p>
<ul>
<li><p>Cyclic: A graph with at least one cycle (a path that starts and ends at the same node).</p>
</li>
<li><p>Acyclic: A graph that does not contain any cycles.</p>
</li>
<li><p>Connected: A graph in which there is a path between any two nodes.</p>
</li>
<li><p>Disconnected: A graph in which there are one or more isolated components, with no paths connecting them.</p>
</li>
</ul>
<p>Graphs can also have more complex structures. For example, a social network can have hundreds or thousands of nodes representing users, with edges representing friendships between them.</p>
<hr />
<h3 id="heading-use-of-graph-in-daggerhilt">Use of Graph In Dagger/Hilt</h3>
<p>Both Dagger and Hilt use a graph data structure to represent the dependencies between classes in your app. This graph is used to determine which classes need to be created and how they should be injected with dependencies.</p>
<p>Dagger uses a compile-time graph, which means that the graph is generated at compile-time. This makes Dagger faster than Hilt, but it also makes it more difficult to change the dependencies in your app.</p>
<p>Hilt uses a runtime graph, which means that the graph is generated at runtime. This makes Hilt slower than Dagger, but it also makes it easier to change the dependencies in your app.</p>
<p>Here is an example of a graph that Hilt might generate for an Android app:</p>
<p><strong>Code snippet</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> </span>{
    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> viewModel: ViewModel

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// Hilt will inject the viewModel dependency into this class.</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ViewModel</span> </span>{
    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> userRepo: UserRepo

    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> newsRepo: NewsRepo

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doSomething</span><span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// Hilt will inject the repository dependency into this class.</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserRepo</span> </span>{

}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewsRepo</span> </span>{

}
</code></pre>
<p>In this example, the <code>MainActivity</code> class depends on the <code>ViewModel</code> class, and the <code>ViewModel</code> class depends on the <code>Repository</code> class. Hilt will generate a graph that represents these dependencies.</p>
<p>When Hilt needs to create an instance of <code>MainActivity</code>, it will traverse the graph and find all of the dependencies that <code>MainActivity</code> needs. Hilt will then create instances of those dependencies and inject them into <code>MainActivity</code>.</p>
<p>Hilt uses this process to generate instances of all of the classes in your app and to inject them with their dependencies. This allows you to write code that is independent of specific implementations of dependencies.</p>
<p>Example of A Dagger/Hilt Graph -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1687099692567/93937afa-ee13-4227-a097-66346e1de1de.png" alt class="image--center mx-auto" /></p>
<hr />
<h1 id="heading-conclusion">Conclusion</h1>
<p>In conclusion, understanding data structures is crucial for successful Android app development. In this blog, we have explored various fundamental data structures such as arrays, lists, hashmaps, sets, queues, stacks, trees, and graphs. These structures serve as the building blocks for organizing and manipulating data efficiently in your app.</p>
<p>Sure, here is a good conclusion for a blog where you have explained about data structures like arrays, lists, hashmaps, sets, queues, stacks, trees, and graphs for Android app development:</p>
<p>In conclusion, data structures are an essential part of Android app development. They provide a way to store and organize data in a way that is efficient and easy to access. There are many different data structures available, and the best one to use will depend on the specific needs of your app.</p>
<p>Here is a quick summary of the data structures that we have discussed:</p>
<ul>
<li><p>Arrays: Arrays are a simple data structure that stores data in a contiguous block of memory. They are efficient for storing data that is accessed in sequential order.</p>
</li>
<li><p>Lists: Lists are a more flexible data structure than arrays. They can store data in any order, and they can be easily modified.</p>
</li>
<li><p>HashMaps: HashMaps are a data structure that stores data in a key-value pair. They are efficient for storing data that is accessed by its key.</p>
</li>
<li><p>Sets: Sets are a data structure that stores data in a unique collection. They are efficient for storing data that does not need to be accessed in any particular order.</p>
</li>
<li><p>Queues: Queues are a data structure that stores data in a first-in, first-out (FIFO) order. They are efficient for storing data that needs to be processed in a specific order.</p>
</li>
<li><p>Stacks: Stacks are a data structure that stores data in a last-in, first-out (LIFO) order. They are efficient for storing data that needs to be processed in reverse order.</p>
</li>
<li><p>Trees: Trees are a data structure that stores data in a hierarchical order. They are efficient for storing data that needs to be accessed by its relationship to other data.</p>
</li>
<li><p>Graphs: Graphs are a data structure that stores data in a network of nodes and edges. They are efficient for storing data that needs to be processed in a complex way.</p>
</li>
</ul>
<p>Having a solid understanding of these data structures enables you to design and implement efficient algorithms, optimize memory usage, and enhance the overall performance of your Android app.</p>
<p>It allows you to choose the most suitable data structure based on the requirements of your application, ensuring better user experiences and smoother functionality.</p>
<hr />
<p>Remember, selecting the appropriate data structure requires careful consideration of factors such as data access patterns, search requirements, insertion and deletion operations, and memory usage.</p>
<p>Additionally, continuously improving your knowledge of data structures and algorithms will empower you to tackle more complex problems and make your Android app development journey even more successful.</p>
<p>So, take the time to master these foundational data structures, experiment with them, and explore their capabilities within the context of Android app development. By doing so, you'll be equipped with the tools to create efficient, scalable, and robust applications that deliver exceptional user experiences.</p>
<p>I hope this blog has helped you to understand the basics of data structures and how they can be used in Android app development. If you have any questions, please feel free to leave a comment below. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Essential Data Structures for your upcoming Android interview - Part 1]]></title><description><![CDATA[Master essential data structures for Android interviews and development, including arrays, lists, hashmaps, sets, queues, stacks, trees, and graphs…]]></description><link>https://satyajitdas.hashnode.dev/essential-data-structures-for-your-upcoming-android-interview-part-1</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/essential-data-structures-for-your-upcoming-android-interview-part-1</guid><category><![CDATA[Android]]></category><category><![CDATA[data structures]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[android development]]></category><category><![CDATA[data structure and algorithms ]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Sun, 18 Jun 2023 15:05:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682019517181/c0e26a09-c088-4c9b-ae2f-3a65089e9b67.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The first round of an Android interview focusing on DSA helps employers assess a candidate's foundational knowledge, problem-solving abilities, and potential for developing efficient and scalable Android applications.</p>
<p>It is a crucial step in identifying candidates who can handle complex programming challenges and contribute effectively to the development team.</p>
<hr />
<p>Data structures are a fundamental concept in computer science that allow us to store and organize data efficiently and effectively.</p>
<p>In the world of Android development, understanding the different types of data structures and how to use them can make a significant difference in the <strong>performance</strong> and <strong>functionality</strong> of your application.</p>
<p>In this blog, we will explore some of the most commonly used data structures by Android developers and how they can be implemented in your own projects.</p>
<p>Whether you are a beginner or an experienced developer, this guide will provide you with a solid foundation in the world of data structures for Android development.</p>
<p>Though there are numerous concepts to grasp, we will concentrate solely on those most commonly utilized from an Android perspective.</p>
<p>In this blog, we will cover these data structures.</p>
<p><code>Array</code> <code>List</code> <code>HashMap</code> <code>Sets</code> <code>Queue</code> <code>Stack</code> <code>Tree</code> <code>Graph</code></p>
<p>Before delving into the data structures, let's discuss where they are stored: the RAM.</p>
<h2 id="heading-what-is-ram">What is RAM?</h2>
<p>Certainly! RAM, or Random Access Memory, is a vital part of a computer's hardware. It is responsible for temporarily storing data and instructions actively used by the computer's processor.</p>
<p>From a data structure perspective, RAM can be thought of as a large collection of storage cells, each capable of storing a certain amount of information. These cells are organized into a two-dimensional grid of bits. A bit is the smallest unit of data in a computer, representing a binary value of either 0 or 1.</p>
<p>The size of RAM is typically measured in terms of bytes. A byte consists of 8 bits. So, when you see specifications like 4 GB (gigabytes) of RAM, it means there are approximately 4 billion bytes of storage available.</p>
<p>Now, let's understand how data structures utilize RAM. When you create variables, arrays, or other data structures in a programming language, they occupy a certain amount of memory in RAM based on their data type and size.</p>
<p>For example, let's consider an integer variable in a programming language. In most programming languages, an integer is typically represented using 4 bytes (32 bits) of memory. This means that when you declare an integer variable, 4 bytes of RAM will be allocated to store its value.</p>
<p>Similarly, let's say you have an array of 100 integers. Since each integer occupies 4 bytes, the array would require <strong>100 * 4 = 400 bytes</strong> of RAM.</p>
<p>Different data structures have different memory requirements based on their design and the type of data they store. For instance:</p>
<ol>
<li><p>Arrays: As mentioned earlier, arrays store elements of the same data type in contiguous memory locations. The memory required by an array is determined by multiplying the size of each element by the number of elements in the array.</p>
</li>
<li><p>Linked Lists: In a linked list, memory is dynamically allocated for each node. Each node contains both the data and a pointer/reference to the next node in the list. The memory required for a linked list depends on the number of nodes and the size of each node.</p>
</li>
<li><p>Trees: Trees consist of nodes connected in a hierarchical structure. Each node holds data and pointers to its child nodes. The memory needed for a tree depends on the number of nodes and the size of each node.</p>
</li>
</ol>
<p>It's important to note that the memory usage of data structures is not limited to just the data they store. It also includes any additional metadata or overhead required by the programming language or the underlying implementation of the data structure.</p>
<p>Efficient memory management is a crucial consideration when designing and working with data structures. It helps ensure optimal utilization of RAM and avoids unnecessary memory wastage.</p>
<hr />
<h2 id="heading-1-array">1. Array</h2>
<p>An array is a data structure in Kotlin that stores a fixed-size sequential collection of elements of the same type. In other words, an array is a container that holds a fixed number of elements of a specific type.</p>
<p>Declaring and initializing an array in Kotlin is easy. Here is an example of an array of integers:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> numbers: IntArray = intArrayOf(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>)
</code></pre>
<p>In this example, we declare an array called <code>numbers</code> and initialize it with the values 1, 2, 3, 4, and 5. The <code>IntArray</code> type specifies that the array holds integers.</p>
<p>We can access individual elements of the array using their index, which starts at 0. For example, to access the first element of the <code>numbers</code> array, we can use the following code:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> firstNumber = numbers[<span class="hljs-number">0</span>]
</code></pre>
<p>This assigns the value of the first element of the <code>numbers</code> array to the variable <code>firstNumber</code>. Similarly, we can access any other element of the array by specifying its index.</p>
<p>We can also modify individual elements of the array by assigning a new value to their index. For example, to change the value of the third element of the <code>numbers</code> array to 10, we can use the following code:</p>
<pre><code class="lang-kotlin">numbers[<span class="hljs-number">2</span>] = <span class="hljs-number">10</span>
</code></pre>
<p>Arrays in Kotlin also provide several useful methods for working with their elements, such as <code>size</code>, which returns the number of elements in the array, and <code>forEach</code>, which applies a function to each element of the array.</p>
<pre><code class="lang-kotlin">arraySize = numbers.size <span class="hljs-comment">// returns 5</span>
numbers.forEach { println(it) } <span class="hljs-comment">// prints each element of the array</span>
</code></pre>
<p>Keep in mind that arrays in Kotlin have a fixed size, which means that once you declare an array, you cannot add or remove elements from it. If you need a collection that can grow or shrink dynamically, you may want to consider using a <code>List</code> instead.</p>
<hr />
<h3 id="heading-how-an-array-is-stored-in-memory">How an Array is stored in memory?</h3>
<p>When an array is created in a programming language, the memory for the array is allocated in the computer's RAM (Random Access Memory) in a contiguous block of memory. The amount of memory required to store an array depends on the data type and the number of elements in the array.</p>
<p>For example, consider this array:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> numbers: IntArray = intArrayOf(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>)
</code></pre>
<p>This creates an array of integers called <code>numbers</code> with a size of 5. The array can hold 5 integers, and each integer requires 4 bytes of memory on a typical <strong>32-bit</strong> system. Therefore, the total memory required to store the entire array is <strong>5 * 4 = 20 bytes</strong>.</p>
<p>When the array is created, the memory for the array is allocated in the computer's RAM as a contiguous block of memory.</p>
<p>The starting address of this block of memory is stored in reference variable <code>numbers</code>.</p>
<p>Each element of the array is stored in a consecutive memory location, and the index of an element corresponds to its offset from the starting address of the array.</p>
<p>For example, let's say that the starting address of the array <code>arr</code> is 1000. Then, the memory locations for each element of the array would be as follows:</p>
<pre><code class="lang-kotlin">numbers[<span class="hljs-number">0</span>]: <span class="hljs-number">1000</span>
numbers[<span class="hljs-number">1</span>]: <span class="hljs-number">1004</span>
numbers[<span class="hljs-number">2</span>]: <span class="hljs-number">1008</span>
numbers[<span class="hljs-number">3</span>]: <span class="hljs-number">1012</span>
numbers[<span class="hljs-number">4</span>]: <span class="hljs-number">1016</span>
</code></pre>
<p>As you can see, each element of the array is stored in a consecutive memory location, and the offset between two consecutive elements is equal to the size of the data type, which is 4 bytes in this case.</p>
<p>When an element of the array is accessed, the computer uses the starting address of the array and the index of the element to calculate the memory location of the element in the RAM. This process is very efficient and allows for fast and easy access to the elements of the array in O(1).</p>
<h2 id="heading-2-list">2. List</h2>
<p>list is a data structure that represents an ordered collection of elements, where each element has an associated index. It allows for efficient insertion, deletion, and retrieval of elements based on their positions in the list.</p>
<p>In Kotlin, the <code>List</code> the interface provides a read-only list, while the <code>MutableList</code> interface extends <code>List</code> to support the modification of elements.</p>
<p>Arrays and lists are similar in that they both store ordered collections of elements. However, there are some key differences:</p>
<ul>
<li><p>Size: Arrays have a fixed size defined at the time of creation, whereas lists can dynamically grow or shrink as elements are added or removed.</p>
</li>
<li><p>Flexibility: Lists offer more flexibility in terms of resizing and modifying elements, while arrays are more static in nature.</p>
</li>
<li><p>Memory Management: Arrays generally require less memory overhead, as they only store the elements themselves, whereas lists may require additional memory for managing their internal structures.</p>
</li>
</ul>
<h3 id="heading-how-list-works-inside-memory">How List works inside memory</h3>
<p>When a dynamic list (also known as a dynamic array or resizable array) is stored in memory, it starts with an initial allocated capacity. As new items are added to the list and the capacity is exceeded, the list is resized by allocating a larger block of memory and copying the existing elements to the new block. Let's explore the process in more detail:</p>
<ol>
<li><p>Memory Allocation: When the dynamic list is created, an initial block of memory is allocated to hold a certain number of elements. The size of this block depends on the implementation and may vary. The list also keeps track of the current number of elements and the allocated capacity.</p>
</li>
<li><p>Adding a New Item: When a new item is added to the dynamic list, the implementation checks if there is enough space in the allocated block to accommodate the new element.</p>
<p> a. If there is available space: If the current number of elements does not exceed the allocated capacity, the new item is simply stored in the next available memory slot.</p>
<p> b. If the capacity is exceeded: If the current number of elements exceeds the allocated capacity, the list needs to be resized. The implementation follows these steps:</p>
<ol>
<li><p>Allocate a new, larger block of memory: A new block of memory is allocated with an increased capacity. The new capacity can be determined based on various factors, such as doubling the current capacity or adding a fixed number of additional slots.</p>
</li>
<li><p>Copy existing elements to the new block: The existing elements from the old block of memory are copied to the new block, ensuring their order is maintained.</p>
</li>
<li><p>Update references and release old memory: The list updates the references to the new block and releases the old memory to free up resources.</p>
</li>
<li><p>Add the new item: Finally, the new item is added to the next available memory slot in the resized list.</p>
</li>
</ol>
</li>
</ol>
<p>    This resizing process ensures that the dynamic list can accommodate additional elements beyond its initial capacity.</p>
<p>It's important to note that the resizing operation can be costly in terms of time and memory. The frequency of resizing can impact the performance of the dynamic list. To mitigate excessive resizing, some implementations may employ strategies such as resizing by a larger factor or using incremental resizing.</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Creating a List</span>
    <span class="hljs-keyword">val</span> myList = listOf(<span class="hljs-string">"apple"</span>, <span class="hljs-string">"banana"</span>, <span class="hljs-string">"orange"</span>, <span class="hljs-string">"kiwi"</span>)
    println(<span class="hljs-string">"Original List: <span class="hljs-variable">$myList</span>"</span>)

    <span class="hljs-comment">// Accessing Elements</span>
    <span class="hljs-keyword">val</span> firstElement = myList[<span class="hljs-number">0</span>]
    println(<span class="hljs-string">"First Element: <span class="hljs-variable">$firstElement</span>"</span>)

    <span class="hljs-comment">// Modifying Elements (Creating a Mutable List)</span>
    <span class="hljs-keyword">val</span> mutableList = myList.toMutableList()
    mutableList[<span class="hljs-number">1</span>] = <span class="hljs-string">"grape"</span>
    println(<span class="hljs-string">"Modified List: <span class="hljs-variable">$mutableList</span>"</span>)

    <span class="hljs-comment">// Adding Elements</span>
    mutableList.add(<span class="hljs-string">"watermelon"</span>) <span class="hljs-comment">// Adding an element to the end</span>
    mutableList.add(<span class="hljs-number">2</span>, <span class="hljs-string">"mango"</span>) <span class="hljs-comment">// Inserting an element at index 2</span>
    println(<span class="hljs-string">"List after Adding Elements: <span class="hljs-variable">$mutableList</span>"</span>)

    <span class="hljs-comment">// Removing Elements</span>
    mutableList.remove(<span class="hljs-string">"banana"</span>) <span class="hljs-comment">// Removing an element by value</span>
    mutableList.removeAt(<span class="hljs-number">0</span>) <span class="hljs-comment">// Removing an element at index 0</span>
    println(<span class="hljs-string">"List after Removing Elements: <span class="hljs-variable">$mutableList</span>"</span>)

    <span class="hljs-comment">// Checking List Size and Empty</span>
    <span class="hljs-keyword">val</span> listSize = mutableList.size
    <span class="hljs-keyword">val</span> isEmpty = mutableList.isEmpty()
    println(<span class="hljs-string">"List Size: <span class="hljs-variable">$listSize</span>"</span>)
    println(<span class="hljs-string">"Is List Empty? <span class="hljs-variable">$isEmpty</span>"</span>)

    <span class="hljs-comment">// Iterating and Transforming Elements</span>
    mutableList.forEach { element -&gt;
        println(<span class="hljs-string">"Processing element: <span class="hljs-variable">$element</span>"</span>)
    }

    <span class="hljs-keyword">val</span> upperCaseList = mutableList.map { element -&gt;
        element.toUpperCase()
    }
    println(<span class="hljs-string">"List after Transforming to Upper Case: <span class="hljs-variable">$upperCaseList</span>"</span>)

    <span class="hljs-comment">// Filtering Elements</span>
    <span class="hljs-keyword">val</span> filteredList = mutableList.filter { element -&gt;
        element.length &gt; <span class="hljs-number">4</span>
    }
    println(<span class="hljs-string">"Filtered List: <span class="hljs-variable">$filteredList</span>"</span>)

    <span class="hljs-comment">// Sorting Elements</span>
    <span class="hljs-keyword">val</span> sortedList = mutableList.sorted()
    println(<span class="hljs-string">"Sorted List: <span class="hljs-variable">$sortedList</span>"</span>)
}
</code></pre>
<h1 id="heading-3-hashmap">3. HashMap</h1>
<p>A HashMap is a data structure that provides fast access to values based on a unique key. It internally uses an array and a hashing function to map keys to specific indices in the array, allowing for efficient retrieval and storage of key-value pairs.Let's explore HashMaps with an example in Kotlin:</p>
<p>Consider a scenario where you want to store a collection of students and their corresponding grades using a HashMap.</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Create a HashMap to store student grades</span>
    <span class="hljs-keyword">val</span> gradesMap = HashMap&lt;String, <span class="hljs-built_in">Int</span>&gt;()

    <span class="hljs-comment">// Add student grades to the HashMap</span>
    gradesMap[<span class="hljs-string">"John"</span>] = <span class="hljs-number">85</span>
    gradesMap[<span class="hljs-string">"Emily"</span>] = <span class="hljs-number">92</span>
    gradesMap[<span class="hljs-string">"Michael"</span>] = <span class="hljs-number">78</span>

    <span class="hljs-comment">// Accessing values from the HashMap</span>
    <span class="hljs-keyword">val</span> johnGrade = gradesMap[<span class="hljs-string">"John"</span>]
    println(<span class="hljs-string">"John's Grade: <span class="hljs-variable">$johnGrade</span>"</span>)

    <span class="hljs-comment">// Updating a value in the HashMap</span>
    gradesMap[<span class="hljs-string">"Emily"</span>] = <span class="hljs-number">95</span>
    <span class="hljs-keyword">val</span> updatedEmilyGrade = gradesMap[<span class="hljs-string">"Emily"</span>]
    println(<span class="hljs-string">"Updated Emily's Grade: <span class="hljs-variable">$updatedEmilyGrade</span>"</span>)

    <span class="hljs-comment">// Removing a value from the HashMap</span>
    gradesMap.remove(<span class="hljs-string">"Michael"</span>)
    <span class="hljs-keyword">val</span> michaelGrade = gradesMap[<span class="hljs-string">"Michael"</span>]
    println(<span class="hljs-string">"Michael's Grade: <span class="hljs-variable">$michaelGrade</span>"</span>)

    <span class="hljs-comment">// Checking if a key exists in the HashMap</span>
    <span class="hljs-keyword">val</span> containsJohn = gradesMap.containsKey(<span class="hljs-string">"John"</span>)
    println(<span class="hljs-string">"Does the HashMap contain John? <span class="hljs-variable">$containsJohn</span>"</span>)

    <span class="hljs-comment">// Iterating over the HashMap</span>
    <span class="hljs-keyword">for</span> ((student, grade) <span class="hljs-keyword">in</span> gradesMap) {
        println(<span class="hljs-string">"<span class="hljs-variable">$student</span>: <span class="hljs-variable">$grade</span>"</span>)
    }
}
</code></pre>
<p>Regarding how HashMap generates indices, it uses a hashing function to convert the keys into integer values called hash codes.</p>
<p>The hash codes are then mapped to specific indices in the underlying array using a process called hashing. This allows for efficient storage and retrieval of key-value pairs. The exact hashing algorithm used depends on the implementation of HashMap.</p>
<p>internally, a HashMap in Kotlin uses an array of linked lists (buckets) to store key-value pairs. The hashing function in Kotlin is responsible for converting the key into an integer value called the hash code.</p>
<p>This hash code is used to determine the index (bucket) in the array where the key-value pair will be stored. Let's dive into the internal workings of a HashMap:</p>
<ol>
<li><p>Hashing Function:</p>
<ul>
<li><p>The hashing function in Kotlin is implemented by the <code>hashCode()</code> method, which is defined in the <code>Any</code> class. All objects inherit this method, and it can be overridden for custom types.</p>
</li>
<li><p>The <code>hashCode()</code> method calculates a unique integer value (hash code) for each object based on its internal state. Objects that are considered equal should have the same hash code.</p>
</li>
<li><p>Kotlin provides default implementations of <code>hashCode()</code> for built-in types, such as <code>String</code>, <code>Int</code>, and <code>Boolean</code>.</p>
</li>
</ul>
</li>
<li><p>Hashing and Index Calculation:</p>
<ul>
<li><p>Once the hash code is obtained from the key, the HashMap applies a process called hashing to map the hash code to an index in the underlying array.</p>
</li>
<li><p>The index calculation is performed by applying a transformation to the hash code using bitwise operations and masking to ensure the index falls within the valid range of the array.</p>
</li>
<li><p>The specific algorithm for index calculation can vary based on the HashMap implementation.</p>
</li>
</ul>
</li>
<li><p>Handling Collisions:</p>
<ul>
<li><p>Since multiple keys can potentially have the same hash code or map to the same index, HashMap uses separate chaining to handle collisions.</p>
</li>
<li><p>Each index in the array can hold a linked list of key-value pairs. If multiple keys have the same index, they are stored in the corresponding linked list.</p>
</li>
<li><p>When retrieving a value, the HashMap uses the hash code and equality comparison to find the appropriate key-value pair in the linked list.</p>
</li>
</ul>
</li>
<li><p>Resizing and Load Factor:</p>
<ul>
<li><p>HashMap also implements resizing to maintain a balance between the number of key-value pairs and the capacity of the underlying array.</p>
</li>
<li><p>The load factor is a threshold that determines when to resize the HashMap. When the number of elements exceeds the load factor multiplied by the current capacity, the HashMap is resized by creating a new array with a larger capacity and rehashing all the key-value pairs into the new array.</p>
</li>
<li><p>Resizing allows for efficient storage and retrieval even as the number of key-value pairs increases.</p>
</li>
</ul>
</li>
</ol>
<p>It's important to note that the exact implementation details of hashing functions and collision resolution may vary depending on the HashMap implementation in different versions of Kotlin or different programming languages.</p>
<p>By leveraging the hashing function and handling collisions with linked lists, HashMap provides efficient storage and retrieval of key-value pairs based on their unique keys.</p>
<hr />
<p>We will continue with <a target="_blank" href="https://satyajitdas.tech/essential-data-structures-for-your-upcoming-android-interview-part-2">part 2</a>, discussing the rest of the Data structures. Click <a target="_blank" href="https://satyajitdas.tech/essential-data-structures-for-your-upcoming-android-interview-part-2">here</a> to read . Happy Coding !!</p>
]]></content:encoded></item><item><title><![CDATA[Android Passkey: Enhancing Security and Ease for Signing In]]></title><description><![CDATA[Android Passkey: Public-key cryptography & biometric authentication for secure, convenient website & app sign-ins]]></description><link>https://satyajitdas.hashnode.dev/android-passkey-enhancing-security-and-ease-for-signing-in</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/android-passkey-enhancing-security-and-ease-for-signing-in</guid><category><![CDATA[Android]]></category><category><![CDATA[passkeys]]></category><category><![CDATA[Security]]></category><category><![CDATA[Google]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Sun, 14 May 2023 13:21:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683990233995/b95e58a1-d120-4ed0-a91d-ffe3e8be75ce.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Do you ever forget your passwords? Or maybe you're worried about your passwords being stolen. If so, then you're not alone. Millions of people struggle with passwords every day.</p>
<p>But there's good news! There's a new way to sign in to websites and apps that is both easier and more secure than passwords. It's called Android passkeys.</p>
<h2 id="heading-1-what-is-android-passkey">1. What is Android Passkey?</h2>
<p>Android Passkeys are a more secure and convenient alternative to passwords, allowing users to sign in to apps and websites using biometric sensors, PINs, or patterns instead of traditional passwords.</p>
<p>Passkeys use cryptographic keys instead of strings of characters. This makes them much more secure than traditional passwords, which can be easily guessed or stolen.</p>
<h2 id="heading-2-how-does-android-passkey-work">2. How does Android Passkey work?</h2>
<p>Passkeys are based on public-key cryptography, which allows for secure authentication without the need to store any sensitive data on a server.</p>
<p>When you create a passkey, your device generates a unique public and private key pair. The public key is stored on the server, while the private key is kept secret on your device.</p>
<p>When you log in, the server sends a challenge to your device. Your device uses the private key to generate a response, which is then sent back to the server. If the response is correct, you are logged in.</p>
<p>Passkeys have several advantages over traditional passwords. First, they are much more secure. Because the private key is never stored on a server, it cannot be stolen or hacked.</p>
<p>Second, passkeys are much easier to use. You do not have to remember a long, complex password. Instead, you can simply use your fingerprint or facial recognition to log in.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684067895528/5214a2d4-c9f3-4189-af95-a61cfeeffc6c.webp" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-what-are-the-benefits-of-using-android-passkey">3. What are the benefits of using Android Passkey?</h2>
<ul>
<li><p><strong>They are more secure than passwords.</strong> Passkeys use public-key cryptography, which makes them much more difficult to hack or steal than traditional passwords.</p>
</li>
<li><p><strong>They are easier to use.</strong> You do not have to remember a long, complex passkey. Instead, you can simply use your fingerprint or facial recognition to log in.</p>
</li>
<li><p><strong>They are more portable.</strong> Passkeys are stored on your device, so you can use them on any computer or device that supports them.</p>
</li>
<li><p><strong>They are more future-proof.</strong> Passwords are becoming increasingly obsolete. As more and more websites and apps adopt passkeys, it will become increasingly important to use them.</p>
</li>
</ul>
<h2 id="heading-4-how-to-create-an-android-passkey"><strong>4. How to Create an Android Passkey</strong></h2>
<p>To use CredentialManager for generating a passkey, you can follow these steps:</p>
<ol>
<li><p>Open your app and sign in to establish a session.</p>
</li>
<li><p>Next, your app prompts the user to create a passkey.</p>
</li>
<li><p>The system displays this UI near the bottom of the screen.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684069457809/d5f37c6c-1e69-4556-8463-ee817cd90254.webp" alt class="image--center mx-auto" /></p>
<ol>
<li><p>A passkey is created after receiving the user's consent using the device's screen lock/biometrics. The credential provider creates a new asymmetric key pair and securely stores the private key on the device.</p>
</li>
<li><p>After the suspendable call is resolved, a public key credential containing a new public key, a credential ID, and other attestation data is returned to your app.</p>
</li>
</ol>
<p>The example code shows how to create a passkey using <a target="_blank" href="https://developer.android.com/training/sign-in/passkeys#kotlin">CredentialManager</a></p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Use your app or activity context to instantiate a client instance of</span>
<span class="hljs-comment">// CredentialManager.</span>
<span class="hljs-keyword">val</span> credentialManager = CredentialManager.create(context)

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createPasskey</span><span class="hljs-params">(requestJson: <span class="hljs-type">String</span>, preferImmediatelyAvailableCredentials: <span class="hljs-type">Boolean</span>)</span></span> {
    <span class="hljs-keyword">val</span> createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest(
        <span class="hljs-comment">// Contains the request in JSON format. Uses the standard WebAuthn</span>
        <span class="hljs-comment">// web JSON spec.</span>
        requestJson = requestJson,
        <span class="hljs-comment">// Defines whether you prefer to use only immediately available credentials,</span>
        <span class="hljs-comment">// not hybrid credentials, to fulfill this request. This value is false</span>
        <span class="hljs-comment">// by default.</span>
        preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
    )
    <span class="hljs-comment">// Execute CreateCredentialRequest asynchronously to register credentials</span>
    <span class="hljs-comment">// for a user account. Handle success and failure cases with the result and</span>
    <span class="hljs-comment">// exceptions, respectively.</span>
    coroutineScope.launch {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">val</span> result = credentialManager.createCredential(
                request = createPublicKeyCredentialRequest,
                activity = activity,
            )
            handlePasskeyRegistrationResult(result)
        } <span class="hljs-keyword">catch</span> (e : CreateCredentialException){
            <span class="hljs-comment">//handle error</span>
        }
    }
}
</code></pre>
<p>Source: Google LLC. 2022</p>
<h2 id="heading-5-what-are-some-of-the-limitations-of-android-passkey"><strong>5. What are some of the limitations of Android Passkey?</strong></h2>
<ul>
<li><p><strong>Not all websites and apps support passkeys yet.</strong> This is a rapidly developing technology, and more and more websites and apps are supporting passkeys all the time. However, there are still some that don't, so you may not be able to use passkeys everywhere.</p>
</li>
<li><p><strong>Passkeys are not as secure as hardware security keys.</strong> Hardware security keys are physical devices that you plug into your computer or phone when you log in to websites and apps. They offer an extra layer of security because they are not connected to the internet, so they cannot be hacked remotely. Passkeys are still very secure, but they are not as secure as hardware security keys.</p>
</li>
<li><p><strong>Passkeys can be a bit of a hassle to set up.</strong> You have to create a passkey for each website or app that you want to use. This can be a bit time-consuming, especially if you have a lot of accounts.</p>
</li>
</ul>
<h2 id="heading-6-the-future-of-android-passkey"><strong>6. The future of Android Passkey</strong></h2>
<p>Google has been working on this technology for years, and it is finally starting to gain traction. More and more websites and apps are supporting passkeys, and it is only a matter of time before they become the standard way to log in to online accounts.</p>
<p>There are several reasons why passkeys are so promising. First, they are much more secure than traditional passwords. Passkeys use public-key cryptography, which makes them very difficult to hack or steal.</p>
<p>Second, passkeys are much easier to use than traditional passwords. You do not have to remember a long, complex password. Instead, you can simply use your fingerprint or facial recognition to log in.</p>
<p>As more and more people become aware of the benefits of passkeys, they are likely to become the standard way to log in to online accounts. This will make our online lives much more secure and convenient.</p>
<hr />
<p>In conclusion, Android Passkeys offer a more secure and convenient alternative to traditional passwords for signing in to websites and apps. using public-key cryptography and biometric authentication.</p>
<p>Though not universally supported or as secure as hardware security keys, their adoption is growing, leading to a safer and user-friendly online experience.</p>
<p>If you enjoyed this blog, please give it a like and share it with others who may find it helpful.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Android Memory Management: A Comprehensive Guide]]></title><description><![CDATA[Guide to Android memory management: Optimize resources, improve performance, and enhance user experience]]></description><link>https://satyajitdas.hashnode.dev/understanding-android-memory-management-a-comprehensive-guide</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/understanding-android-memory-management-a-comprehensive-guide</guid><category><![CDATA[Android]]></category><category><![CDATA[memory-management]]></category><category><![CDATA[garbagecollection]]></category><category><![CDATA[#memorymanagement]]></category><category><![CDATA[operatingsystems ]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Fri, 05 May 2023 08:26:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682195852536/f37f70a3-7544-45f9-8321-77e4fe432d54.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-i-introduction">I. Introduction</h2>
<p>Memory management in operating systems is the process of managing the RAM (Random Access Memory) and ensuring that each process and application has access to the required amount of memory.</p>
<p>It involves allocating memory when a process or application needs it, freeing up memory when it is no longer required, and preventing memory leaks and other issues that can arise from inefficient memory usage.</p>
<p>Every Operating system has its own way of managing memory so does Android. The foundation of the Android platform is the Linux kernel. the Android Runtime (ART) relies on the Linux kernel for underlying functionalities such as threading and low-level memory management.</p>
<p><img src="https://developer.android.com/static/guide/platform/images/android-stack_2x.png" alt class="image--center mx-auto" /></p>
<p>Efficient memory management helps to ensure that each process and application has access to the required amount of memory, preventing memory leaks and other issues that can arise from inefficient memory usage.</p>
<p>It also helps to conserve battery life by reducing unnecessary memory usage. Overall, proper memory management is essential for a smooth and efficient user experience on Android devices.</p>
<p>In this blog, we will cover how the system manages memory internally.</p>
<h2 id="heading-ii-types-of-memory">II. Types Of Memory</h2>
<p>Android has 3 Types of Memory. Ram, zRam &amp; Storage</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683316868875/4ab9b5a3-ce02-43f5-8b98-b6bbd6e7c607.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>RAM:</strong> it's the fastest type of memory, but is usually limited in size. High-end devices typically have the largest amounts of RAM. This is the prime memory that handles all ongoing operations.</p>
</li>
<li><p><strong>zRAM:</strong> It's a partition of RAM used for swap space. Everything is compressed when placed into zRAM, and then decompressed when copied out of zRAM. This portion of RAM grows or shrinks in size as pages are moved into or taken out of zRAM. Device manufacturers can set the maximum size.</p>
</li>
<li><p><strong>Storage</strong>: It contains all of the persistent data such as the file system and the included object code for all apps, libraries, and the platform. Storage has much more capacity than the other two types of memory. On Android, storage isn’t used for swap space like it is on other Linux implementations since frequent writing can cause wear on this memory, and shorten the life of the storage medium.</p>
</li>
</ul>
<h2 id="heading-iii-memory-pages">III. Memory Pages</h2>
<p>RAM is broken up into <em>pages</em>. Typically each page is 4KB of memory.</p>
<p>Pages are considered either <strong><em>free</em></strong> or <strong><em>used</em></strong>. Free pages are unused RAM. Used pages are RAM that the system is actively using, and are grouped into the following categories:</p>
<ol>
<li><p><strong>Cached</strong>: Memory backed by a file on storage (for example, code or memory-mapped files). There are two types of cached memory:/</p>
<ul>
<li><p><strong>Private: Owned by one process and not shared</strong></p>
<ul>
<li><p><em>Clean: Unmodified copy of a file on storage, can be deleted by</em> <code>kswapd</code> <em>to increase free memory</em></p>
</li>
<li><p><em>Dirty: Modified copy of the file on storage; can be moved to, or compressed in, zRAM by</em> <code>kswapd</code> <em>to increase free memory</em></p>
</li>
</ul>
</li>
<li><p><strong>Shared: Used by multiple processes</strong></p>
<ul>
<li><p>Clean: Unmodified copy of the file on storage, which can be deleted by <code>kswapd</code> to increase free memory</p>
</li>
<li><p>Dirty: Modified copy of the file on storage; allows changes to be written back to the file in storage to increase free memory by <code>kswapd</code>, or explicitly using <a target="_blank" href="https://developer.android.com/reference/android/system/Os#msync(long,%2520long,%2520int)"><code>msync()</code></a> or <a target="_blank" href="https://developer.android.com/reference/android/system/Os#munmap(long,%2520long)"><code>munmap</code></a></p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<hr />
<ol>
<li><p><strong>Anonymous</strong>: Memory <strong>not</strong> backed by a file on storage (for example, allocated by <a target="_blank" href="https://developer.android.com/reference/android/system/Os#mmap(long,%2520long,%2520int,%2520int,%2520java.io.FileDescriptor,%2520long)"><code>mmap()</code></a> with the <code>MAP_ANONYMOUS</code> flag set)</p>
<p> it is a Dirty page that can be moved/compressed in zRAM by <code>kswapd</code> to increase free memory</p>
</li>
</ol>
<h2 id="heading-iv-low-memory-killer">IV. Low Memory Killer</h2>
<p>When free memory falls below the low threshold, <code>kswapd</code> starts to reclaim memory. Once the free memory reaches the high threshold, <code>kswapd</code> stops reclaiming memory.</p>
<p><strong>Clean Page :</strong> <code>kswapd</code> can reclaim clean pages by deleting them because they're backed by storage and have not been modified.</p>
<p>If a process tries to address a <code>clean</code> page that has been deleted, the system copies the page from storage to <strong>RAM</strong>. This operation is known as <a target="_blank" href="https://www.javatpoint.com/os-demand-paging"><code>demand paging</code></a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683316887713/bf7b726f-e5f5-4e71-be4b-8cca88b19a8e.png" alt class="image--center mx-auto" /></p>
<hr />
<p><strong>Dirty Pages:</strong> <code>kswapd</code> can move cached private <strong>dirty</strong> pages and anonymous dirty pages to zRAM, where they are compressed. Doing so frees up available memory in RAM (free pages).</p>
<p>If a process tries to touch a dirty page in zRAM, the page is uncompressed and moved back into RAM. If the process associated with a compressed page is killed, then the page is deleted from zRAM.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683316899299/9cf4e70b-400e-478d-895b-1722e19662e3.png" alt class="image--center mx-auto" /></p>
<hr />
<p>If the amount of free memory falls below a certain threshold, the system starts killing processes. To decide which process to kill, LMK uses an "out of memory" score called <a target="_blank" href="https://android.googlesource.com/platform/system/memory/lmkd/+/master/README.md"><code>oom_adj_score</code></a> to prioritize the running processes.</p>
<p>Processes with a high score are killed first. Background apps are first to be killed, and system processes are last to be killed. The following table lists the LMK scoring categories from high-to-low. Items in the highest-scoring category, in row one, will be killed first:</p>
<h3 id="heading-v-garbage-collection">V. Garbage Collection</h3>
<p>Garbage collection in Android identifies and releases memory that is no longer being used by the app, helping to prevent memory leaks and ensure efficient memory usage.</p>
<p>It involves marking live objects in the heap, traversing the object graph to mark all reachable objects, sweeping away unreachable objects to free up memory, and compacting remaining live objects to reduce memory fragmentation.</p>
<p>In Android Garbage collection runs when System want to release the app completely from the heap or while the user using the app if any object reference is not required any more.</p>
<h2 id="heading-vi-switch-apps">VI. Switch Apps</h2>
<p>When users switch between apps, Android keeps apps that are not foreground—that is, not visible to the user or running a foreground service like music playback— in a cache.</p>
<p>For example, when a user first launches an app, a process is created for it; but when the user leaves the app, that process does <em>not</em> quit. The system keeps the process cached. If the user later returns to the app, the system reuses the process, thereby making the app switching faster.</p>
<p>If your app has a cached process and it retains resources that it currently does not need, then your app—even while the user is not using it— affects the system's overall performance.</p>
<p>As the system runs low on resources like memory, it kills processes in the cache. The system also accounts for processes that hold onto the most memory and can terminate them to free up RAM.</p>
<p><strong>Note:</strong> The less memory your app consumes while in the cache, the better its chances are not to be killed and to be able to quickly resume. However, depending on instantaneous system requirements, it's possible for cached processes to be terminated at any time no matter their resource utilization.</p>
<hr />
<p>In conclusion, understanding Android memory management is crucial for optimizing app performance and ensuring a smooth user experience.</p>
<p>By learning about the types of memory, memory pages, low memory killer, garbage collection, and app switching, developers can create efficient apps that make the best use of available resources.</p>
<p>Proper memory management helps conserve battery life and reduces the likelihood of app termination due to low memory conditions.</p>
<hr />
<p>That's all for now. If you enjoyed the article, please give it a thumbs up. Thank you for reading! :)</p>
]]></content:encoded></item><item><title><![CDATA[Kotlin Delegation Functions]]></title><description><![CDATA[Master Kotlin delegation for resource management and interface implementation. Improve projects with practical examples and versatile features]]></description><link>https://satyajitdas.hashnode.dev/kotlin-delegation-functions</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/kotlin-delegation-functions</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[delegation]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Wed, 03 May 2023 11:51:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683114092195/4648791f-24e2-4c4e-82d8-9770f780f4f9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Discover the power of Kotlin delegation functions, a versatile feature that allows you to delegate operations between objects, implement interfaces, and manage resources efficiently.</p>
<p>In this article, we'll explore the benefits of using delegation functions in your Kotlin projects and provide practical examples to demonstrate their usage.</p>
<p>In Kotlin, a delegation function allows one object to delegate certain operations to another object.</p>
<p>For example, let's say you have two classes: <code>ClassA</code> and <code>ClassB</code>. <code>ClassB</code> wants to use some of the functionality of <code>ClassA</code> without inheriting from it. This is where delegation comes in.</p>
<p>Instead of <code>ClassB</code> inheriting from <code>ClassA</code>, it can delegate the functionality it needs to an instance of <code>ClassA</code>. This is done using the <code>by</code> keyword.</p>
<hr />
<p>Here's an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassA</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">someFunction</span><span class="hljs-params">()</span></span> {
        println(<span class="hljs-string">"Hello from ClassA"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassB</span></span>(a: ClassA) {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> classA = a

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">callSomeFunction</span><span class="hljs-params">()</span></span> {
        classA.someFunction()
    }
}
</code></pre>
<p>In this example, <code>ClassB</code> is delegating the <code>someFunction()</code> operation to an instance of <code>ClassA</code>.</p>
<p>We create an instance of <code>ClassA</code> and pass it to <code>ClassB</code>'s constructor. <code>ClassB</code> stores this instance in a private variable called <code>classA</code>.</p>
<p>Then, <code>ClassB</code> has a function called <code>callSomeFunction()</code> which calls <code>someFunction()</code> on the <code>classA</code> instance.</p>
<p>We can simplify this code by using the <code>by</code> keyword to delegate the functionality:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassB</span></span>(a: ClassA) <span class="hljs-keyword">by</span> a {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">callSomeFunction</span><span class="hljs-params">()</span></span> {
        someFunction()
    }
}
</code></pre>
<p>In this version, we're saying that <code>ClassB</code> will delegate all of its functions and properties to an instance of <code>ClassA</code>. We don't need to store the instance in a variable or call <code>someFunction()</code> using the <code>classA</code> variable. Instead, we can call it directly with <code>someFunction()</code>.</p>
<hr />
<p><strong>Another Example: Delegating interface implementation</strong></p>
<p>if we have an interface called <code>MyInterface</code>, we can create a class that implements this interface and then delegate its implementation to another object. This can be done using the <code>by</code> keyword and passing in the object that we want to delegate to. Here's an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">MyInterface</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doSomething</span><span class="hljs-params">()</span></span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyInterfaceImpl</span> : <span class="hljs-type">MyInterface {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">doSomething</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Doing something..."</span>)
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> : <span class="hljs-type">MyInterface by MyInterfaceImpl</span></span>()

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">val</span> obj = MyClass()
  obj.doSomething() <span class="hljs-comment">// output: "Doing something..."</span>
}
</code></pre>
<p>In this example, we have an interface called <code>MyInterface</code> and a class called <code>MyInterfaceImpl</code> that implements it. We then create a class called <code>MyClass</code> and delegate its implementation of <code>MyInterface</code> to <code>MyInterfaceImpl</code> using the <code>by</code> keyword.</p>
<p>When we create an instance of <code>MyClass</code> and call <code>doSomething()</code>, it delegates the call to the <code>MyInterfaceImpl</code> object and prints "Doing something..." to the console.</p>
<h3 id="heading-use-cases">Use Cases :</h3>
<ul>
<li><p><strong>Implementing interfaces:</strong> Kotlin delegation allows you to implement interfaces without implementing all of their methods. You can create a separate class that implements the interface and then delegate the implementation of the interface methods to that class.</p>
</li>
<li><p><strong>Property delegation:</strong> Kotlin delegation allows you to delegate property access to a separate object, which can handle getting and setting the property values. This can be useful for implementing lazy properties, observable properties, and properties that need to be initialized dynamically.</p>
</li>
<li><p><strong>Resource management:</strong> Kotlin delegation can be used for resource management, such as closing database connections or file handles when they are no longer needed. You can create a separate class that handles the resource management and delegate to it the class that uses the resources.</p>
</li>
<li><p><strong>Decorator pattern:</strong> Kotlin delegation can be used to implement the decorator pattern, where you have a base class and one or more decorator classes that add functionality to the base class. You can use delegation to delegate the base class functionality to the decorator classes.</p>
</li>
<li><p><strong>Dependency injection:</strong> Kotlin delegation can be used for dependency injection, where you create a separate class that provides the dependencies and then delegate to it in the class that needs the dependencies. This can help to reduce coupling between classes and make your code more modular.</p>
</li>
</ul>
<p>These are just a few examples of how Kotlin delegation can be used. It's a powerful feature that can help to make your code more modular and reusable.</p>
<hr />
<p>That's all for now. If you enjoyed this article, please give it a thumbs-up and subscribe to my newsletter for more.</p>
]]></content:encoded></item><item><title><![CDATA[Why Jetpack Compose is the Way Forward for Android App Development]]></title><description><![CDATA[4 Reasons Why Jetpack Compose is the Future of Android App Development]]></description><link>https://satyajitdas.hashnode.dev/why-jetpack-compose-is-the-way-forward-for-android-app-development</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/why-jetpack-compose-is-the-way-forward-for-android-app-development</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Jetpack Compose]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Thu, 27 Apr 2023 13:28:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682601679619/c879e036-5044-4872-a1a5-c3f8cf846cc5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Jetpack Compose is a modern toolkit for building native Android UIs. It simplifies and accelerates UI development by providing a declarative way to build UI components, making it easier to create complex layouts and animations.</p>
<p>Unlike the traditional Android View system, Jetpack Compose is built on Kotlin, which allows for easier integration with the rest of the Android ecosystem. With Jetpack Compose, developers can create beautiful, responsive, and performant UIs in <strong>less time</strong> and with <strong>less code</strong>.</p>
<h3 id="heading-declarative-ui"><strong>Declarative UI:</strong></h3>
<p>Jetpack Compose provides a declarative way of building UI components, which makes it easier to create complex layouts and animations with less code.</p>
<p>XML :</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">LinearLayout</span>
   <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/my_linearlayout"</span>
   <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"match_parent"</span>
   <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
   <span class="hljs-attr">android:orientation</span>=<span class="hljs-string">"vertical"</span>&gt;</span>

   <span class="hljs-tag">&lt;<span class="hljs-name">TextView</span>
       <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/textview1"</span>
       <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span>
       <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
       <span class="hljs-attr">android:text</span>=<span class="hljs-string">"TextView 1"</span> /&gt;</span>

   <span class="hljs-tag">&lt;<span class="hljs-name">TextView</span>
       <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/textview2"</span>
       <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span>
       <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
       <span class="hljs-attr">android:text</span>=<span class="hljs-string">"TextView 2"</span> /&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">LinearLayout</span>&gt;</span>
</code></pre>
<p>Compose :</p>
<pre><code class="lang-kotlin">Column {
   Text(<span class="hljs-string">"TextView 1"</span>)
   Text(<span class="hljs-string">"TextView 2"</span>)
}
</code></pre>
<p>Example 2 :</p>
<p><code>XML:</code></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">androidx.recyclerview.widget.RecyclerView</span>
   <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/my_recyclerview"</span>
   <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"match_parent"</span>
   <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"match_parent"</span> /&gt;</span>
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> recyclerView = findViewById&lt;RecyclerView&gt;(R.id.my_recyclerview)
<span class="hljs-keyword">val</span> adapter = MyAdapter(<span class="hljs-keyword">data</span>)
recyclerView.adapter = adapter
</code></pre>
<p>Then further another 60-80 lines of code for vidwHolder, Adapter, item blah blah.</p>
<p><code>Compose:</code></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> <span class="hljs-keyword">data</span> = listOf(<span class="hljs-string">"Item 1"</span>, <span class="hljs-string">"Item 2"</span>, <span class="hljs-string">"Item 3"</span>)

LazyColumn {
   items(<span class="hljs-keyword">data</span>) { item -&gt;
      Text(text = item)
   }
}
</code></pre>
<h3 id="heading-kotlin-integration">Kotlin Integration</h3>
<p>Jetpack Compose is built on <strong>Kotlin</strong>, which allows for easier integration with the rest of the Android ecosystem, and leveraging all the power of Kotlin while creating composable Functions.</p>
<p>It uses various Kotlin features such as <a target="_blank" href="https://play.kotlinlang.org/byExample/04_functional/03_extensionFunctions"><code>extension functions</code></a>, <a target="_blank" href="https://kotlinlang.org/docs/operator-overloading.html"><code>operator overloading</code></a>, and <a target="_blank" href="https://play.kotlinlang.org/byExample/04_functional/02_Lambdas"><code>lambda expressions</code></a> to create composable functions that can be reused and combined to build complex UIs.</p>
<p>For example, Compose provides composable functions like <code>Text()</code>, <code>Button()</code>, and <code>Column()</code> that can be used to create UI components.</p>
<p>These functions can be combined to create more complex UIs and layouts. Additionally, Compose uses Kotlin's <code>type inference</code> and <code>null safety</code> features to reduce boilerplate code and catch errors at compile time.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">MyScreenContent</span><span class="hljs-params">(names: <span class="hljs-type">List</span>&lt;<span class="hljs-type">String</span>&gt; = listOf(<span class="hljs-string">"Android"</span>, <span class="hljs-string">"there"</span>)</span></span>) {
    Column(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
        Text(text = <span class="hljs-string">"Hello, <span class="hljs-subst">${names.first()}</span>!"</span>)
        LazyColumn {
            items(names) { name -&gt;
                Greeting(name = name)
                Divider(color = Color.Black)
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Greeting</span><span class="hljs-params">(name: <span class="hljs-type">String</span>)</span></span> {
    Text(text = <span class="hljs-string">"Hello <span class="hljs-variable">$name</span>!"</span>, modifier = Modifier.padding(<span class="hljs-number">24</span>.dp))
}
</code></pre>
<h3 id="heading-improved-performance">Improved Performance:</h3>
<p>Jetpack Compose is designed to be more performant than traditional XML-based UI development, with faster rendering times and improved memory usage.</p>
<p>it improves performance by reducing the number of UI updates, which results in faster rendering times and improved memory usage.</p>
<p>This is achieved through the use of a unidirectional data flow architecture, where state changes are propagated from a single source of truth to the UI components that depend on them.</p>
<p>As a result, only the <strong>affected UI</strong> components are re-rendered, instead of the entire UI hierarchy. This approach can lead to significant performance improvements, especially for complex UIs with many dynamic elements.</p>
<h3 id="heading-simplified-ui-development">Simplified UI Development:</h3>
<p>Jetpack Compose simplifies and accelerates UI development, making it easier to create beautiful, responsive, and performant UIs in less time and with less code.</p>
<p>No need to create multiple XML files and go back and forth. One single file will likely contain everything that is responsible for the specific screen.</p>
<hr />
<p>With Compose, bringing movement and life to your apps through animations is quick and easy to implement: “<em>Animations are so easy to add in Compose that there’s very little reason not to animate things like colour/size/elevation changes</em>” (Monzo), “<em>you can make animations without requiring anything special -- it’s no different than showing a static screen</em>” - <a target="_blank" href="https://squareup.com/us/en?v=all">Square</a></p>
<p>With Compose, you build small, stateless components that are not tied to a specific activity or fragment. That makes them easy to reuse and test: “<em>We set a goal for ourselves to deliver a new set of UI components that were stateless, easy to use and maintain, and intuitive to implement/extend/customize. Compose really provided a solid answer for us in this.</em>” - <a target="_blank" href="https://twitter.com/">Twitter</a></p>
<hr />
<p>In the Next blog, we will see how Compose draws UI internally.</p>
<p>If you found this article helpful, please give it a thumbs up. Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[What are Type aliases in Kotlin?]]></title><description><![CDATA[Type alias in Kotlin is a feature that allows you to give a new name to an existing type. It can help make your code more readable and easier to…]]></description><link>https://satyajitdas.hashnode.dev/what-are-type-aliases-in-kotlin</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/what-are-type-aliases-in-kotlin</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Mon, 17 Apr 2023 21:24:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681766508286/4820bb7e-eb6d-448b-a473-e75a12ddc765.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Type alias in Kotlin is a feature that allows you to give a new name to an existing type. It can help make your code more readable and easier to understand.</p>
<p>Here's an example: let's say you're working on an Android app and you're using the type <code>Pair&lt;String, Int&gt;</code> a lot in your code. Instead of writing <code>Pair&lt;String, Int&gt;</code> every time you need to use it, you can create a type alias for it:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">typealias</span> StringIntPair = Pair&lt;String, <span class="hljs-built_in">Int</span>&gt;
</code></pre>
<p>Now you can use the <code>StringIntPair</code> type alias instead of <code>Pair&lt;String, Int&gt;</code> in your code. Here's an example:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> pair: StringIntPair = <span class="hljs-string">"foo"</span> to <span class="hljs-number">42</span>
</code></pre>
<p>This is the same as writing:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> pair: Pair&lt;String, <span class="hljs-built_in">Int</span>&gt; = <span class="hljs-string">"foo"</span> to <span class="hljs-number">42</span>
</code></pre>
<p>Type aliases can also be used with generic types, nullable types, and function types. For example, the following code defines a type alias for a nullable function that takes two integers as arguments and returns a nullable integer</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">typealias</span> MyFunction = ((<span class="hljs-built_in">Int</span>, <span class="hljs-built_in">Int</span>) -&gt; <span class="hljs-built_in">Int</span>)?
</code></pre>
<p>Now you can use the type alias "MyFunction" instead of the function type <code>((Int, Int) -&gt; Int)?</code>. For example, the following code creates a variable of type "MyFunction" and assigns a lambda expression to it:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> myFunction: MyFunction = { a, b -&gt; a + b }
</code></pre>
<p>This is equivalent to creating a variable of the type <code>((Int, Int) -&gt; Int)?</code> and assign a lambda expression to it:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> myFunction: ((<span class="hljs-built_in">Int</span>, <span class="hljs-built_in">Int</span>) -&gt; <span class="hljs-built_in">Int</span>)? = { a, b -&gt; a + b }
</code></pre>
<p>You can have new names for <code>inner nested classes</code></p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> </span>{
    <span class="hljs-keyword">inner</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Inner</span></span>
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> </span>{
    <span class="hljs-keyword">inner</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Inner</span></span>
}

<span class="hljs-keyword">typealias</span> AInner = A.Inner
<span class="hljs-keyword">typealias</span> BInner = B.Inner
</code></pre>
<p>You can even use resource file names.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">typealias</span> Drawable = R.drawable
<span class="hljs-keyword">typealias</span> Layout = R.layout

setContentView(Layout.activity_main)
imageView.setImageDrawable(ContextCompat.getDrawable(<span class="hljs-keyword">this</span>,Drawable.ic_launcher_background))
</code></pre>
<p>In general, type aliases can make your code more concise and easier to read. They're especially useful when you're working with complex types or when you want to create your own custom types that are more specific to your app's needs.  </p>
<p>This is all about <strong>typeAlias</strong> in Koltin.</p>
<p>Happy learning.</p>
]]></content:encoded></item><item><title><![CDATA[How Do Image Loading Libraries work internally In Android?]]></title><description><![CDATA[How do Image loading libraries like glide Picasso works internally in Android?]]></description><link>https://satyajitdas.hashnode.dev/how-do-image-loading-libraries-work-internally-in-android</link><guid isPermaLink="true">https://satyajitdas.hashnode.dev/how-do-image-loading-libraries-work-internally-in-android</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[android apps]]></category><category><![CDATA[imageloadinglibrary]]></category><category><![CDATA[glide]]></category><dc:creator><![CDATA[Satyajit Das]]></dc:creator><pubDate>Wed, 29 Mar 2023 22:28:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680809108782/fa8bfbdb-b1fe-45b5-9d6c-876907567b37.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-why-does-a-image-loading-library-exist">Why Does A Image Loading Library Exist?</h3>
<p>Why utilize an external library should be the first question that pops into your head. Is it only because we want to write fewer lines of code? perhaps it has additional aspects. Let's learn the fundamentals of loading an image from a URL.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680809251984/dc8a2dc5-3aac-40f0-95f3-8678246d5d91.png" alt class="image--center mx-auto" /></p>
<p>It appears simple. This approach will work for the app's single image. However, as the number of images increases, you will begin to experience these issues.</p>
<ul>
<li><p><strong>The app will feel unresponsive and Laggy</strong> - Because a large amount of memory will be allocated to these images in the heap, and the <a target="_blank" href="https://developer.android.com/topic/performance/memory-overview#gc">GC</a> will attempt to release the memory whenever this image view is off the screen.</p>
</li>
<li><p><strong>Out Of Memory and App crash</strong> - Because our heap has a limited amount of memory if we keep assigning it multiple images, eventually it will run out of memory and the app will crash.</p>
</li>
<li><p><strong>Slow Loading of Images and Poor UX</strong> - Since we will be loading images one at a time, this method will slow down the loading of the images.</p>
<p>  As an example, if there are 20 images on the screen and the user scrolls to image number 20, the first 19 images will load before the 20th one. Additionally, the user wants to view the image of the spot where he is now, so this is an awful user experience.</p>
</li>
</ul>
<p>Now let's see how these libraries fix these problems for us and make our life easier.</p>
<h3 id="heading-1-how-does-image-loading-library-add-responsiveness-to-the-app">1. How does Image Loading Library add Responsiveness to the App?</h3>
<p>The Answer is BitmapPool.</p>
<p>In Android, a Bitmap Pool is a cache that keeps reusable Bitmap objects in memory. The purpose of a Bitmap Pool is to reduce the frequency of garbage collection and improve performance by recycling Bitmaps that are no longer being used.</p>
<p>When you load Bitmaps in your Android application, the system allocates memory for each Bitmap object. When the Bitmap is no longer needed, the memory used by the Bitmap is released and can be reused by the system.</p>
<p>However, allocating new memory for Bitmaps can be expensive and cause performance issues if done frequently.</p>
<p>By using a Bitmap Pool, you can reuse Bitmaps that are no longer being used instead of allocating new memory each time. This can improve the performance of your application and reduce the frequency of <a target="_blank" href="https://developer.android.com/topic/performance/memory-overview#gc">garbage collection</a>.</p>
<p>Here's an example of how to create and use a Bitmap Pool in Android:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Create a Bitmap Pool with the desired size</span>
BitmapPool bitmapPool = <span class="hljs-keyword">new</span> LruBitmapPool(maxSizeBytes);

<span class="hljs-comment">// Load a Bitmap into memory</span>
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);

<span class="hljs-comment">// Get a Bitmap from the pool, or allocate a new one</span>
Bitmap pooledBitmap = bitmapPool.get(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);

<span class="hljs-comment">// Set the pixels of the pooled Bitmap to match the original Bitmap</span>
pooledBitmap.setPixels(bitmap.getPixels(), <span class="hljs-number">0</span>, bitmap.getWidth(), <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, bitmap.getWidth(), bitmap.getHeight());

<span class="hljs-comment">// Use the Bitmap</span>

<span class="hljs-comment">// When the Bitmap is no longer needed, return it to the pool</span>
bitmapPool.put(pooledBitmap);
</code></pre>
<p>In the above example, a Bitmap Pool is created using the LruBitmapPool implementation with the maximum size in bytes that the pool can hold.</p>
<p>The code then loads a Bitmap and retrieves a Bitmap object from the pool using the <code>get()</code> method. If there is no available Bitmap in the pool, a new Bitmap is allocated.</p>
<p>The pixels of the new Bitmap is set to match the original Bitmap, and the pooled Bitmap is used for the intended purpose. When the Bitmap is no longer needed, it should be returned to the pool using the <code>put()</code> method.</p>
<p>For example, if our bitmap pool is capable of holding 20 bitmaps and the user is scrolling through a list of 40 images when the user will reach the 21st position, the memory of the 1st bitMap will be reused to store the 21st bitmap</p>
<pre><code class="lang-java"><span class="hljs-keyword">final</span> BitmapFactory.Options options = <span class="hljs-keyword">new</span> BitmapFactory.Options();
options.inJustDecodeBounds = <span class="hljs-keyword">true</span>;

<span class="hljs-comment">//Decoding bitmap from file</span>
BitmapFactory.decodeFile(filePathTwntyOne, options); 
options.inMutable = <span class="hljs-keyword">true</span>;

<span class="hljs-comment">//attempt to reuse bitmapOne when loading content</span>
options.inBitmap = bitmapOne;
options.inJustDecodeBounds = <span class="hljs-keyword">false</span>;

Bitmap bitmapTwentyOne = BitmapFactory.decodeFile(filePathTwntyOne, options);
imageView.setImageBitmap(bitmapTwentyOne);
</code></pre>
<p>You can read more about BitmapFactory <a target="_blank" href="https://developer.android.com/reference/android/graphics/BitmapFactory">here</a>.</p>
<h3 id="heading-2-how-do-image-loading-libraries-solve-outofmemory-issues">2. How do Image Loading Libraries solve OutOfMemory issues?</h3>
<p>The Answer is the downsampling of the image.</p>
<p>Image downsampling is the process of decreasing the resolution of a digital image. Downsampling is done by reducing the number of pixels in the image, which in turn reduces the amount of information stored in the image.</p>
<p>The process of downsampling can be used to reduce the file size of an image or to create a smaller version of the same image.</p>
<p>Downsampling can be achieved by removing every other pixel in a specified direction, or by taking an average of adjacent pixels to create a new, smaller image. Image downsampling can also be referred to as image resampling or image scaling.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680809556970/a1fa13b6-f5ea-4588-85d3-dbd3d8eb26b4.png" alt class="image--center mx-auto" /></p>
<p>After Downloading the Entire image File from the URL The Library Downsample it to the size of imageView.</p>
<p>As an example, the downloaded image resolution may be 1920*1080 but our imageView size is 420*270. So we don't need to decode the whole image in 1920*1080 resolution which will waste resources unless you have explicitly told the library not to downsample it. So it gets downsampled to 420*270 and sent to imageView.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680809525464/11f70e93-cc17-4517-814e-e59e464cd898.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> Bitmap <span class="hljs-title">getResizedBitmap</span><span class="hljs-params">(<span class="hljs-keyword">int</span> targetW, <span class="hljs-keyword">int</span> targetH,  String imagePath)</span> </span>{

    <span class="hljs-comment">// Get the dimensions of the bitmap</span>
    BitmapFactory.Options bmOptions = <span class="hljs-keyword">new</span> BitmapFactory.Options();

    <span class="hljs-comment">//inJustDecodeBounds = true &lt;-- will not load the bitmap into memory</span>
    bmOptions.inJustDecodeBounds = <span class="hljs-keyword">true</span>;
    BitmapFactory.decodeFile(imagePath, bmOptions);
    <span class="hljs-keyword">int</span> photoW = bmOptions.outWidth;
    <span class="hljs-keyword">int</span> photoH = bmOptions.outHeight;

    <span class="hljs-comment">// Determine how much to scale down the image</span>
    <span class="hljs-keyword">int</span> scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    <span class="hljs-comment">// Decode the image file into a Bitmap sized to fill the View</span>
    bmOptions.inJustDecodeBounds = <span class="hljs-keyword">false</span>;
    bmOptions.inSampleSize = scaleFactor;

    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
    <span class="hljs-keyword">return</span>(bitmap);
}
</code></pre>
<h3 id="heading-3-how-image-loading-libraries-solve-the-slow-loading-issue"><strong>3. How Image Loading Libraries solve the Slow loading issue?</strong></h3>
<p>Here 2 things come into the picture. <strong>Prioritizing</strong> and <strong>deprioritizing</strong> the image request and <strong>Cache Management</strong>.</p>
<p><strong>Prioritizing Request</strong></p>
<p>Multiple image requests may be added to the queue when switching from one page to another. However, we must load the images where the user is at the moment according to the precedence.</p>
<p>As we provide the context to the imageLoading request it exactly knows what is the exact position of the user. And based on that it prioritizes the request. As a result, the current screen images load as soon as possible.</p>
<hr />
<p><strong>Cache Management</strong></p>
<p>Memory caching and disk caching are two different types of caching mechanisms used in image-loading libraries:</p>
<p><strong>Memory Caching:</strong> It is the process of temporarily storing data (in this case, images) in the device's RAM or memory. When the data is accessed again, it can be loaded more quickly since it's stored in memory.</p>
<p>Memory caching is ideal for frequently accessed data, such as images that are repeatedly displayed on the screen.</p>
<p>The drawback of memory caching is that it can consume a lot of RAM, leading to memory overflow and crashes. This is why we use the Bitmap pool as discussed above.</p>
<p><strong>Disk Caching:</strong> It is the process of saving data (in this case, images) to the device's local storage. When the data is accessed again, it's loaded from the disk instead of being downloaded from the internet or server, which can be slower.</p>
<p>Disk caching is ideal for infrequently accessed data since it doesn't consume memory as memory caching does. The drawback of disk caching is that it requires more storage space on the device, and the read/write operations can also be slow.</p>
<p>whenever a new request is introduced to the queue it first looks for the image in-memory cache. If it is not found, look in the disc cache. If that fails, go to the source URL to obtain the downsample and set it as the imageView.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680809581881/a51ab46b-5e15-449c-b8ad-72197dbf39b7.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>As we have seen, image-loading libraries not only allow us to write less code but also directly address several more difficult problems, making the lives of developers much simpler.</p>
<p>Here is an LLD of these libraries.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681065881831/2b523cc3-2d15-42ab-b9ea-839ca6b73ece.png" alt class="image--center mx-auto" /></p>
<p>Some of the popular Image loading libraries are <a target="_blank" href="https://github.com/bumptech/glide">Glide</a>, <a target="_blank" href="https://github.com/square/picasso">Picasso</a>, <a target="_blank" href="https://frescolib.org/">Freso</a>, and <a target="_blank" href="https://coil-kt.github.io/coil/">COIL</a>.</p>
]]></content:encoded></item></channel></rss>