Analyze the first program

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTheme {
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
Copy the code

As you can see, the compose entry is still an Activity, but instead of the setContentView method in the onCreate method, setContent. So how do you display the layout? Let’s go to the setContent source to see how it works:

public fun ComponentActivity.setContent( parent: CompositionContext? = null, content: @Composable () -> Unit ) { val existingComposeView = window.decorView .findViewById<ViewGroup>(android.R.id.content) .getChildAt(0) as? ComposeView if (existingComposeView ! = null) with(existingComposeView) { setParentCompositionContext(parent) setContent(content) } else ComposeView(this).apply { // Set content and parent **before** setContentView // to have ComposeView create the composition on attach setParentCompositionContext(parent) setContent(content) // Set the view tree owners before setting  the content view so that the inflation process // and attach listeners will see them already present setOwners() setContentView(this, DefaultActivityContentLayoutParams) } }Copy the code

First, this method is an extension of ComponentActivity, and the auto-generated MainActivity above also inherits from ComponentActivity. Now find the root layout through the decorView of the window in the Activity, and get the 0th sublayout of the root layout and force it to ComposeView. But right now we don’t have that set, so existingComposeView is NULL, if anything happens we’ll go into the else branch and create a new ComposeView, and then set the content and the parent before the setContentView so that the ComposeView creates the composition, And then I’m going to call setContentView. In the setContent method, the first argument is the parent control in Compose, which is used for scheduling, and the second argument is a Composable function with a Composable lambda argument.

The setContent is wrapped with the ComposeTheme, which is Compose’s theme, which wraps around the Surface and sets the background color of the page. The Surface Greeting is the control displayed on the page, the Hellow World control displayed on the page.

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}
Copy the code

Greeting is a method, also known as a composable function, because of the control you can use in Compose. The following points to note when using the Compose control:

1. This function is annotated with @composable. All composable functions must carry this annotation, which tells the Compose editor that the function is intended to convert data into an interface.

2. Composable functions can accept parameters that allow the application logic to describe the page. For example, the Greeing method in the example above accepts parameters of type String that can be displayed directly in the interface.

3. The Compose function does not return a value. The Compose function does not need to return anything.

4. Composable functions have no side effects when describing interfaces, such as modifying properties or global variables.

Using the Preview

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeTheme {
        Greeting("Android")
    }
}
Copy the code

We can see the preview in Split on the right

Try changing the method parameter “Android” to “My Android”

If the preview is not updated in time after modifying the code, it can be refreshed manually by clicking the Refresh button in the upper left corner.

There are many ways to use Preview, so we can look at the code for this annotation class:

@Repeatable annotation class Preview( val name: String = "", val group: String = "", @IntRange(from = 1) val apiLevel: Int = -1, // TODO(mount): Make this Dp when they are inline classes val widthDp: Int = -1, // TODO(mount): Make this Dp when they are inline classes val heightDp: Int = -1, val locale: String = "", @floatrange (from = 0.01) val fontScale: Float = 1f, val showSystemUi: Boolean = false, val showBackground: Boolean Boolean = false, val backgroundColor: Long = 0, @UiMode val uiMode: Int = 0, @Device val device: String = Devices.DEFAULT )Copy the code

We tried to change the width and height of the preview, and we can see the effect in the preview on the right:

@Preview(showBackground = true, widthDp = 100, heightDp = 150)
@Composable
fun DefaultPreview() {
    ComposeTheme {
        Greeting("My Android")
    }
}
Copy the code

Other properties you can try to verify.