SlideShare a Scribd company logo
1 of 49
Download to read offline
Android Jetpack
Hassan Abid - Google Developer Expert Android
Presented at Google IO Extended Singapore 2018
Google I/O Talks
● Android Jetpack: what's new in Android Support Library
● Android Jetpack: what's new in Architecture Components
● Modern Android development: Android Jetpack, Kotlin, and more
● Android Jetpack: how to smartly use Fragments in your UI
● Android Jetpack: manage UI navigation with Navigation Controller
● Android Jetpack: manage infinite lists with RecyclerView and Paging
● Android Jetpack: easy background processing with WorkManager
● Android Slices: build interactive results for Google Search
● Android Jetpack: sweetening Kotlin development with Android KTX
● Protips: a fresh look at advanced topics for Android experts
AndroidX
AndroidX: "Android Extension Libraries"
android.support.v4.view.ViewCompat
→ androidx.core.view.ViewCompat
android.support.v7.app.AppCompatActivity
→ androidx.appcompat.app.AppCompatActivity
android.arch.persistence.room.RoomDatabase
→ androidx.room.RoomDatabase
AndroidX
● Strict Semantic versioning rule
○ Reset to 1.0.0
Refactor to AndroidX
Migration from 28.0.0-alpha1
Recommended Architecture
Architecture Components
● LifeCycle (1.1.1 Stable)
● Databinding (Stable)
● ViewModel (Stable)
● LiveData (Stable)
● Room (1.1.1 Stable)
● Paging (1.0.1 Stable)
● WorkManager (Alpha Release)
● Navigation (Alpha Release)
https://developer.android.com/jetpack/docs/release-notes
Adding Components to your project
allprojects {
repositories {
jcenter()
google()
}
}
Example : LifeCycle
dependencies {
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// alternatively - just ViewModel. use -ktx for Kotlin
implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
}
Example : LifeCycle (Android X)
dependencies {
def lifecycle_version = "2.0.0-alpha1"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
// alternatively - just ViewModel use -ktx for Kotlin
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" }
LifeCycle
LifeCycle
LifeCycle Benefits
● Avoid Lifecycle related UI state loss: View Model
● Observability for your UI: LiveData
● Avoid Lifecycle related memory leak
● LiveData transformations
● UI-Database observations : LiveData /Room
● XML-ViewModel observations: DataBinding
● Query and Observe UI Lifecycle State
Fragment View Lifecycle
viewModel.plantAndGardenPlantings.observe(viewLifecycleOwner, Observer { result ->
if (result != null && result.isNotEmpty())
adapter.submitList(result)
})
Databinding
Databinding
A support library that allows you to bind UI components in your
layouts to data sources in your app using a declarative format rather
than programmatically.
TextView textView = findViewById(R.id.sample_text);
textView.setText(viewModel.getUserName());
<TextView
android:text="@{viewmodel.userName}" />
Databinding LiveData
class PlantDetailViewModel() : ViewModel() {
val plant: LiveData<Plant> = ...
}
<data>
<variable
name="viewModel"
type="viewmodels.PlantAndGardenPlantingsViewModel"/>
</data>
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop"
app:imageFromUrl="@{viewModel.imageUrl}"
/>
Databinding : One More thing
android {
dataBinding {
enabled = true
}
}
val binding = DataBindingUtil.inflate<FragmentPlantDetailBinding>(
inflater, R.layout.fragment_plant_detail, container,
false).apply {
viewModel = plantDetailViewModel
setLifecycleOwner(this@PlantDetailFragment)
}
ViewModel
ViewModel
● Provide data for UI Components
● Survive Configuration changes
ViewModel
Hold UI Data
Repository
API for loading and saving
data
Activity
Drawing UI
User Interactions
Presenter
Process Data for UI
ViewModel
class PlantDetailViewModel() : ViewModel() {
val plant: LiveData<Plant>
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val plantDetailViewModel = ViewModelProviders.of(this, factory)
.get(PlantDetailViewModel::class.java)
}
Don’t store activity context in
ViewModel
LiveData
LiveData
LiveData is an observable data holder. It is lifecycle aware
public class ProductViewModel extends AndroidViewModel {
private final LiveData<ProductEntity> mObservableProduct;
// ....
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
}
// Observe product data and
model.getObservableProduct().observe(this, new Observer<ProductEntity>() {
@Override
public void onChanged(@Nullable ProductEntity productEntity) {
// update UI
}
});
ViewModel + LiveData +
DataBinding = Reactive UI
Room
Room
● Object Mapping for SQLite Database
● Raw Queries are supported
● Support for RxJava
● Work with java.util.Optional
Room - Entity
@Entity(tableName = "plants")
data class Plant(
@PrimaryKey @ColumnInfo(name = "id") val plantId: String,
val name: String,
val description: String,
val growZoneNumber: Int,
val wateringInterval: Int = 7,
val imageUrl: String = ""
)
Room - Dao
@Dao
interface PlantDao {
@Query("SELECT * FROM plants ORDER BY name")
fun getPlants(): LiveData<List<Plant>>
@Query("SELECT * FROM plants WHERE growZoneNumber = :growZoneNumber ORDER BY
name")
fun getPlantsWithGrowZoneNumber(growZoneNumber: Int): LiveData<List<Plant>>
@Query("SELECT * FROM plants WHERE id = :plantId")
fun getPlant(plantId: String): LiveData<Plant>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(plants: List<Plant>)
}
Observable queries
Room - RoomDatabase
@Database(entities = [GardenPlanting::class, Plant::class], version = 1,
exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun gardenPlantingDao(): GardenPlantingDao
abstract fun plantDao(): PlantDao
...
}
Modern Android App
Architecture
Paging Library
Paging
● Fetch from database, Network, or both into RecycleView
● Extension of observable List Pattern (e.g LiveData<List>)
● Configurable Load Size, prefetch, placeholders
● Integrates with Room, LiveData, RX
● Stable release
Paging - core components 1/2
● PagedList
○ Load data in pages
○ Async data loading
● DataSource and DataSource.Factory
○ Base class for loading snapshots of data into PagedList
○ Backed by Network or Database
Paging - core components 2/2
● LivePagedListBuilder
○ Build a LiveData<PagedList> based on DataSource.Factory and a
PagedList.config
● BoundaryCallBack
○ Signals when PagedList has reached end of available data
● PagedListAdapter
○ A RecyclerView.Adapter that presents data from PagedLists
Paging - simplified
UI
PageListAdapter
PagedList
--------------
--------------
--------------
Data Layer
DataSource.Factory
BoundyCallBack
Data Source
OnItemAtEndLoaded()
Save data
Get Data
ViewModel
LiveData<PagedList>
Repository
LivePagedListBuilder
LiveData<PagedList>
create()
Build
--------------
Load
more
DataSource
● PageKeyedDataSource
● ItemKeyedDataSource
● PositionalDataSource
BoundaryCallBack
class ConcertBoundaryCallback(
private val query: String,
private val service: MyService,
private val cache: MyLocalCache
) : PagedList.BoundaryCallback<Concert>() {
override fun onZeroItemsLoaded() {
requestAndSaveData(query)
}
override fun onItemAtEndLoaded(itemAtEnd: Concert) {
requestAndSaveData(query)
}
}
Navigation
Navigation - Challenges
● Passing Arguments
● Deep Links
● Fragment Transactions
● Testing
Navigation - Only available in Android Studio
3.2
Navigation
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
app:startDestination="@+id/garden_fragment">
<fragment
android:id="@+id/plant_list_fragment"
android:name="com.google.samples.apps.sunflower.PlantListFragment">
<argument
.../>
<action
android:id="@+id/action_plant_list_fragment_to_plant_detail_fragment"
app:destination="@id/plant_detail_fragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
....
</navigation>
Navigation - Add Navgraph
<fragment
android:id="@+id/garden_nav_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_garden"/>
Navigation - NavigationController
val navController = Navigation.findNavController(this,
R.id.garden_nav_fragment)
// Set up ActionBar
setSupportActionBar(binding.toolbar)
NavigationUI.setupActionBarWithNavController(this,
navController, drawerLayout)
// Set up navigation menu
binding.navigationView.setupWithNavController(navController)
Navigation - NavigationOnClickListener
private fun createOnClickListener(plantId: String): View.OnClickListener {
val bundle = bundleOf(PlantDetailFragment.ARG_ITEM_ID to plantId)
return Navigation.createNavigateOnClickListener(
R.id.action_plant_list_fragment_to_plant_detail_fragment, bundle)
}
<action
android:id="@+id/action_plant_list_fragment_to_plant_detail_fragment"
app:destination="@id/plant_detail_fragment"/>
Samples and Code Lab
Android SunFlower https://github.com/googlesamples/android-sunflower
Universal Music Player
https://github.com/googlesamples/android-UniversalMusicPlayer/blob/master/app/build.gradle
Architecture Components https://github.com/googlesamples/android-architecture-components
Code Labs https://codelabs.developers.google.com/?cat=Android
Guide to Architecture Components https://developer.android.com/jetpack/docs/guide
Conclusion
● Finally Android platform got an Architecture
● Highly Recommended for New Apps
● Try out samples and codelabs
Thank You!
Twitter : @hassanabidpk
Github : hassanabidpk

More Related Content

What's hot

What's new in android jakarta gdg (2015-08-26)
What's new in android   jakarta gdg (2015-08-26)What's new in android   jakarta gdg (2015-08-26)
What's new in android jakarta gdg (2015-08-26)Google
 
Android Studio簡介
Android Studio簡介Android Studio簡介
Android Studio簡介Walter Shi
 
Firebase analytics event_201607
Firebase analytics event_201607Firebase analytics event_201607
Firebase analytics event_201607PRADA Hsiung
 
Entwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und GradleEntwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und Gradleinovex GmbH
 
Intro to Flutter
Intro to FlutterIntro to Flutter
Intro to FlutterEason Pai
 
Introducing the (new) Google Docs API (2019)
Introducing the (new) Google Docs API (2019)Introducing the (new) Google Docs API (2019)
Introducing the (new) Google Docs API (2019)wesley chun
 
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Get Hip with JHipster - Colorado Springs Open Source User Group 2021Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Get Hip with JHipster - Colorado Springs Open Source User Group 2021Matt Raible
 
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...e-Legion
 
Gradle and Android Studio : Best of Friends
Gradle and Android Studio : Best of FriendsGradle and Android Studio : Best of Friends
Gradle and Android Studio : Best of FriendsRomin Irani
 
Node in Production at Aviary
Node in Production at AviaryNode in Production at Aviary
Node in Production at AviaryAviary
 
Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Natalia Efimtseva
 
Intro to Gradle + How to get up to speed
Intro to Gradle + How to get up to speedIntro to Gradle + How to get up to speed
Intro to Gradle + How to get up to speedReid Baker
 
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...Raj Lal
 
Present and Future of GWT from a developer perspective
Present and Future of GWT from a developer perspectivePresent and Future of GWT from a developer perspective
Present and Future of GWT from a developer perspectiveManuel Carrasco Moñino
 
ProjectsSummary
ProjectsSummaryProjectsSummary
ProjectsSummaryYa Wang
 
Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Matt Raible
 
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019Matt Raible
 

What's hot (20)

What's new in android jakarta gdg (2015-08-26)
What's new in android   jakarta gdg (2015-08-26)What's new in android   jakarta gdg (2015-08-26)
What's new in android jakarta gdg (2015-08-26)
 
Google cloud endpoints
Google cloud endpointsGoogle cloud endpoints
Google cloud endpoints
 
Google Cloud Enpoints
Google Cloud EnpointsGoogle Cloud Enpoints
Google Cloud Enpoints
 
Android Studio簡介
Android Studio簡介Android Studio簡介
Android Studio簡介
 
Firebase analytics event_201607
Firebase analytics event_201607Firebase analytics event_201607
Firebase analytics event_201607
 
Micro Frontends
Micro FrontendsMicro Frontends
Micro Frontends
 
Entwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und GradleEntwicklung mit Android Studio und Gradle
Entwicklung mit Android Studio und Gradle
 
Intro to Flutter
Intro to FlutterIntro to Flutter
Intro to Flutter
 
Introducing the (new) Google Docs API (2019)
Introducing the (new) Google Docs API (2019)Introducing the (new) Google Docs API (2019)
Introducing the (new) Google Docs API (2019)
 
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Get Hip with JHipster - Colorado Springs Open Source User Group 2021Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
 
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
#MBLTdev: Разработка backend для мобильного приложения с использованием Googl...
 
Gradle and Android Studio : Best of Friends
Gradle and Android Studio : Best of FriendsGradle and Android Studio : Best of Friends
Gradle and Android Studio : Best of Friends
 
Node in Production at Aviary
Node in Production at AviaryNode in Production at Aviary
Node in Production at Aviary
 
Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)Mobile backends with Google Cloud Platform (MBLTDev'14)
Mobile backends with Google Cloud Platform (MBLTDev'14)
 
Intro to Gradle + How to get up to speed
Intro to Gradle + How to get up to speedIntro to Gradle + How to get up to speed
Intro to Gradle + How to get up to speed
 
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...
Build Cutting edge Mobile Apps using QML and JavaScript for MeeGo N9: Linux F...
 
Present and Future of GWT from a developer perspective
Present and Future of GWT from a developer perspectivePresent and Future of GWT from a developer perspective
Present and Future of GWT from a developer perspective
 
ProjectsSummary
ProjectsSummaryProjectsSummary
ProjectsSummary
 
Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019
 
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019
Microservices for the Masses with Spring Boot, JHipster and OAuth - GIDS 2019
 

Similar to Android Jetpack - Google IO Extended Singapore 2018

Android architecture components with cloud firestore
Android architecture components with cloud firestoreAndroid architecture components with cloud firestore
Android architecture components with cloud firestorePankaj Rai
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsHassan Abid
 
Android Applications Development: A Quick Start Guide
Android Applications Development: A Quick Start GuideAndroid Applications Development: A Quick Start Guide
Android Applications Development: A Quick Start GuideSergii Zhuk
 
AndroidX Google Extended I/O BKK 2018
AndroidX Google Extended I/O BKK 2018 AndroidX Google Extended I/O BKK 2018
AndroidX Google Extended I/O BKK 2018 Theerasan Tonthongkam
 
بررسی چارچوب جنگو
بررسی چارچوب جنگوبررسی چارچوب جنگو
بررسی چارچوب جنگوrailsbootcamp
 
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROID
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROIDMaterial Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROID
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROIDJordan Open Source Association
 
Organizing the Data Chaos of Scientists
Organizing the Data Chaos of ScientistsOrganizing the Data Chaos of Scientists
Organizing the Data Chaos of ScientistsAndreas Schreiber
 
Android App Development - 01 Introduction
Android App Development - 01 IntroductionAndroid App Development - 01 Introduction
Android App Development - 01 IntroductionDiego Grancini
 
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum
 
DataFinder: A Python Application for Scientific Data Management
DataFinder: A Python Application for Scientific Data ManagementDataFinder: A Python Application for Scientific Data Management
DataFinder: A Python Application for Scientific Data ManagementAndreas Schreiber
 
Web App Prototypes with Google App Engine
Web App Prototypes with Google App EngineWeb App Prototypes with Google App Engine
Web App Prototypes with Google App EngineVlad Filippov
 
Using Automatic Refactoring to Improve Energy Efficiency of Android Apps
Using Automatic Refactoring to Improve Energy Efficiency of Android AppsUsing Automatic Refactoring to Improve Energy Efficiency of Android Apps
Using Automatic Refactoring to Improve Energy Efficiency of Android AppsLuis Cruz
 
How to use data binding in android
How to use data binding in androidHow to use data binding in android
How to use data binding in androidInnovationM
 
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023Nicolas HAAN
 
ADO .NET by Sonu Vishwakarma
ADO .NET by Sonu VishwakarmaADO .NET by Sonu Vishwakarma
ADO .NET by Sonu VishwakarmaSonu Vishwakarma
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React NativeEric Deng
 
Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Kavya Barnadhya Hazarika
 

Similar to Android Jetpack - Google IO Extended Singapore 2018 (20)

Android architecture components with cloud firestore
Android architecture components with cloud firestoreAndroid architecture components with cloud firestore
Android architecture components with cloud firestore
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Stmik bandung
Stmik bandungStmik bandung
Stmik bandung
 
Android Applications Development: A Quick Start Guide
Android Applications Development: A Quick Start GuideAndroid Applications Development: A Quick Start Guide
Android Applications Development: A Quick Start Guide
 
AndroidX Google Extended I/O BKK 2018
AndroidX Google Extended I/O BKK 2018 AndroidX Google Extended I/O BKK 2018
AndroidX Google Extended I/O BKK 2018
 
Droidcon Paris 2015
Droidcon Paris 2015Droidcon Paris 2015
Droidcon Paris 2015
 
بررسی چارچوب جنگو
بررسی چارچوب جنگوبررسی چارچوب جنگو
بررسی چارچوب جنگو
 
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROID
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROIDMaterial Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROID
Material Design (The Technical Essentials) by Mohammad Aljobairi @AMMxDROID
 
Android Materials Design
Android Materials Design Android Materials Design
Android Materials Design
 
Organizing the Data Chaos of Scientists
Organizing the Data Chaos of ScientistsOrganizing the Data Chaos of Scientists
Organizing the Data Chaos of Scientists
 
Android App Development - 01 Introduction
Android App Development - 01 IntroductionAndroid App Development - 01 Introduction
Android App Development - 01 Introduction
 
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
 
DataFinder: A Python Application for Scientific Data Management
DataFinder: A Python Application for Scientific Data ManagementDataFinder: A Python Application for Scientific Data Management
DataFinder: A Python Application for Scientific Data Management
 
Web App Prototypes with Google App Engine
Web App Prototypes with Google App EngineWeb App Prototypes with Google App Engine
Web App Prototypes with Google App Engine
 
Using Automatic Refactoring to Improve Energy Efficiency of Android Apps
Using Automatic Refactoring to Improve Energy Efficiency of Android AppsUsing Automatic Refactoring to Improve Energy Efficiency of Android Apps
Using Automatic Refactoring to Improve Energy Efficiency of Android Apps
 
How to use data binding in android
How to use data binding in androidHow to use data binding in android
How to use data binding in android
 
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
 
ADO .NET by Sonu Vishwakarma
ADO .NET by Sonu VishwakarmaADO .NET by Sonu Vishwakarma
ADO .NET by Sonu Vishwakarma
 
20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native20180518 QNAP Seminar - Introduction to React Native
20180518 QNAP Seminar - Introduction to React Native
 
Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)
 

More from Hassan Abid

Improving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesImproving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesHassan Abid
 
Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)Hassan Abid
 
Exploring CameraX from JetPack
Exploring CameraX from JetPackExploring CameraX from JetPack
Exploring CameraX from JetPackHassan Abid
 
What’s new in Android JetPack
What’s new in Android JetPackWhat’s new in Android JetPack
What’s new in Android JetPackHassan Abid
 
Kotlin for Android Developers
Kotlin for Android DevelopersKotlin for Android Developers
Kotlin for Android DevelopersHassan Abid
 
Recap of Android Dev Summit 2018
Recap of Android Dev Summit 2018Recap of Android Dev Summit 2018
Recap of Android Dev Summit 2018Hassan Abid
 
What's new in Android Pie
What's new in Android PieWhat's new in Android Pie
What's new in Android PieHassan Abid
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applicationsHassan Abid
 
VR Video Apps on Daydream
VR Video Apps on DaydreamVR Video Apps on Daydream
VR Video Apps on DaydreamHassan Abid
 
Best Practices in Media Playback
Best Practices in Media PlaybackBest Practices in Media Playback
Best Practices in Media PlaybackHassan Abid
 
ExoPlayer for Application developers
ExoPlayer for Application developersExoPlayer for Application developers
ExoPlayer for Application developersHassan Abid
 
Android n preview
Android n previewAndroid n preview
Android n previewHassan Abid
 
Introduction to Pakistan
Introduction to PakistanIntroduction to Pakistan
Introduction to PakistanHassan Abid
 

More from Hassan Abid (13)

Improving app performance with Kotlin Coroutines
Improving app performance with Kotlin CoroutinesImproving app performance with Kotlin Coroutines
Improving app performance with Kotlin Coroutines
 
Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)
 
