A Short Note – In Which Order Custom Code Executes At Launch Time In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (In Which Order Custom Code Executes At Launch Time In iOS ?).

In this note series, we will learn about the App Launch Sequence in iOS. We will discuss the order that our custom code executes at launch time in iOS.

So Let’s begin.


Overview

Launching an app involves a complex sequence of steps, most of which UIKit handles automatically. During the launch sequence, UIKit calls methods of our app delegate so we can perform custom tasks. 

In Figure illustrates the sequence of below steps that occur from the time the app is launched until it is considered initialized.

  1. The app is launched, either explicitly by the user or implicitly by the system.
  2. The XCode-provided main function calls UIKit’s UIApplicationMain(_:_:_:_:) function.
  3. The UIApplicationMain(_:_:_:_:) function creates the UIApplication object and our app delegate.
  4. UIKit loads our app’s default interface from the main storyboard or nib file.
  5. UIKit calls our app delegate’s application(_:willFinishLaunchingWithOptions:) method.
  6. This UIKit performs state restoration, which calls for additional methods of our app delegate and view controllers.
  7. UIKit calls our app delegate’s application(_:didFinishLaunchingWithOptions:) method .

When initialization is complete, the system uses either our scene delegates or app delegate to display our UI and manage the life cycle for our app.


Conclusion

In this note series, we understood about the App Launch Sequence in iOS. We discussed the order that our custom code executes at launch time in iOS.

Thanks for reading! I hope you enjoyed and learned about App Launch Sequence concepts in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How To Perform One-Time Setup For iOS App ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How To Perform One-Time Setup For iOS App ?).

In this note series, we will learn about how to perform one-time setup for iOS application. We will discuss how to ensure proper configuration of our app environment.

So Let’s begin.


Overview

When the user launches our app for the first time, we might want to prepare our app environment by performing some one-time tasks. For example, we might want to:

  • Download required data from our server.
  • Copy document templates or modifiable data files from our app bundle to a writable directory.
  • Configure default preferences for the user.
  • Set up user accounts or gather other required data.

Perform any one-time tasks in our app delegate’s application(_:willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions:) method. Never block the app’s main thread for tasks that do not require user input. Instead, start tasks asynchronously using a dispatch queue, and let them run in the background while our app finishes launching. For tasks that require user input, make all changes to our user interface in the application(_:didFinishLaunchingWithOptions:) method.


Install Files in the Proper Locations

Our app has its own container directory for storing files, and we should always place app-specific files in the ~/Library subdirectory. Specifically, store our files in the following ~/Library subdirectories:

  • ~/Library/Application Support/—Store app-specific files that we want backed up with the user’s other content. (We can create custom subdirectories here as needed.) Use this directory for data files, configuration files, document templates, and so on.
  • ~/Library/Caches/—Store temporary data files that can be easily regenerated or downloaded.

To obtain a URL for one of the directories in our app’s container, use the urls(for:in:) method of FileManager.

let appSupportURL = FileManager.default.urls(for: 
      .applicationSupportDirectory, in: .userDomainMask)

let cachesURL = FileManager.default.urls(for: 
      .cachesDirectory, in: .userDomainMask)

Place any temporary files in our app’s tmp/ directory. Temporary files might include compressed files that we intend to delete once their contents have been extracted and installed elsewhere. Retrieve the URL for our app’s temporary directory using the temporaryDirectory method of FileManager.


Conclusion

In this note series, we understood how to perform one-time setup for iOS application. We also discussed how to ensure proper configuration of our app environment.

Thanks for reading! I hope you enjoyed and learned about Proper App Environment Configuration concepts in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How To Control Component Size In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How To Control Component Size In React Native ?).

In this note series, we will learn how to control component size in React Native. A component’s height and width determine its size on the screen.

So Let’s begin.


Fixed Dimensions

The general way to set the dimensions of a component is by adding a fixed width and height to style. All dimensions in React Native are unitless and represent density-independent pixels.

Height and Width

