Build Applications Faster with Android Jetpack
Gilang Ramadhan,
Academy Content Writer at Dicoding
Gilang Ramadhan �Academy Content Writer at Dicoding
What is Android Jetpack?
Jetpack?
Kiri, Kanan, L1, L2, R1, R2, Atas, Bawah, Kiri, Kanan
Android Jetpack
Jetpack is a collection of Android software components to make it easier for you to develop great Android apps.
Advantages
Accelerate development
Eliminate boilerplate code
Build high quality, robust apps
Android Jetpack Components
Foundation
Architecture
UI
Behavior
Foundation - AppCompat
Before After
com.android.support:cardview-v7 androidx.cardview:cardview:1.0.0
com.android.support:appcompat-v7 androidx.appcompat:appcompat:1.0.0
com.android.support:recyclerview-v7 androidx.recyclerview:recyclerview:1.0.0
android.arch.persistence.room:common androidx.room:room-common:2.0.0-rc01
android.arch.core:common androidx.arch.core:core-common:2.0.0-rc01
android.arch.core:core androidx.arch.core:core:2.0.0-rc01
android.arch.paging:common androidx.paging:paging-common:2.0.0-rc01
.... ....
Degrade gracefully on older versions of Android
Foundation - Android KTX
Getting Started
dependencies {
implementation 'androidx.core:core-ktx:1.0.0'
}
Before
sharedPreferences.edit()
.putBoolean("key", value)
.apply()
After
sharedPreferences.edit {
putBoolean("key", value)
}
Write more concise, idiomatic Kotlin code
Foundation - Multidex
Multidex Support prior to Android 5.0 (Api 21)
android {
defaultConfig {
...
minSdkVersion 15
targetSdkVersion 28
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.3'
}
Provide support for apps with multiple DEX files
Enable multidex for apps with over 64K methods
Foundation - Test
An Android testing framework for unit and runtime UI tests
Foundation - Test
An Android testing framework for unit and runtime UI tests
Foundation - Unit Test
Getting Started
dependencies {
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.12'
// Optional -- Robolectric environment
testImplementation 'androidx.test:core:1.0.0'
// Optional -- Mockito framework
testImplementation 'org.mockito:mockito-core:1.10.19'
}
Foundation - Instrumental Testing
Getting Started
dependencies {
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
// Optional -- Hamcrest library
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
// Optional -- UI testing with Espresso
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
// Optional -- UI testing with UI Automator
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
}
Architecture Component
Architecture - ViewModel
Manage UI-related data in a lifecycle-conscious way
Architecture - LiveData
Ensures your UI matches your data state
No memory leaks
No crashes due to stopped activities
No more manual lifecycle handling
Always up to date data
Proper configuration changes
Sharing resources
Notify views when underlying database changes
Architecture - LiveData
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<String>();
}
return currentName;
}
// Rest of the ViewModel...
}
Notify views when underlying database changes
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
Architecture - Data Binding
Getting Started
android {
....
dataBinding {
enabled = true
}
}
Declaratively bind observable data to UI elements
Activity
TextView textView = findViewById(R.id.sample_text);
textView.setText(viewModel.getUserName());
Layout
<TextView
android:text="@{viewmodel.userName}" />
Architecture - Lifecycles
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) {
// ...
}
void start() {
// connect to system location service
}
void stop() {
// disconnect from system location service
}
}
Manage your activity and fragment lifecycles
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
@Override
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// update UI
});
}
@Override
public void onStart() {
super.onStart();
myLocationListener.start();
// manage other components that need to respond to the activity lifecycle
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
// manage other components that need to respond to the activity lifecycle
}
}
class MyActivity extends AppCompatActivity {
...
@Override
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start();
}
});
}
...
}
Architecture - Lifecycles
Manage your activity and fragment lifecycles
Architecture - Lifecycles
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
Manage your activity and fragment lifecycles
Architecture - Room
Fluent SQLite database access
Architecture - Room
Entity
@Entity
public class User {
@PrimaryKey
public int uid;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
Architecture - Room
Dao
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAll();
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
List<User> loadAllByIds(int[] userIds);
@Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1")
User findByName(String first, String last);
@Insert
void insertAll(User... users);
@Delete
void delete(User user);
}
Architecture - Room
Database
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
Create Database
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, "database-name").build();
Architecture - Paging
Gradually load information on demand from your data source
Architecture - Paging
PagedList
public class ConcertViewModel extends ViewModel {
private ConcertDao concertDao;
public final LiveData<PagedList<Concert>> concertList;
// Creates a PagedList object with 50 items per page.
public ConcertViewModel(ConcertDao concertDao) {
this.concertDao = concertDao;
concertList = new LivePagedListBuilder<>(
concertDao.concertsByDate(), 50).build();
}
}
Gradually load information on demand from your data source
Architecture - Paging
Data
@Dao
public interface ConcertDao {
// The Integer type parameter tells Room to use a
// PositionalDataSource object.
@Query("SELECT * FROM concerts ORDER BY date DESC")
DataSource.Factory<Integer, Concert> concertsByDate();
}
Gradually load information on demand from your data source
Architecture - Paging
Gradually load information on demand from your data source
Architecture - Navigation
Handle everything needed for in-app navigation
If you want to use the Navigation Architecture Component with Android Studio, you must use Android Studio 3.2 Canary 14 or higher.
Architecture - Navigation
Handle everything needed for in-app navigation
Architecture - WorkManager
Key features:
Manage your Android background jobs
Architecture - WorkManager
public class UploadWorker extends Worker {
public UploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@Override
public Result doWork() {
// Do the work here--in this case, upload the images.
uploadImages()
// Indicate whether the task finished successfully with the Result
return Result.success()
}
}
Manage your Android background jobs
Architecture - WorkManager
OneTimeWorkRequest
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class).build()
PeriodicWorkRequest
Constraints constraints = new Constraints.Builder().setRequiresCharging(true).build();
PeriodicWorkRequest saveRequest = new PeriodicWorkRequest.Builder(SaveImageFileWorker.class, 1, TimeUnit.HOURS).setConstraints(constraints).build();
WorkManager.getInstance().enqueue(saveRequest);
Manage your Android background jobs
Architecture - WorkManager
WorkContinuation chain1 = WorkManager.getInstance()
.beginWith(workA)
.then(workB);
WorkContinuation chain2 = WorkManager.getInstance()
.beginWith(workC)
.then(workD);
WorkContinuation chain3 = WorkContinuation
.combine(Arrays.asList(chain1, chain2))
.then(workE);
chain3.enqueue();
Manage your Android background jobs
Behavior - Download Manager
class DownloadManager.Query
This class may be used to filter download manager queries.
class DownloadManager.Request
This class contains all the information necessary to request a new download.
Schedule and manage large downloads
Behavior - Media & Playback
A multimedia application that plays audio or video usually has two parts:
Backwards compatible APIs for media playback and routing (including Google Cast)
Behavior - Media & Playback
A multimedia application that plays audio or video usually has two parts:
Backwards compatible APIs for media playback and routing (including Google Cast)
Behavior - Media & Playback
Backwards compatible APIs for media playback and routing (including Google Cast)
Behavior - Media & Playback
Video apps versus audio apps
Behavior - Notifications
Status bar and notification drawer Heads-up notification
Provides a backwards-compatible notification API with support for Wear and Auto
Behavior - Notifications
Lock screen App icon badge Wear OS devices
Provides a backwards-compatible notification API with support for Wear and Auto
Behavior - Notifications
Provides a backwards-compatible notification API with support for Wear and Auto
Behavior - Permissions
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application ...>
...
</application>
</manifest>
Compatibility APIs for checking and requesting app permissions
Behavior - Preferences
<androidx.preference.PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
app:key="notifications"
app:title="Enable message notifications"/>
<Preference
app:key="feedback"
app:title="Send feedback"
app:summary="Report technical issues or suggest new features"/>
</androidx.preference.PreferenceScreen>
Create interactive settings screens
Behavior - Sharing
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_item_share"
android:showAsAction="ifRoom"
android:title="Share"
android:actionProviderClass=
"android.widget.ShareActionProvider" />
...
</menu>
Provides a share action suitable for an app’s action bar
private ShareActionProvider shareActionProvider;
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu resource file.
getMenuInflater().inflate(R.menu.share_menu, menu);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.menu_item_share);
// Fetch and store ShareActionProvider
shareActionProvider = (ShareActionProvider) item.getActionProvider();
// Return true to display menu
return true;
}
// Call to update the share intent
private void setShareIntent(Intent shareIntent) {
if (shareActionProvider != null) {
shareActionProvider.setShareIntent(shareIntent);
}
}
Behavior - Slices
Android’s new approach to remote content :
Create flexible UI elements that can display app data outside the app
dependencies {
// ...
implementation "androidx.slice:slice-builders:(latest version)"
// ...
}
Behavior - Slices
Dynamic and interactive content Enables rich and flexible layout
Templated
Behavior - Slices
Enhance predictions with rich app content
Accelerate navigation, task completion and discovery of app content.
App names
eg. [maps], [lyft], [airbnb]
General trems
eg. [get a ride], [trending videos]
Launching in search
Behavior - Slices
Example Use Case
Behavior - Slices
adb install -r -t slice-viewer.apk
Enter slice-<your slice URI> in the URL field
Example: slice-content://com.example.your.sliceuri
Example Use Case
Behavior - Slices
Slice Structure
UI - Animations & Transitions
Move widgets and transition between screens
UI - Emoji
Enable an up-to-date emoji font on older platforms
UI - Emoji
How does EmojiCompat work?
dependencies {
...
implementation "androidx.emoji:emoji:1.0.0"
}
UI - Fragment
A basic unit of composable UI
UI - Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>
Lay out widgets using different algorithms
UI - Palette
dependencies {
...
implementation 'androidx.palette:palette:1.0.0'
}
Pull useful information out of color palettes
UI - Auto
Components to help develop apps for Android Auto
UI - TV
Components to help develop apps for Android TV
UI - Wear OS by Google
Components to help develop apps for Wear
What’s Next?
Create useful applications!
https://developer.android.com/jetpack
Thank you
Gilang Ramadhan
+6281904996393
gilang@dicoding.com