Skip to content

Commit 685db45

Browse files
Refactor: Introduce SyntaxFabActivity to reduce boilerplate
This commit introduces a new abstract base class, `SyntaxFabActivity`, to encapsulate the common behavior of the "Show Syntax" Floating Action Button (FAB). This FAB, used across many lesson activities, now has its click handling and auto-shrink logic managed within this shared base class. Key changes: - Created `SyntaxFabActivity` which handles the FAB's `setOnClickListener` and the 5-second auto-shrink `postDelayed` logic. - Migrated numerous lesson activities to extend `SyntaxFabActivity` instead of `UpNavigationActivity`, replacing duplicated Handler and click listener code with a single call to the new `setupSyntaxFab` method. - Updated the Room dependency to version 2.8.2.
1 parent e89166e commit 685db45

File tree

30 files changed

+127
-402
lines changed

30 files changed

+127
-402
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.d4rk.androidtutorials.java.ui.components.navigation;
2+
3+
import android.os.Handler;
4+
import android.os.Looper;
5+
6+
import androidx.annotation.NonNull;
7+
import androidx.annotation.Nullable;
8+
9+
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
10+
11+
/**
12+
* Base activity that encapsulates the common pattern of wiring a syntax FAB that shrinks after
13+
* a short delay. A large portion of the lesson detail screens use the same behaviour which was
14+
* previously duplicated in every activity.
15+
*/
16+
public abstract class SyntaxFabActivity extends UpNavigationActivity {
17+
18+
private static final long DEFAULT_SHRINK_DELAY_MS = 5000L;
19+
20+
private final Handler syntaxFabHandler = new Handler(Looper.getMainLooper());
21+
22+
protected final void setupSyntaxFab(@Nullable ExtendedFloatingActionButton fab,
23+
@NonNull Runnable onClick) {
24+
if (fab == null) {
25+
return;
26+
}
27+
28+
fab.setOnClickListener(view -> onClick.run());
29+
syntaxFabHandler.postDelayed(fab::shrink, DEFAULT_SHRINK_DELAY_MS);
30+
}
31+
32+
@Override
33+
protected void onDestroy() {
34+
syntaxFabHandler.removeCallbacksAndMessages(null);
35+
super.onDestroy();
36+
}
37+
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/alerts/alertdialog/AlertDialogActivity.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
7-
85
import com.d4rk.androidtutorials.java.R;
96
import com.d4rk.androidtutorials.java.databinding.ActivityAlertDialogBinding;
10-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
7+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
118
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
129
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1310
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
1411

15-
public class AlertDialogActivity extends UpNavigationActivity {
16-
private final Handler handler = new Handler(Looper.getMainLooper());
12+
public class AlertDialogActivity extends SyntaxFabActivity {
1713
private ActivityAlertDialogBinding binding;
1814

1915
@Override
@@ -25,13 +21,11 @@ protected void onCreate(Bundle savedInstanceState) {
2521
MaterialAlertDialogBuilder alertDialog = createAlertDialog();
2622
binding.button.setOnClickListener(v -> alertDialog.show());
2723

28-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
24+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
2925
Intent intent = new Intent(this, CodeActivity.class);
3026
intent.putExtra("lesson_name", "AlertDialog");
3127
startActivity(intent);
3228
});
33-
34-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
3529
}
3630

3731
private MaterialAlertDialogBuilder createAlertDialog() {
@@ -42,11 +36,4 @@ private MaterialAlertDialogBuilder createAlertDialog() {
4236
.setPositiveButton(android.R.string.ok, null)
4337
.setNegativeButton(android.R.string.cancel, null);
4438
}
45-
46-
47-
@Override
48-
protected void onDestroy() {
49-
super.onDestroy();
50-
handler.removeCallbacksAndMessages(null);
51-
}
5239
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/alerts/snackbar/SnackBarActivity.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
7-
85
import com.d4rk.androidtutorials.java.R;
96
import com.d4rk.androidtutorials.java.databinding.ActivitySnackBarBinding;
10-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
7+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
118
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
129
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1310
import com.google.android.material.snackbar.Snackbar;
1411

15-
public class SnackBarActivity extends UpNavigationActivity {
16-
private final Handler handler = new Handler(Looper.getMainLooper());
12+
public class SnackBarActivity extends SyntaxFabActivity {
1713
private ActivitySnackBarBinding binding;
1814

1915
@Override
@@ -28,19 +24,10 @@ protected void onCreate(Bundle savedInstanceState) {
2824
snackbar.show();
2925
});
3026

31-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
27+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
3228
Intent intent = new Intent(this, CodeActivity.class);
3329
intent.putExtra("lesson_name", "SnackBar");
3430
startActivity(intent);
3531
});
36-
37-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
38-
}
39-
40-
41-
@Override
42-
protected void onDestroy() {
43-
super.onDestroy();
44-
handler.removeCallbacksAndMessages(null);
4532
}
4633
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/alerts/toast/ToastActivity.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,15 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
75
import android.widget.Toast;
86

