Source: Google Blog
Optimization | Effect |
---|---|
Combination of multiple Class files in one DEX file | Smaller memory footprint, faster load of the application |
Sharing of DEX files between processes (read-only mapping) | Smaller memory footprint, faster load of the application |
Byte ordering and word alignment according to local machine (install time) | Faster load of the application DEX file itself still platform independent |
Bytecode pre-verification (as much as possible, install time) | Faster load and execution |
Install-time optimization of bytecode | Faster execution, still platform independence |
Register instead of stack based virtual machine | Faster execution (~30%) |
/Users/\<user>/Library/Android/sdk/platform-tools
adb -e shell
adb push \<local> \<remote>
adb pull \<remote> \[\<local>]
adb install \<file>
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<uses-permission/>
<application>
<activity>
<intent-filter>
<action/>
<category/>
<data/>
</intent-filter>
<meta-data/>
</activity>
<service>
<intent-filter>...</intent-filter>
<meta-data/>
</service>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"/>
</LinearLayout>
@Composable
fun component() {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = "Hello World!")
Button(onClick = { /*TODO*/ }) {
Text(text = "Button")
}
}
}
A composable function always has the annotation @Composable
. Within the function the basic building block is declared and describes the UI. It might contain several UI elements.
@Composable
fun MovieItem(movie: Movie, onMovieClick: (Movie) -> Unit) {
AsyncImage(model = movie.poster, contentDescription = "poster")
Text(text = movie.title)
Text(text = movie.year)
}
In most of the cases you can just use the standard layout elements like Box
, Row
or Column
to place the items on the screen.
@Composable
fun MovieItem(movie: Movie, onMovieClick: (Movie) -> Unit) {
Row() {
AsyncImage(model = movie.poster, contentDescription = "poster",)
Text(text = movie.title)
Text(text = movie.year)
}
}
There are also properties to align the elements accordingly:
@Composable
fun MovieItem(movie: Movie, onMovieClick: (Movie) -> Unit) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(model = movie.poster, contentDescription = "poster",)
Text(text = movie.title)
Text(text = movie.year)
}
}
You can also nest elements like you need them:
@Composable
fun MovieItem(movie: Movie, onMovieClick: (Movie) -> Unit) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(model = movie.poster, contentDescription = "poster",)
Column {
Text(text = movie.title)
Text(text = movie.year)
}
}
}
A special property is the Modifier
. This can be used to change the size, layout, behaviour of the element. You can also add information like accessibility labels or test tags. You can also make elements clickable.
Please keep in mind that the order of the modifiers functions is significant because this can affect the final result.
@Composable
fun MovieItem(movie: Movie, onMovieClick: (Movie) -> Unit) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(modifier = Modifier.width(80.dp).padding(8.dp), model = movie.poster, contentDescription = "poster",)
Column {
Text(text = movie.title, fontSize = 20.sp)
Text(text = movie.year)
}
}
}
Scaffold
which provides a structure of your screenTopAppBar
to display a title and provide navigationText
as a label to display textButton
to make clickable elementsTextField
for text inputsThe MainActivity
class is the entry UI component. The onCreate()
function belongs to the Activity Lifecycle and is automatically called by the system. In there you need to call the first composable in the setContent()
function:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MovieTrackerTheme {
MovieTracker()
}
}
}
}
To keep in mind that there are still old apps around you need to now the most common types of layouts:
A ConstraintLayout
is a android.view.ViewGroup
which allows you to position and size widgets in
a flexible way.
A layout that organizes its children into a single horizontal or vertical row. It creates a scrollbar if the length of the window exceeds the length of the screen.
Enables you to specify the location of child objects relative to each other (child A to the left of child B) or to the parent (aligned to the top of the parent).
remember
API to store objects in memory. There are 3 different ways to do so:val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
Here is an example:
@Composable
fun helloContent() {
Column(modifier = Modifier.padding(16.dp)) {
var name by remember { mutableStateOf("") }
if (name.isNotEmpty()) {
Text(
text = "Hello, $name!",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.bodyMedium
)
}
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
}
}
/res/values/strings.xml
/res/drawable
/res/mipmap
/res/layout
(not needed with Jetpack Compose)@string
) and images
(@drawable
):AsyncImage(model = R.drawable.ic_launcher_background, contentDescription = "poster",)
Text(text = stringResource(id = R.string.app_name))
Create a new directory in res/ named in the form <resources_name>-<config_qualifier>
<resources_name>
is the directory name of the corresponding default resources<qualifier>
is a name that specifies an individual configuration for which these resources
are to be usedSave the respective alternative resources in this new directory. The resource files must be named exactly the same as the default resource files
res/
drawable/
icon.png
background.png
drawable-hdpi/
icon.png
background.png
Sizes of view components should be defined in Density Independent Pixels (dp) in order to always get the best results.
More information here.
dp
) describes the size of a UI element in a density independent
manner160ppi
, one dp corresponds to one physical pixel (px)160ppi
, the dp values are converted with the help of the
densityFactor
densityFactor
describes the device's physical density in relation to the default density of
160ppi
densityFactor
at runtime:val densityFactor = LocalDensity.current.density
R.java
filepublic final class R {
// ...
public static final class layout {
public static final int activity_main = 0x7f030000;
}
public static final class mipmap {
public static final int ic_launcher = 0x7f020000;
public static final int ic_launcher_round = 0x7f020001;
}
public static final class string {
public static final int ButtonText = 0x7f050000;
public static final int app_name = 0x7f050001;
}
}
Note: AndroidX is the successor of the deprecated Android Support Libraries. The usage of the old Android Support Libraries is not recommended anymore for most of the projects.
AppCompatActivity
class is the default class used for Activities that want to make
use of the new Material Design features (introduced with API level 21)
build.gradle
/build.gradle.kts
files