---
title: "AndroidView"
description: "Composes an Android [View] obtained from [factory]. The [factory] block will be called exactly
once to obtain the [View] being composed, and it is also guaranteed to be invoked on the UI
thread. Therefore, in addition to creating the [View], the [factory] block can also be used to
perform one-off initializations and [View] constant properties' setting. The [update] block can
run multiple times (on the UI thread as well) due to recomposition, and it is the right place to
set the new properties. Note that the block will also run once right after the [factory] block
completes.

[AndroidView] is commonly needed for using Views that are infeasible to be reimplemented in
Compose and there is no corresponding Compose API. Common examples for the moment are WebView,
SurfaceView, AdView, etc.

This overload of [AndroidView] does not automatically pool or reuse Views. If placed inside of a
reusable container (including inside a [LazyRow][androidx.compose.foundation.lazy.LazyRow] or
[LazyColumn][androidx.compose.foundation.lazy.LazyColumn]), the View instances will always be
discarded and recreated if the composition hierarchy containing the AndroidView changes, even if
its group structure did not change and the View could have conceivably been reused.

To opt-in for View reuse, call the overload of [AndroidView] that accepts an `onReset` callback,
and provide a non-null implementation for this callback. Since it is expensive to discard and
recreate View instances, reusing Views can lead to noticeable performance improvements —
especially when building a scrolling list of [AndroidViews][AndroidView]. It is highly
recommended to opt-in to View reuse when possible.

[AndroidView] will not clip its content to the layout bounds. Use [View.setClipToOutline] on the
child View to clip the contents, if desired. Developers will likely want to do this with all
subclasses of SurfaceView to keep its contents contained.

[AndroidView] has nested scroll interop capabilities if the containing view has nested scroll
enabled. This means this Composable can dispatch scroll deltas if it is placed inside a container
that participates in nested scroll. For more information on how to enable nested scroll interop:"
type: "composable"
---

<div class='type'>Composable Function</div>


<a id='references'></a>

<div class='sourceset sourceset-android'>Android</div>


```kotlin
@Composable
fun <T : View> AndroidView(
    factory: (Context) -> T,
    modifier: Modifier = Modifier,
    update: (T) -> Unit = NoOpUpdate,
)
```


Composes an Android `View` obtained from `factory`. The `factory` block will be called exactly
once to obtain the `View` being composed, and it is also guaranteed to be invoked on the UI
thread. Therefore, in addition to creating the `View`, the `factory` block can also be used to
perform one-off initializations and `View` constant properties' setting. The `update` block can
run multiple times (on the UI thread as well) due to recomposition, and it is the right place to
set the new properties. Note that the block will also run once right after the `factory` block
completes.

`AndroidView` is commonly needed for using Views that are infeasible to be reimplemented in
Compose and there is no corresponding Compose API. Common examples for the moment are WebView,
SurfaceView, AdView, etc.

This overload of `AndroidView` does not automatically pool or reuse Views. If placed inside of a
reusable container (including inside a `LazyRow` or
`LazyColumn`), the View instances will always be
discarded and recreated if the composition hierarchy containing the AndroidView changes, even if
its group structure did not change and the View could have conceivably been reused.

To opt-in for View reuse, call the overload of `AndroidView` that accepts an `onReset` callback,
and provide a non-null implementation for this callback. Since it is expensive to discard and
recreate View instances, reusing Views can lead to noticeable performance improvements —
especially when building a scrolling list of `AndroidViews`. It is highly
recommended to opt-in to View reuse when possible.

`AndroidView` will not clip its content to the layout bounds. Use `View.setClipToOutline` on the
child View to clip the contents, if desired. Developers will likely want to do this with all
subclasses of SurfaceView to keep its contents contained.

`AndroidView` has nested scroll interop capabilities if the containing view has nested scroll
enabled. This means this Composable can dispatch scroll deltas if it is placed inside a container
that participates in nested scroll. For more information on how to enable nested scroll interop:

#### Parameters