97
import com.d4rk.androidtutorials.java.R;
108
import com.d4rk.androidtutorials.java.databinding.ActivityToastBinding;
11-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
9+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
1210
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
1311
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1412

15-
public class ToastActivity extends UpNavigationActivity {
16-
private final Handler handler = new Handler(Looper.getMainLooper());
13+
public class ToastActivity extends SyntaxFabActivity {
1714
private ActivityToastBinding binding;
1815

1916
@Override
@@ -27,19 +24,10 @@ protected void onCreate(Bundle savedInstanceState) {
2724
Toast.makeText(this, R.string.toast_this_is_a_toast, Toast.LENGTH_SHORT).show()
2825
);
2926

30-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
27+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
3128
Intent intent = new Intent(this, CodeActivity.class);
3229
intent.putExtra("lesson_name", "Toast");
3330
startActivity(intent);
3431
});
35-
36-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
37-
}
38-
39-
40-
@Override
41-
protected void onDestroy() {
42-
super.onDestroy();
43-
handler.removeCallbacksAndMessages(null);
4432
}
4533
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/buttons/buttons/ButtonsActivity.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.buttons.buttons;
22

33
import android.os.Bundle;
4-
import android.os.Handler;
5-
import android.os.Looper;
6-
74
import com.d4rk.androidtutorials.java.R;
85
import com.d4rk.androidtutorials.java.ads.AdUtils;
96
import com.d4rk.androidtutorials.java.databinding.ActivityButtonsBinding;
10-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
7+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
118
import com.d4rk.androidtutorials.java.ui.screens.android.lessons.buttons.buttons.tabs.ButtonsTabCodeFragment;
129
import com.d4rk.androidtutorials.java.ui.screens.android.lessons.buttons.buttons.tabs.ButtonsTabLayoutFragment;
1310
import com.d4rk.androidtutorials.java.ui.screens.android.lessons.common.LessonCodeTabsActivity;
@@ -17,8 +14,7 @@
1714
import me.zhanghai.android.fastscroll.FastScrollerBuilder;
1815
import java.util.Arrays;
1916

20-
public class ButtonsActivity extends UpNavigationActivity {
21-
private final Handler handler = new Handler(Looper.getMainLooper());
17+
public class ButtonsActivity extends SyntaxFabActivity {
2218
private ActivityButtonsBinding binding;
2319

2420
@Override
@@ -52,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) {
5248
binding.floatingButtonSecondary.setOnClickListener(view -> Snackbar.make(binding.getRoot(), getString(R.string.floating_button_secondary_icon) + " " + getString(R.string.snack_bar_clicked), Snackbar.LENGTH_SHORT).show());
5349
binding.floatingButtonSurface.setOnClickListener(view -> Snackbar.make(binding.getRoot(), getString(R.string.floating_button_surface_icon) + " " + getString(R.string.snack_bar_clicked), Snackbar.LENGTH_SHORT).show());
5450
binding.floatingButtonTertiary.setOnClickListener(view -> Snackbar.make(binding.getRoot(), getString(R.string.floating_button_tertiary_icon) + " " + getString(R.string.snack_bar_clicked), Snackbar.LENGTH_SHORT).show());
55-
binding.floatingButtonShowSyntax.setOnClickListener(v -> startActivity(
51+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> startActivity(
5652
LessonCodeTabsActivity.createIntent(
5753
ButtonsActivity.this,
5854
R.string.buttons,
@@ -67,13 +63,5 @@ protected void onCreate(Bundle savedInstanceState) {
6763
)
6864
)
6965
)));
70-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
71-
}
72-
73-
74-
@Override
75-
protected void onDestroy() {
76-
super.onDestroy();
77-
handler.removeCallbacksAndMessages(null);
7866
}
7967
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/buttons/image/ImageButtonsActivity.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,15 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
7-
85
import com.d4rk.androidtutorials.java.R;
96
import com.d4rk.androidtutorials.java.ads.AdUtils;
107
import com.d4rk.androidtutorials.java.databinding.ActivityImageButtonsBinding;
11-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
8+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
129
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
1310
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1411
import com.google.android.material.snackbar.Snackbar;
1512

16-
public class ImageButtonsActivity extends UpNavigationActivity {
17-
private final Handler handler = new Handler(Looper.getMainLooper());
13+
public class ImageButtonsActivity extends SyntaxFabActivity {
1814
private ActivityImageButtonsBinding binding;
1915

2016
@Override
@@ -33,19 +29,10 @@ protected void onCreate(Bundle savedInstanceState) {
3329
Snackbar.make(binding.getRoot(), R.string.snack_image_button, Snackbar.LENGTH_SHORT).show()
3430
);
3531

36-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
32+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
3733
Intent intent = new Intent(this, CodeActivity.class);
3834
intent.putExtra("lesson_name", "ImageButtons");
3935
startActivity(intent);
4036
});
41-
42-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
43-
}
44-
45-
46-
@Override
47-
protected void onDestroy() {
48-
super.onDestroy();
49-
handler.removeCallbacksAndMessages(null);
5037
}
5138
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/buttons/radio/RadioButtonsActivity.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
75
import android.util.SparseArray;
86