import React from 'react';
import { View } from 'react-native';

const FixedDimensionsBasics = () => {
    return (
      <View>
        <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
        <View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
        <View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} />
      </View>
    );
};

export default FixedDimensionsBasics;

Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions.

The Preview of the above example is :


Flex Dimensions

We use flex in a component’s style to have the component expand and shrink dynamically based on available space. Normally we will use flex: 1, which tells a component to fill all available space, shared evenly amongst other components with the same parent. The larger the flex given, the higher the ratio of space a component will take compared to its siblings.

A component can only expand to fill available space if its parent has dimensions greater than 0. If a parent does not have either a fixed width and height or flex, the parent will have dimensions of 0 and the flex children will not be visible.

Flex Dimensions

import React from 'react';
import { View } from 'react-native';

const FlexDimensionsBasics = () => {
    return (
      // Try removing the `flex: 1` on the parent View.
      // The parent will not have dimensions, so the children can't expand.
      // What if you add `height: 300` instead of `flex: 1`?
      <View style={{flex: 1}}>
        <View style={{flex: 1, backgroundColor: 'powderblue'}} />
        <View style={{flex: 2, backgroundColor: 'skyblue'}} />
        <View style={{flex: 3, backgroundColor: 'steelblue'}} />
      </View>
    );
};

export default FlexDimensionsBasics;

The Preview of the above example is :


Conclusion

In this note series, we understood how to control component size in React Native. This note series showed Fixed Dimensions and Flex Dimensions to control the component size in react native.

Thanks for reading! I hope you enjoyed and learned about Fixed Dimensions and Flex Dimensions concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How To Prepare UI To Run In The Foreground In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How To Prepare UI To Run In The Foreground In iOS ?).

In this note series, we will learn about how to prepare UI to run in the foreground in iOS. This note series shows how to configure our app to appear on-screen.

So Let’s begin.


Overview

We use foreground transitions to prepare our app’s UI to appear on-screen. An app’s transition to the foreground is usually in response to a user’s action. For example, when the user taps the app’s icon, the system launches the app and brings it to the foreground. We use a foreground transition to update our app’s UI, gain resources, and start the services we need to handle user requests.

All state transitions result in UIKit sending notifications to the delegate object:

  • In iOS 13 and later—A UISceneDelegate object.
  • In iOS 12 and earlier—The UIApplicationDelegate object.

We can support both types of delegate objects, but UIKit always uses scene delegate objects when they are available. UIKit notifies only the scene delegate associated with the specific scene that is entering the foreground.


Update Our App’s Data Model when Entering the Foreground

At launch time, the system starts our app in the inactive state before transitioning it to the foreground. We use our app’s launch-time methods to perform any work needed. UIKit moves our background app to the inactive state by calling one of the following methods:

  • For apps that support scenes — The sceneWillEnterForeground(_:) method of the scene delegate object.
  • For all other apps — The applicationWillEnterForeground(_:) method.

When transitioning from the background to the foreground, we use these methods to load resources from disk and fetch data from the network.


Configure User Interface and Initial Tasks at Activation

The system moves our app to the active state immediately before displaying the app’s UI. Activation is a good time to configure our app’s UI and runtime behavior; specifically:

  • Show our app’s windows if needed.
  • Change the currently visible view controller, if needed.
  • Update the data values and state of views and controls.
  • Display controls to resume a paused game.
  • Start or resume any dispatch queues that you use to execute tasks.
  • Update data source objects.
  • Start timers for periodic tasks.

We can put our configuration code in one of the following methods:

  • For a scene-based UI—The sceneDidBecomeActive(_:) method of the scene delegate object.
  • For all other apps—The applicationDidBecomeActive(_:) method of our app delegate object.

Activation is also the time to put finishing touches on our UI before displaying it to the user. Don’t run any code that might block our activation method. Instead, make sure we have everything, we need in advance. For example, if our data changes frequently outside of the app, we use background tasks to fetch updates from the network before our app returns to the foreground. Otherwise, be prepared to display existing data while we fetch changes asynchronously.