Exploring CameraX from JetPack
Exploring CameraX from JetPackExploring CameraX from JetPack
Exploring CameraX from JetPack
 
What’s new in Android JetPack
What’s new in Android JetPackWhat’s new in Android JetPack
What’s new in Android JetPack
 
Kotlin for Android Developers
Kotlin for Android DevelopersKotlin for Android Developers
Kotlin for Android Developers
 
Recap of Android Dev Summit 2018
Recap of Android Dev Summit 2018Recap of Android Dev Summit 2018
Recap of Android Dev Summit 2018
 
What's new in Android Pie
What's new in Android PieWhat's new in Android Pie
What's new in Android Pie
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applications
 
VR Video Apps on Daydream
VR Video Apps on DaydreamVR Video Apps on Daydream
VR Video Apps on Daydream
 
Best Practices in Media Playback
Best Practices in Media PlaybackBest Practices in Media Playback
Best Practices in Media Playback
 
ExoPlayer for Application developers
ExoPlayer for Application developersExoPlayer for Application developers
ExoPlayer for Application developers
 
Android n preview
Android n previewAndroid n preview
Android n preview
 
Introduction to Pakistan
Introduction to PakistanIntroduction to Pakistan
Introduction to Pakistan
 

Recently uploaded

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 

Recently uploaded (20)

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 

