Getting started with jetpack compose from XML
Tags: android, jetpackcompose, tutorial, mobile
Published: 2023-02-07 08:52:53

As developers specializing in Android, we are well-versed in creating user interfaces using XML. However, it is worth noting that Google is currently advocating the use of Jetpack Compose for developing native user interfaces. Jetpack Compose represents a contemporary toolkit designed for creating native user interfaces on the Android platform. 

[_Why adopt Compose?_
](https://developer.android.com/jetpack/compose/why-adopt)

This article aims to demonstrate the process of incorporating Jetpack Compose into an existing project that utilizes XML for building the user interface. To facilitate this tutorial, the same [project](https://github.com/jhnaiem/UnsplashPhotos/tree/develop) will be utilized throughout. Without further ado, let us commence...


Initially, it is necessary to include the Jetpack Compose dependency within the `build.gradle` file of the application. However, this can be a tedious process when integrating the dependency into an existing project due to the requisite matching of various dependency versions, compilation SDK versions, and Kotlin versions. After several iterations of modifying the dependency versions, I was eventually able to successfully integrate Jetpack Compose into one of my existing projects. Below is a code snippet outlining the configuration: 

```
composeOptions {
        kotlinCompilerExtensionVersion = "1.3.1"
    }
kotlinOptions {
        jvmTarget = '1.8'
    }
buildFeatures {
        compose true
        dataBinding true
        viewBinding true
    }
```

```
ext.versions = [
            'navigation'         : '2.5.1',
            'lifecycle_version'  : '2.4.0',
            'retrofit_version'   : '2.9.0',
            'glide'              : '4.12.0',
            'hilt'               : '2.44.2',
            'paging'             : '3.1.1',
            'timber'             : '5.0.1',
            'compose_version'    : '1.2.0',
            'hilt_navigation'    : '1.0.0',
            'accompanist_version': '0.25.1'
    ]
```

```
//Paging Library
    implementation "androidx.paging:paging-runtime:${versions.paging}"
    implementation "androidx.paging:paging-compose:1.0.0-alpha14"

    //logger
    implementation "com.jakewharton.timber:timber:${versions.timber}"

    //compose
    implementation "androidx.compose.animation:animation:${versions.compose_version}"
    implementation "androidx.compose.foundation:foundation:${versions.compose_version}"
    implementation "androidx.compose.material:material:${versions.compose_version}"
    implementation "androidx.compose.material:material:${versions.compose_version}"
    implementation "androidx.compose.runtime:runtime:${versions.compose_version}"
    implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha01"
    implementation "androidx.compose.ui:ui:${versions.compose_version}"
    debugImplementation "androidx.compose.ui:ui-tooling:${versions.compose_version}"
    implementation "androidx.compose.ui:ui-tooling-preview:${versions.compose_version}"
    implementation('io.coil-kt:coil-compose:2.2.2')
    implementation "androidx.hilt:hilt-navigation-compose:${versions.hilt_navigation}"
    implementation "androidx.navigation:navigation-compose:1.0.0"
    implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0"
    // Accompanist
    implementation "com.google.accompanist:accompanist-placeholder-material:${versions.accompanist_version}"
    implementation "com.google.accompanist:accompanist-navigation-animation:${versions.accompanist_version}"
    implementation "com.google.accompanist:accompanist-permissions:${versions.accompanist_version}"
```

**1.** First replace the part from the XML that you want to convert to Jetpack Compose with _**Compose view**_. Let's remove a recycler view and use Compose view there.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oq90cz0q62i5qm4fl2k0.png)

  

> **Compose view:** It's view in XML which can host Jetpack 
>   Compose UI content. Using this we can get familiar with 
>   jetpack compose on our existing project. Basically all the 
>   view drawn using Jetpack compose will be drawn over this 
>   Compose view.

**2.** Create necessary UI component for the recyclerview you have replaced. We are going to replace recyclerview with **LazyVerticalGrid** in Compose and also create  ItemView(PhotoItemCard) in Compose for the **LazyVerticalGrid** item. 

// The UI for each item can be generated by a reusable composable

{% embed https://gist.github.com/jhnaiem/63b692dae6c4c45f359452bbc4905b90.js %}

Here, I have created a UI for photo item. I have used `Card` to make the photo item clickable.

**3.** Now, I'll put this itemview(PhotoItemCard) inside a  LazyVerticalGrid which is similar to RecyclerView with GridLayoutManager. Creating recyelerview in compose is so simple and easy. No adapters. No view holders. In Compose Recyclerview is replace with LazyColumn, LazyRow, LazyVerticalGrid and LazyHorizontalGrid appropriately.

{% embed https://gist.github.com/jhnaiem/f7ef7e9cdb3c11b5064e0efc7d958736.js %}

{% embed https://gist.github.com/jhnaiem/1f38a1d687947351e289db06ad9d57b5.js %}

Here, I am using the ViewModel (PhotoViewModel) to get the photos PagingData Flow object. After that inside the `PhotoGriding` UI composable convert it to PagingItem by using `collectAsLazyPagingItem` extension function. it collects the flow’s data as lazy items. And that’s exactly what we need. Compose knows how to handle this object and request more items when the user reaches the end of the list. I am loading this paginated data into the list using LazyVerticalGrid.

**4.** Lastly, define a function in the fragment on which view you are replacing and access the composeView in the xml using binding. set view composition strategy to DisposeOnViewTreeLifecycleDestroyed. Then inside setcontent call the composable function.

> ViewCompositionStrategy that disposes the composition when the ViewTreeLifecycleOwner of the next window the view is attached to is destroyed.

{% embed https://gist.github.com/jhnaiem/87adaaf39fda3494fde6f067417be2b3.js %}

Here, I have defined a lamda for item click to navigate to
 PhotoFullScreen and passed it to the composable function as an argument. Also passed the ViewModel(PhotoViewModel) to access the data(photos).

**--->**
  It's a good idea to start with small parts of your app and gradually convert more and more of it to Compose.That would be all for this article, I hope you liked it!
**N.B. You may find Jetpack Compose app laggy in debug mode.** [You should always test Compose performance in release.](https://medium.com/androiddevelopers/why-should-you-always-test-compose-performance-in-release-4168dd0f2c71)
The full code with detailed implementation can be found on GitHub. Checkout the [to-JetpackCompose](https://github.com/jhnaiem/UnsplashPhotos/tree/to-JetpackCompose) branch:
{% embed https://github.com/jhnaiem/UnsplashPhotos %}

**References:**
[https://developer.android.com/jetpack/compose/interop
](https://developer.android.com/jetpack/compose/interop)
[https://developer.android.com/jetpack/compose/interop/interop-apis](https://developer.android.com/jetpack/compose/interop/interop-apis)