Start UI-Specific Tasks when View Appears

When our activation method returns, UIKit shows any windows that we made visible. It also notifies any relevant view controllers that their views are about to appear. We use our view controller’s viewWillAppear(_:) method to perform any final updates to our interface. For example:

  • Start user interface animations, as appropriate.
  • Begin playing media files, if auto-play is enabled.
  • Begin displaying graphics for games and immersive content at their full frame rates.

Don’t show a different view controller or make major changes to our user interface. By the time our view controller appears on-screen, our interface should be ready to display.


Conclusion

In this note series, we understood how to prepare UI to run in the foreground in iOS. We also discussed how to configure our app to appear on-screen.

Thanks for reading! I hope you enjoyed and learned about UI Preparation concepts during foreground in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – Higher-order Components vs Render Props In React JS

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (Higher-order Components vs Render Props In React JS).

In this note series, we will about Higher-order components vs Render Props in React JS. Higher-order components (HOC) and render props are two ways to build cross cutting code in React JS. How do we decide to use one over the other?

The reason we have these two approaches is that React used ES6 class for building React components to manage the state. Before that, to share cross-cutting concerns for components React.createClass mixins was the way to handle that. However, class does not support mixins and a new way had to be developed.

So Let’s begin.

Higher-order Components

Soon HOC evolved into the picture to support code reuse. Essentially, these are like the decorator pattern, a function that takes a component as the first parameter and returns a new component. This is where we apply our cross-cutting functionality.

Example of higher-order component:

function withExample(Component) {
  return function(props) {
    // cross cutting logic added here
    return <Component {...props} />;
  };
}

What does HOC solve?

  • Importantly, they provided a way to reuse code when using ES6 classes.
  • No longer have method name clashing if two HOC implement the same one.
  • It is easy to make small reusable units of code, supporting the single responsibility principle.
  • Apply multiple HOCs to one component by composing them. The readability can be improve using a compose function like in Recompose.

We can see similarities in the downsides for both mixins and HOC:

  • There is still an indirection issue, however, not about which HOC is changing the state but which one is providing a certain prop.
  • It is possible two HOC could use the same prop, meaning one would overwrite the other silently.

Higher-order components come with new problems:

  • Boilerplate code like setting the displayName with the HOC function name e.g. (withHOC(Component)) to help with debugging.
  • Ensure all relevant props are passed through to the component.
  • Hoist static methods from the wrapped component.
  • It is easy to compose several HOCs together and then this creates a deeply nested tree, making it difficult to debug.

Render Props

A render prop is where a component’s prop is assigned a function, and this is called in the render method of the component. Calling the function can return a React element or component to render.

Example of using a render prop:

render(){
  <FetchData render={(data) => {
    return <p>{data}</p>
  }} />
}

What do render props solve?

  • Reuse code across components when using ES6 classes.
  • The lowest level of indirection – it’s clear which component is called and the state is isolated.
  • No naming collision issues for props, state and class methods.
  • No need to deal with boiler code and hoisting static methods.

Minor problems:

  • Caution using shouldComponentUpdate as the render prop might close over data it is unaware of.
  • There could also be minor memory issues when defining a closure for every render. But be sure to measure first before making performance changes, as it might not be an issue for our app.
  • Another small annoyance is the render props callback is not so neat in JSX as it needs to be wrapped in an expression. Rendering the result of an HOC looks cleaner.

HOC or Render props

From this, we can say render props solves the issues posed by HOC, and it should be our go-to pattern for creating cross-cutting logic. Render props are easier to set up, with less boiler code and no need to hoist static methods, as they are like standard components. They are also more predictable as fewer things can go wrong with updating state and passing props through.

However, we find HOC better to compose over render props, especially when many cross-cutting concerns are applied to a component. Many nested render prop components will look similar to “callback hell”. It’s straightforward to create small HOC units and compose them together to build a feature-rich component. Recompose is a great example and can be useful to apply to solving our next challenge.