Android Jetpack - Google IO Extended Singapore 2018

  • 1. Android Jetpack Hassan Abid - Google Developer Expert Android Presented at Google IO Extended Singapore 2018
  • 2.
  • 3. Google I/O Talks ● Android Jetpack: what's new in Android Support Library ● Android Jetpack: what's new in Architecture Components ● Modern Android development: Android Jetpack, Kotlin, and more ● Android Jetpack: how to smartly use Fragments in your UI ● Android Jetpack: manage UI navigation with Navigation Controller ● Android Jetpack: manage infinite lists with RecyclerView and Paging ● Android Jetpack: easy background processing with WorkManager ● Android Slices: build interactive results for Google Search ● Android Jetpack: sweetening Kotlin development with Android KTX ● Protips: a fresh look at advanced topics for Android experts
  • 4. AndroidX AndroidX: "Android Extension Libraries" android.support.v4.view.ViewCompat → androidx.core.view.ViewCompat android.support.v7.app.AppCompatActivity → androidx.appcompat.app.AppCompatActivity android.arch.persistence.room.RoomDatabase → androidx.room.RoomDatabase
  • 5. AndroidX ● Strict Semantic versioning rule ○ Reset to 1.0.0
  • 6. Refactor to AndroidX Migration from 28.0.0-alpha1
  • 8. Architecture Components ● LifeCycle (1.1.1 Stable) ● Databinding (Stable) ● ViewModel (Stable) ● LiveData (Stable) ● Room (1.1.1 Stable) ● Paging (1.0.1 Stable) ● WorkManager (Alpha Release) ● Navigation (Alpha Release) https://developer.android.com/jetpack/docs/release-notes
  • 9. Adding Components to your project allprojects { repositories { jcenter() google() } }
  • 10. Example : LifeCycle dependencies { def lifecycle_version = "1.1.1" // ViewModel and LiveData implementation "android.arch.lifecycle:extensions:$lifecycle_version" // alternatively - just ViewModel. use -ktx for Kotlin implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" }
  • 11. Example : LifeCycle (Android X) dependencies { def lifecycle_version = "2.0.0-alpha1" // ViewModel and LiveData implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" // alternatively - just ViewModel use -ktx for Kotlin implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" }
  • 14. LifeCycle Benefits ● Avoid Lifecycle related UI state loss: View Model ● Observability for your UI: LiveData ● Avoid Lifecycle related memory leak ● LiveData transformations ● UI-Database observations : LiveData /Room ● XML-ViewModel observations: DataBinding ● Query and Observe UI Lifecycle State
  • 15. Fragment View Lifecycle viewModel.plantAndGardenPlantings.observe(viewLifecycleOwner, Observer { result -> if (result != null && result.isNotEmpty()) adapter.submitList(result) })
  • 17. Databinding A support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically. TextView textView = findViewById(R.id.sample_text); textView.setText(viewModel.getUserName()); <TextView android:text="@{viewmodel.userName}" />
  • 18. Databinding LiveData class PlantDetailViewModel() : ViewModel() { val plant: LiveData<Plant> = ... } <data> <variable name="viewModel" type="viewmodels.PlantAndGardenPlantingsViewModel"/> </data> <ImageView android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop" app:imageFromUrl="@{viewModel.imageUrl}" />
  • 19. Databinding : One More thing android { dataBinding { enabled = true } } val binding = DataBindingUtil.inflate<FragmentPlantDetailBinding>( inflater, R.layout.fragment_plant_detail, container, false).apply { viewModel = plantDetailViewModel setLifecycleOwner(this@PlantDetailFragment) }
  • 21. ViewModel ● Provide data for UI Components ● Survive Configuration changes ViewModel Hold UI Data Repository API for loading and saving data Activity Drawing UI User Interactions Presenter Process Data for UI
  • 22. ViewModel class PlantDetailViewModel() : ViewModel() { val plant: LiveData<Plant> } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val plantDetailViewModel = ViewModelProviders.of(this, factory) .get(PlantDetailViewModel::class.java) } Don’t store activity context in ViewModel
  • 24. LiveData LiveData is an observable data holder. It is lifecycle aware public class ProductViewModel extends AndroidViewModel { private final LiveData<ProductEntity> mObservableProduct; // .... public LiveData<ProductEntity> getObservableProduct() { return mObservableProduct; } } // Observe product data and model.getObservableProduct().observe(this, new Observer<ProductEntity>() { @Override public void onChanged(@Nullable ProductEntity productEntity) { // update UI } });
  • 25. ViewModel + LiveData + DataBinding = Reactive UI
  • 26. Room
  • 27. Room ● Object Mapping for SQLite Database ● Raw Queries are supported ● Support for RxJava ● Work with java.util.Optional
  • 28. Room - Entity @Entity(tableName = "plants") data class Plant( @PrimaryKey @ColumnInfo(name = "id") val plantId: String, val name: String, val description: String, val growZoneNumber: Int, val wateringInterval: Int = 7, val imageUrl: String = "" )
  • 29. Room - Dao @Dao interface PlantDao { @Query("SELECT * FROM plants ORDER BY name") fun getPlants(): LiveData<List<Plant>> @Query("SELECT * FROM plants WHERE growZoneNumber = :growZoneNumber ORDER BY name") fun getPlantsWithGrowZoneNumber(growZoneNumber: Int): LiveData<List<Plant>> @Query("SELECT * FROM plants WHERE id = :plantId") fun getPlant(plantId: String): LiveData<Plant> @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertAll(plants: List<Plant>) } Observable queries
  • 30. Room - RoomDatabase @Database(entities = [GardenPlanting::class, Plant::class], version = 1, exportSchema = false) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun gardenPlantingDao(): GardenPlantingDao abstract fun plantDao(): PlantDao ... }
  • 32.
  • 34. Paging ● Fetch from database, Network, or both into RecycleView ● Extension of observable List Pattern (e.g LiveData<List>) ● Configurable Load Size, prefetch, placeholders ● Integrates with Room, LiveData, RX ● Stable release
  • 35. Paging - core components 1/2 ● PagedList ○ Load data in pages ○ Async data loading ● DataSource and DataSource.Factory ○ Base class for loading snapshots of data into PagedList ○ Backed by Network or Database
  • 36. Paging - core components 2/2 ● LivePagedListBuilder ○ Build a LiveData<PagedList> based on DataSource.Factory and a PagedList.config ● BoundaryCallBack ○ Signals when PagedList has reached end of available data ● PagedListAdapter ○ A RecyclerView.Adapter that presents data from PagedLists
  • 37. Paging - simplified UI PageListAdapter PagedList -------------- -------------- -------------- Data Layer DataSource.Factory BoundyCallBack Data Source OnItemAtEndLoaded() Save data Get Data ViewModel LiveData<PagedList> Repository LivePagedListBuilder LiveData<PagedList> create() Build -------------- Load more
  • 39. BoundaryCallBack class ConcertBoundaryCallback( private val query: String, private val service: MyService, private val cache: MyLocalCache ) : PagedList.BoundaryCallback<Concert>() { override fun onZeroItemsLoaded() { requestAndSaveData(query) } override fun onItemAtEndLoaded(itemAtEnd: Concert) { requestAndSaveData(query) } }
  • 41. Navigation - Challenges ● Passing Arguments ● Deep Links ● Fragment Transactions ● Testing
  • 42. Navigation - Only available in Android Studio 3.2
  • 44. Navigation - Add Navgraph <fragment android:id="@+id/garden_nav_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_garden"/>
  • 45. Navigation - NavigationController val navController = Navigation.findNavController(this, R.id.garden_nav_fragment) // Set up ActionBar setSupportActionBar(binding.toolbar) NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout) // Set up navigation menu binding.navigationView.setupWithNavController(navController)
  • 46. Navigation - NavigationOnClickListener private fun createOnClickListener(plantId: String): View.OnClickListener { val bundle = bundleOf(PlantDetailFragment.ARG_ITEM_ID to plantId) return Navigation.createNavigateOnClickListener( R.id.action_plant_list_fragment_to_plant_detail_fragment, bundle) } <action android:id="@+id/action_plant_list_fragment_to_plant_detail_fragment" app:destination="@id/plant_detail_fragment"/>
  • 47. Samples and Code Lab Android SunFlower https://github.com/googlesamples/android-sunflower Universal Music Player https://github.com/googlesamples/android-UniversalMusicPlayer/blob/master/app/build.gradle Architecture Components https://github.com/googlesamples/android-architecture-components Code Labs https://codelabs.developers.google.com/?cat=Android Guide to Architecture Components https://developer.android.com/jetpack/docs/guide
  • 48. Conclusion ● Finally Android platform got an Architecture ● Highly Recommended for New Apps ● Try out samples and codelabs
  • 49. Thank You! Twitter : @hassanabidpk Github : hassanabidpk