| | |
| --- | --- |
| factory | The block creating the `View` to be composed. |
| modifier | The modifier to be applied to the layout. |
| update | A callback to be invoked after the layout is inflated and upon recomposition to update the information and state of the view. |




<div class='sourceset sourceset-android'>Android</div>


```kotlin
@Composable
fun <T : View> AndroidView(
    factory: (Context) -> T,
    modifier: Modifier = Modifier,
    onReset: ((T) -> Unit)? = null,
    onRelease: (T) -> Unit = NoOpUpdate,
    update: (T) -> Unit = NoOpUpdate,
)
```


Composes an Android `View` obtained from `factory`. The `factory` block will be called exactly
once to obtain the `View` being composed, and it is also guaranteed to be invoked on the UI
thread. Therefore, in addition to creating the `View`, the `factory` block can also be used to
perform one-off initializations and `View` constant properties' setting. The `update` block can
run multiple times (on the UI thread as well) due to recomposition, and it is the right place to
set the new properties. Note that the block will also run once right after the `factory` block
completes.

`AndroidView` is commonly needed for using Views that are infeasible to be reimplemented in
Compose and there is no corresponding Compose API. Common examples for the moment are WebView,
SurfaceView, AdView, etc.

By default, `AndroidView` does not automatically pool or reuse Views. If placed inside of a
reusable container (including inside a `LazyRow` or
`LazyColumn`), the View instances will always be
discarded and recreated if the composition hierarchy containing the AndroidView changes, even if
its group structure did not change and the View could have conceivably been reused.

Views are eligible for reuse if `AndroidView` is given a non-null `onReset` callback. Since it is
expensive to discard and recreate View instances, reusing Views can lead to noticeable
performance improvements — especially when building a scrolling list of
`AndroidViews`. It is highly recommended to specify an `onReset` implementation and
opt-in to View reuse when possible.

When `onReset` is specified, `View` instances may be reused when hosted inside of a container
that supports reusable elements. Reuse occurs when compatible instances of `AndroidView` are
inserted and removed during recomposition. Two instances of `AndroidView` are considered
compatible if they are invoked with the same composable group structure. The most common scenario
where this happens is in lazy layout APIs like `LazyRow` and `LazyColumn`, which can reuse layout
nodes (and Views, in this case) between items when scrolling.

`onReset` is invoked on the UI thread when the View will be reused, signaling that the View
should be prepared to appear in a new context in the composition hierarchy. This callback is
invoked before `update` and may be used to reset any transient View state like animations or user
input.

Note that `onReset` may not be immediately followed by a call to `update`. Compose may
temporarily detach the View from the composition hierarchy if it is deactivated but not released
from composition. This can happen if the View appears in a `ReusableContentHost` that is not
currently active or inside of a `movable content`
block that is being moved. If this happens, the View will be removed from its parent, but
retained by Compose so that it may be reused if its content host becomes active again. If the
View never becomes active again and is instead discarded entirely, the `onReset` callback will be
invoked directly from this deactivated state when Compose releases the View.

If you need to observe whether the View is currently used in the composition hierarchy, you may
observe whether it is attached via `View.addOnAttachStateChangeListener`. The View may also
observe the lifecycle of its host via `findViewTreeLifecycleOwner`. The lifecycle returned by
this function will match the `LocalLifecycleOwner`. Note that the lifecycle is not set and cannot
be used until the View is attached.

When the View is removed from the composition permanently, `onRelease` will be invoked (also on
the UI thread). Once this callback returns, Compose will never attempt to reuse the previous View
instance regardless of whether an `onReset` implementation was provided. If the View is needed
again in the future, a new instance will be created, with a fresh lifecycle that begins by
calling the `factory`.

`AndroidView` will not clip its content to the layout bounds. Use `View.setClipToOutline` on the
child View to clip the contents, if desired. Developers will likely want to do this with all
subclasses of SurfaceView to keep its contents contained.

`AndroidView` has nested scroll interop capabilities if the containing view has nested scroll
enabled. This means this Composable can dispatch scroll deltas if it is placed inside a container
that participates in nested scroll. For more information on how to enable nested scroll interop:

#### Parameters

| | |
| --- | --- |
| factory | The block creating the `View` to be composed. |
| modifier | The modifier to be applied to the layout. |
| onReset | A callback invoked as a signal that the view is about to be attached to the composition hierarchy in a different context than its original creation. This callback is invoked before `update` and should prepare the view for general reuse. If `null` or not specified, the `AndroidView` instance will not support reuse, and the View instance will always be discarded whenever the AndroidView is moved or removed from the composition hierarchy. |
| onRelease | A callback invoked as a signal that this view instance has exited the composition hierarchy entirely and will not be reused again. Any additional resources used by the View should be freed at this time. |
| update | A callback to be invoked after the layout is inflated and upon recomposition to update the information and state of the view. |





## Code Examples
### AndroidViewSample
```kotlin
@Suppress("SetTextI18n")
@Composable
fun AndroidViewSample() {
    // Compose a TextView.
    AndroidView({ context -> TextView(context).apply { text = "This is a TextView" } })
    // Compose a View and update its size based on state. Note the modifiers.
    var size by remember { mutableStateOf(20) }
    AndroidView(::View, Modifier.clickable { size += 20 }.background(Color.Blue)) { view ->
        view.layoutParams = ViewGroup.LayoutParams(size, size)
    }
}
```
### AndroidViewWithReleaseSample
```kotlin
@Suppress("UNUSED_ANONYMOUS_PARAMETER")
@Composable
fun AndroidViewWithReleaseSample() {
    // Compose a View that needs to be cleaned up when removed from the UI
    class LifecycleAwareView(context: Context) : View(context) {
        var lifecycle: Lifecycle? = null
            set(value) {
                field?.removeObserver(observer)
                value?.addObserver(observer)
                field = value
            }
        private val observer = LifecycleEventObserver { source, event ->
            // React to the event
        }
    }
    val lifecycle = LocalLifecycleOwner.current.lifecycle
    AndroidView(
        factory = { context -> LifecycleAwareView(context) },
        update = { view -> view.lifecycle = lifecycle },
        onRelease = { view ->
            // Need to release the lifecycle to prevent a memory leak
            view.lifecycle = null
        },
    )
}
```
### ReusableAndroidViewInLazyColumnSample
```kotlin
@Composable
fun ReusableAndroidViewInLazyColumnSample() {
    val urls =
        listOf(
            "https://developer.android.com/jetpack/compose",
            "https://google.github.io/accompanist/",
            "https://android-developers.googleblog.com/",
            "https://io.google/",
            // ...
        )
    LazyVerticalGrid(columns = GridCells.Adaptive(512.dp)) {
        items(urls) { url ->
            AndroidView(
                factory = { context ->
                    WebView(context).apply {
                        settings.javaScriptEnabled = true
                        webViewClient =
                            object : WebViewClient() {
                                // Optional overrides for WebViewClient
                            }
                    }
                },
                modifier = Modifier.fillMaxWidth().aspectRatio(1f),
                update = { webView -> webView.loadUrl(url) },
                onReset = { webView ->
                    webView.stopLoading()
                    webView.loadUrl("about:blank")
                    webView.clearHistory()
                },
            )
        }
    }
}
```
### ViewInComposeNestedScrollInteropSample
```kotlin
@Composable
fun ViewInComposeNestedScrollInteropSample() {
    Box(
        Modifier.fillMaxSize()
            .scrollable(
                rememberScrollableState {
                    // view world deltas should be reflected in compose world
                    // components that participate in nested scrolling
                    it
                },
                Orientation.Vertical,
            )
    ) {
        AndroidView({ context ->
            LayoutInflater.from(context).inflate(android.R.layout.activity_list_item, null).apply {
                // Nested Scroll Interop will be Enabled when
                // nested scroll is enabled for the root view
                ViewCompat.setNestedScrollingEnabled(this, true)
            }
        })
    }
}
```