Just remember to use the tool that best helps us solve our problem and don’t let the Hype Driven Development pressure us to do otherwise. Render props and HOC are equally great React patterns.

Conclusion

In this note series, we understood about High-order components vs Render Props in React JS. We also discussed How do we decide to use one over the other in ReactJS.

Thanks for reading! I hope you enjoyed and learned about High-order components vs Render Props concept in React JS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How To Debug HTTPS Problems With CFNetwork Diagnostic Logging In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How To Debug HTTPS Problems With CFNetwork Diagnostic Logging In iOS ?).

In this note series, we will understand how to use CFNetwork diagnostic logging to investigate HTTP and HTTPS problems in iOS.


So Let’s begin.


Overview

If we’re using URLSession and need to debug a complex networking issue, we can enable CFNetwork diagnostic logging to get detailed information about the progress of our network requests. CFNetwork diagnostic logging has unique advantages relative to other network debugging tools, including:

  • Minimal setup
  • The ability to look at network traffic that’s protected by Transport Layer Security (TLS).
  • Information about CFNetwork’s internal state, like which cookies get saved and applied.

CFNetwork diagnostic logging is not exclusive to the CFNetwork framework. The core implementation of the URLSession API lives within the CFNetwork framework, and thus we can and should use CFNetwork diagnostic logging if we’re using URLSession.


Understand the Security Implications

CFNetwork diagnostic logs may contain decrypted TLS data and other security-sensitive information. Take these precautions:

  • Restrict access to any logs we capture.
  • If we build an app that enables this logging programmatically, make sure that anyone who receives that app understands the security implications of using it.
  • If we send a log to Apple, redact any security-sensitive information.

CFNetwork diagnostic logs may contain information that is extremely security-sensitive. Protect these logs accordingly.


Enable Logging In Xcode

To enable CFNetwork diagnostic logging, edit the current scheme (choose Product > Scheme > Edit Scheme), navigate to the Arguments tab, and add a CFNETWORK_DIAGNOSTICS item to the Environment Variables list. The value of this item can range from 0 to 3, where 0 turns logging off, and higher numbers give us progressively more logging. When we next run our app and use URLSession, CFNetwork diagnostic log entries appear in Xcode’s debug console area. If the console area isn’t visible, choose View > Debug Area > Show Debug Area to show it.


Enable Logging Programmatically

To investigate problems outside of Xcode, programmatically enable CFNetwork diagnostic logging by setting the environment variable directly.

setenv("CFNETWORK_DIAGNOSTICS", "3", 1)

Do this right at the beginning of the app’s launch sequence:

  • If we’re programming in Objective-C, put the code at the start of our main function.
  • If our program has a C++ component, make sure this code runs before any C++ static initializers that use CFNetwork or any APIs, like URLSession, that use CFNetwork.
  • If we’re programming in Swift, put this code in main.swift. By default, Swift apps don’t have a main.swift. We need to add one.


View Log Entries

How we view the resulting log entries depends on our specific situation:

  • In macOS, if we can reproduce the problem locally, run the Console utility on our Mac and view log entries there.
  • In iOS, if we can reproduce the problem locally, and we’re able to connect the device to our Mac through USB, run the Console utility on our Mac and view log entries there. Make sure we select our iOS device from the source list on the left of the main Console window (choose View > Show Sources if the source list is not visible).
  • If neither of the above work for us — for example, if we’re trying to debug a problem that can only be reproduced by one of our users in the field — get a sys-diagnose log from the machine exhibiting the problem and then extract the log entries from that.


Conclusion

In this note series, we understood How to use CFNetwork diagnostic logging to investigate HTTP and HTTPS problems in iOS.

Thanks for reading! I hope you enjoyed and learned about CFNetwork diagnostic logging usage in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How To Debug HTTP Server-Side Errors In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How To Debug HTTP Server-Side Errors In iOS ?).

In this note series, we will understand HTTP server-side errors and how to debug them in iOS.


So Let’s begin.