97
import com.d4rk.androidtutorials.java.databinding.ActivityRadioButtonsBinding;
10-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
8+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
119
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
1210
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1311
import com.google.android.material.radiobutton.MaterialRadioButton;
1412
import com.google.android.material.snackbar.Snackbar;
1513

16-
public class RadioButtonsActivity extends UpNavigationActivity {
17-
private final Handler handler = new Handler(Looper.getMainLooper());
14+
public class RadioButtonsActivity extends SyntaxFabActivity {
1815
private ActivityRadioButtonsBinding binding;
1916

2017
@Override
@@ -35,19 +32,10 @@ protected void onCreate(Bundle savedInstanceState) {
3532
}
3633
});
3734

38-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
35+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
3936
Intent intent = new Intent(this, CodeActivity.class);
4037
intent.putExtra("lesson_name", "RadioButtons");
4138
startActivity(intent);
4239
});
43-
44-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
45-
}
46-
47-
48-
@Override
49-
protected void onDestroy() {
50-
super.onDestroy();
51-
handler.removeCallbacksAndMessages(null);
5240
}
5341
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/buttons/switches/SwitchActivity.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,17 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
7-
85
import com.d4rk.androidtutorials.java.R;
96
import com.d4rk.androidtutorials.java.ads.AdUtils;
107
import com.d4rk.androidtutorials.java.databinding.ActivitySwitchBinding;
11-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
8+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
129
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
1310
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1411
import com.google.android.material.snackbar.Snackbar;
1512

1613
import me.zhanghai.android.fastscroll.FastScrollerBuilder;
1714

18-
public class SwitchActivity extends UpNavigationActivity {
19-
private final Handler handler = new Handler(Looper.getMainLooper());
15+
public class SwitchActivity extends SyntaxFabActivity {
2016
private ActivitySwitchBinding binding;
2117

2218
@Override
@@ -40,18 +36,10 @@ private void setOnClickListeners() {
4036
binding.materialSwitch.setOnClickListener(view -> Snackbar.make(binding.getRoot(), R.string.material_switch, Snackbar.LENGTH_SHORT).show());
4137
binding.switchMaterial.setOnClickListener(view -> Snackbar.make(binding.getRoot(), R.string.switch_material, Snackbar.LENGTH_SHORT).show());
4238
binding.buttonToggle.setOnClickListener(view -> Snackbar.make(binding.getRoot(), R.string.toggle_button, Snackbar.LENGTH_SHORT).show());
43-
binding.floatingButtonShowSyntax.setOnClickListener(view -> {
39+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
4440
Intent intent = new Intent(this, CodeActivity.class);
4541
intent.putExtra("lesson_name", "Switch");
4642
startActivity(intent);
4743
});
48-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
49-
}
50-
51-
52-
@Override
53-
protected void onDestroy() {
54-
super.onDestroy();
55-
handler.removeCallbacksAndMessages(null);
5644
}
5745
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/clocks/chronometer/ChronometerActivity.java

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,18 @@
22

33
import android.content.Intent;
44
import android.os.Bundle;
5-
import android.os.Handler;
6-
import android.os.Looper;
75
import android.os.SystemClock;
86

97
import androidx.annotation.Nullable;
108

119
import com.d4rk.androidtutorials.java.R;
1210
import com.d4rk.androidtutorials.java.ads.AdUtils;
1311
import com.d4rk.androidtutorials.java.databinding.ActivityChronometerBinding;
14-
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
12+
import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
1513
import com.d4rk.androidtutorials.java.ui.screens.android.CodeActivity;
1614
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
1715

18-
public class ChronometerActivity extends UpNavigationActivity {
19-
private final Handler handler = new Handler(Looper.getMainLooper());
16+
public class ChronometerActivity extends SyntaxFabActivity {
2017
private ActivityChronometerBinding binding;
2118

2219
@Override
@@ -32,21 +29,13 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
3229
binding.descriptionSection.descriptionText.setText(R.string.summary_chronometer);
3330
AdUtils.loadBanner(binding.descriptionSection.adView);
3431

35-
binding.floatingButtonShowSyntax.setOnClickListener(v -> {
32+
setupSyntaxFab(binding.floatingButtonShowSyntax, () -> {
3633
Intent intent = new Intent(this, CodeActivity.class);
3734
intent.putExtra("lesson_name", "Chronometer");
3835
startActivity(intent);
3936
});
40-
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
4137
binding.buttonStart.setOnClickListener(v -> binding.chronometer.start());
4238
binding.buttonStop.setOnClickListener(v -> binding.chronometer.stop());
4339
binding.buttonReset.setOnClickListener(v -> binding.chronometer.setBase(SystemClock.elapsedRealtime()));
4440
}
45-
46-
47-
@Override
48-
protected void onDestroy() {
49-
super.onDestroy();
50-
handler.removeCallbacksAndMessages(null);
51-
}
5241
}

0 commit comments

Comments
 (0)