Overview

Apple’s HTTP APIs report transport errors and server-side errors:

  • A transport error is caused by a problem getting our request to, or getting the response from, the server. These are represented by a NSError value, typically passed to our completion handler block or to a delegate method like urlSession(_:task:didCompleteWithError:). If we get a transport error, investigate what’s happening with our network traffic.
  • A server-side error is caused by problems detected by the server. Such errors are represented by the statusCode property of the HTTPURLResponse.

The status codes returned by the server aren’t always easy to interpret. Many HTTP server-side errors don’t give us a way to determine, from the client side, what went wrong. These include the 5xx errors (like 500 Internal Server Error) and many 4xx errors (for example, with 400 Bad Request, it’s hard to know exactly why the server considers the request bad).


Print the HTTP Response Body

In this section, we explain how to debug these server-side problems.

Sometimes, the error response from the server includes an HTTP response body that explains what the problem is. Look at the HTTP response body to see whether such an explanation is present. If it is, that’s the easiest way to figure out what went wrong. For example, consider this standard URLSession request code.

URLSession.shared.dataTask(with: url) { (responseBody, response, error) in
    if let error = error {
        // handle transport error
    }
    let response = response as! HTTPURLResponse
    let responseBody = responseBody!
    if !(200...299).contains(response.statusCode) {
        // handle HTTP server-side error
    }
    // handle success
    print("success")
}.resume()

A server-side error runs the line labeled handle HTTP server-side error. To see if the server’s response contains any helpful hints what went wrong, add some code that prints the HTTP response body.

        // handle HTTP server-side error
        if let responseString = String(bytes: responseBody, encoding: .utf8) {
            // The response body seems to be a valid UTF-8 string, so      print that.
            print(responseString)
        } else {
            // Otherwise print a hex dump of the body.
            print(responseBody as NSData)
        }


Compare Against a Working Client

If the HTTP response body doesn’t help, compare our request to a request issued by a working client. For example, the server might not fail if we send it the same request from:

  • A web browser, like Safari
  • A command-line tool, like curl
  • An app running on a different platform

If we have a working client, it’s relatively straightforward to debug our problem:

  1. Use the same network debugging tool to record the requests made by our client and the working client. If we’re using HTTP (not HTTPS), use a low-level packet trace tool to record these requests. If we’re using HTTPS, with Transport Layer Security (TLS), we can’t see the HTTP request. In that case, if our server has a debugging mode that lets us see the plaintext request, look there. If not, a debugging HTTP proxy may let us see the request.
  2. Compare the two requests. Focus on the most significant values first.
    • Do the URL paths or the HTTP methods match?
    • Do the Content-Type headers match?
    • What about the remaining headers?
    • Do the request bodies match?
    • If these all match and things still don’t work, we may need to look at more obscure values, like the HTTP transfer encoding and, if we’re using HTTPS, various TLS parameters.
  3. Address any discrepancies.
  4. Retry with our updated client.
  5. If things still fail, go back to step 1.


Debug on the Server

If we don’t have access to a working client, or we can’t get things to work using the steps described in the previous section, our only remaining option is to debug the problem on the server. Ideally, the server will have documented debugging options that offer more insight into the failure. If not, escalate the problem through the support channel associated with our server software.


Conclusion

In this note series, we understood HTTP server-side errors and how to debug them in iOS.

Thanks for reading! I hope you enjoyed and learned about HTTP Server-side Concept in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – Choosing Network Debugging Tool In iOS

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (Choosing Network Debugging Tool In iOS).

In this note series, we will understand which tool works best for our network debugging problem in iOS.

So Let’s begin.

Overview

Debugging network problems is challenging because of the fundamental nature of networking. Networking is asynchronous, time-sensitive, and error prone. The two programs involved (the client and the server, say) are often created by different developers, who disagree on the exact format of the data being exchanged. Fortunately, a variety of tools can help us debug such problems.

A key goal of these tools is to divide the problem in two. For example, if we’re working on a network client that sends a request to a server and then gets an error back from that server, it’s important to know whether things failed because the request was incorrect (a problem with our client) or because the server is misbehaving. We can use these network debugging tools to view the traffic going over the network, and thus independently check the validity of that traffic.

Choosing Best Network Debugging Tool

The best tool to use depends on the APIs we’re using and the problems we’ve encountered:

  • We may find that our request makes it to the server and then the server sends us a response showing that it failed If we are working at the HTTP level (for example, we get an HTTP response with a status code of 500 Internal Server Error). 
  • If we’re using URLSession, or one subsystem that uses URLSession internally, we can enable CFNetwork diagnostic logging to get a detailed view of how our requests were processed.
  • We need a packet trace if we want a low-level view of the traffic exchanged over the network,.
  • If we’re working in Safari or one of the various web views (like WKWebView), we can use the Web Inspector to view the network requests issued by the page. 
  • Some of the most popular network debugging tools, like HTTP debugging proxies, are third-party products.

Conclusion

In this note series, we understood which tool works best for your network debugging problem in iOS.

Thanks for reading! I hope you enjoyed and learned about Choosing Best Network Tool Concept in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How Does The MVI Work In Android ?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How does the MVI work in Android?).

In this note series, We will understand what MVI architectural pattern is, how it resolves these challenges in android.

Android architectural patterns are growing day by day. As we develop apps, we face new challenges and issues. New patterns will be discovered as we keep solving similar challenges. As Android Developers, we have MVC, MVP, and MVVM as the most commonly used patterns. All of them use an imperative programming approach. With this approach, even though most of our challenges will be resolved, we still face some challenges regarding the thread safety, maintaining states of the application.

So Let’s begin.


What is MVI architecture?

MVI stands for Model-View-Intent. This pattern has been introduced recently in Android. It works based on the principle of unidirectional and cylindrical flow inspired by the Cycle.js framework.

Let’s see what is the role of each component of MVI.

  • Model: Unlike other patterns, In MVI Model represents the state of the UI. i.e. for example UI might have different states like Data Loading, Loaded, Change in UI with user Actions, Errors, User current screen position states. Each state is stored as similar to the object in the model.
  • View: The View in the MVI is our Interfaces, which can be implemented in Activities and fragments. It means to have a container which can accept the different model states and display it as a UI. They use observable intents(Note: This doesn’t represent the Android traditional Intents) to respond to user actions.
  • Intent: Even though this is not an Intent as termed by Android from before. The result of the user actions is passed as an input value to Intents. We can say we will send models as inputs to the Intents, which can load it through Views.


How does the MVI work?

User does an action which will be an Intent → Intent is a state which is an input to model → Model stores state and send the requested state to the View → View Loads the state from Model → Displays to the user.

If we observe, the data will always flow from the user and end with the user through intent. It cannot be the other way, hence its called Unidirectional architecture. If the user does one more action, the same cycle is repeated, hence it is Cyclic.


Advantages and Disadvantages of MVI

Let’s see what are the advantages and disadvantages of MVI.


Advantages of MVI

  • Maintaining state is no more a challenge with this architecture, As it focuses mainly on states.
  • As it is unidirectional, Data flow can be tracked and predicted easily.
  • It ensures thread safety as the state objects are immutable.
  • Easy to debug, As we know the state of the object when the error occurred.
  • It’s more decoupled as each component fulfills its own responsibility.
  • Testing the app also will be easier than we can map the business logic for each state.


Disadvantages of MVI

  • It leads to lots of boilerplate code as we have to maintain a state for each user action.
  • As we know it has to create lots of objects for all the states. This makes it too costly for app memory management.
  • Handling alert states might challenge while we handle configuration changes. For example, if there is no internet we will show the snackbar, On configuration change, it shows the snackbar again as it is the state of the intent. In terms of usability, this has to be handled.


Conclusion

In this note series, we understood about what MVI architectural pattern is, how it resolves these challenges in android.

Thanks for reading! I hope you enjoyed and learned about MVI Concept in Android. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of Android as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – R8 vs Proguard In Android

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (R8 vs Proguard In Android).

In this note series, we will understand about R8 vs Proguard in Android. Google released R8 as a replacement of Proguard to help developers shrink the code with the better-generated output (APK). They are considered much faster compared to Proguard.

So Let’s begin.

What is R8?

R8 is a tool that converts our java byte code into an optimized dex code. It iterates through the whole application and then it optimizes like removing unused classes, methods, etc. and runs on the compile time. It helps us to reduce the size of the build and to make our app to be more secure. R8 uses Proguard rules to modify its default behavior.

How does R8 shrinking work?

While optimizing the code, R8 reduces the code of our application, and then APK size is reduced.

To reduce the APK size, we have three different techniques:

  1. Shrinking or Tree Shaking: Shrinking is the process of removal of unreachable code from our Android project. R8 performs some static analysis to get rid of unreachable code and removes the un-instantiated object.
  2. Optimization: This is used to optimize the code for size. It involves dead code removal, unused argument removal, selective in-lining, class merging, etc.
  3. Identifier Renaming: In this process, we obfuscate the class name and other variable names. For example, if the name of the class is “MainActivity“, then it will be obfuscated to “a” or something else but smaller in size.

How to enable R8 Shrinking in our app?

R8 is present by default in our application but to enable R8 shrinking in our application, set the minifyEnabled to true in our app’s main build.gradle file.

android {
    ...
    buildTypes {
        release {
            minifyEnabled true
        }
    }
}

R8 vs Proguard

So, let’s now compare both R8 and Proguard both and see how it fares,

  • With the Android app using Gradle plugin above 3.4.0 or more the project uses R8 by default and no longer uses the Proguard to perform optimizations. But, it uses Proguard rules only.
  • R8 inlines the container classes and removes unused class, fields, and methods. Proguard reduces the app size by 8.5% and compared to R8 which reduces the code by 10%.
  • R8 has more Kotlin support compared to Proguard.
  • R8 gives better outputs than Proguard, and to do so faster than Proguard does, reducing overall build time.

So, let’s now compare how both Proguard and R8 performs.

Proguard

While using Proguard, it converts the Applications code to Java byte-code by the Java compiler. After the conversion, it is then optimized by Proguard using the rules which we have written. Then dex converts it to optimized Dalvik byte code.

This is roughly a 4 step process to convert it to Dalvik byte-code.

R8

While using R8, first the app’s code is converted to Java byte-code by the java compiler and then using R8 directly, it converts the java byte-code in Dalvik byte-code.

By using R8, it directly reduces the steps of conversion of Java byte-code to Dalvik Byte-code from 2 to 1.

  • Proguard applies 520 peephole optimizations compared to R8, which is very less. Peephole optimizations are the optimizations that are performed on a set of compiler-generated code to improve the performance of the code by making it shorter and faster.
  • In both Proguard and R8, we have to handle the reflection by writing the custom configuration.
  • R8 is faster compared to Proguard in the execution of converting the code.

Optimization Comparison between Proguard and R8

Let us discuss a few features supported by both Proguard and R8.

For example, Proguard and R8 both make the methods private in the code. Both of them also remove unused class, fields, or even methods in the project are not in use. Both of them support the simplification of Enum types. They both inline methods, merge codes, etc.

Proguard also makes the classes final whereas R8 cannot do it. But comparing R8, which is highly supported by Kotlin, optimizes the Kotlin construct which is not possible with Proguard.

Now, If you also want to enable aggressive optimization in R8 and reduce the size more, enable the following in gradle.properties.

android.enableR8.fullMode=true

Conclusion

In this note series, we understood about R8 vs Proguard in Android. We have also discussed R8 and Proguard process and optimization differences. With R8 coming as a default compile-time optimizer, it reduces the size of the app.

Thanks for reading! I hope you enjoyed and learned about R8 vs Proguard in Android. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of Android as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Exit mobile version