Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7bf9adc

Browse files
Replace findViewById usages with view binding
1 parent 8933a43 commit 7bf9adc

File tree

24 files changed

+307
-105
lines changed

24 files changed

+307
-105
lines changed

‎app/src/main/java/com/d4rk/androidtutorials/java/ads/managers/NativeAdLoader.java‎

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.d4rk.androidtutorials.java.ads.managers;
22

33
import android.content.Context;
4+
import android.content.res.Resources;
45
import android.text.TextUtils;
56
import android.util.Log;
67
import android.view.LayoutInflater;
@@ -12,6 +13,7 @@
1213

1314
import androidx.annotation.LayoutRes;
1415
import androidx.annotation.NonNull;
16+
import androidx.viewbinding.ViewBinding;
1517

1618
import com.d4rk.androidtutorials.java.R;
1719
import com.google.android.gms.ads.AdListener;
@@ -23,6 +25,10 @@
2325
import com.google.android.gms.ads.nativead.NativeAd;
2426
import com.google.android.gms.ads.nativead.NativeAdView;
2527

28+
import java.lang.reflect.Field;
29+
import java.lang.reflect.InvocationTargetException;
30+
import java.lang.reflect.Method;
31+
2632
/**
2733
* Helper class to load AdMob native ads into a container.
2834
*/
@@ -73,7 +79,7 @@ public static void load(@NonNull Context context,
7379
adView.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
7480
container.getPaddingRight(), container.getPaddingBottom());
7581
container.setPadding(0, 0, 0, 0);
76-
populateNativeAdView(nativeAd, adView);
82+
populateNativeAdView(nativeAd, adView, layoutRes);
7783
container.removeAllViews();
7884
container.addView(adView);
7985
container.requestLayout();
@@ -92,14 +98,22 @@ public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
9298
adLoader.loadAd(adRequest);
9399
}
94100

95-
private static void populateNativeAdView(@NonNull NativeAd nativeAd, @NonNull NativeAdView adView) {
96-
MediaView mediaView = adView.findViewById(R.id.ad_media);
97-
TextView headlineView = adView.findViewById(R.id.ad_headline);
98-
TextView bodyView = adView.findViewById(R.id.ad_body);
99-
Button callToActionView = adView.findViewById(R.id.ad_call_to_action);
100-
ImageView iconView = adView.findViewById(R.id.ad_app_icon);
101-
TextView attributionView = adView.findViewById(R.id.ad_attribution);
102-
AdChoicesView adChoicesView = adView.findViewById(R.id.ad_choices);
101+
private static void populateNativeAdView(@NonNull NativeAd nativeAd,
102+
@NonNull NativeAdView adView,
103+
@LayoutRes int layoutRes) {
104+
ViewBinding binding = tryBind(adView, layoutRes);
105+
if (binding == null) {
106+
Log.w(TAG, "Could not bind native ad view for layout " + layoutRes);
107+
return;
108+
}
109+
110+
MediaView mediaView = getBindingField(binding, "adMedia", MediaView.class);
111+
TextView headlineView = getBindingField(binding, "adHeadline", TextView.class);
112+
TextView bodyView = getBindingField(binding, "adBody", TextView.class);
113+
Button callToActionView = getBindingField(binding, "adCallToAction", Button.class);
114+
ImageView iconView = getBindingField(binding, "adAppIcon", ImageView.class);
115+
TextView attributionView = getBindingField(binding, "adAttribution", TextView.class);
116+
AdChoicesView adChoicesView = getBindingField(binding, "adChoices", AdChoicesView.class);
103117

104118
if (mediaView != null) {
105119
adView.setMediaView(mediaView);
@@ -166,4 +180,53 @@ private static void populateNativeAdView(@NonNull NativeAd nativeAd, @NonNull Na
166180

167181
adView.setNativeAd(nativeAd);
168182
}
183+
184+
@androidx.annotation.Nullable
185+
private static ViewBinding tryBind(@NonNull NativeAdView adView, @LayoutRes int layoutRes) {
186+
try {
187+
String resourceName = adView.getResources().getResourceEntryName(layoutRes);
188+
String bindingName = toBindingClassName(resourceName);
189+
String fullClassName = adView.getContext().getPackageName() + ".databinding." + bindingName;
190+
Class<?> bindingClass = Class.forName(fullClassName);
191+
Method bindMethod = bindingClass.getMethod("bind", View.class);
192+
return (ViewBinding) bindMethod.invoke(null, adView);
193+
} catch (Resources.NotFoundException | ClassNotFoundException | NoSuchMethodException |
194+
IllegalAccessException | InvocationTargetException e) {
195+
Log.w(TAG, "Failed to create view binding for native ad layout", e);
196+
return null;
197+
}
198+
}
199+
200+
@androidx.annotation.Nullable
201+
private static <T> T getBindingField(@NonNull ViewBinding binding,
202+
@NonNull String fieldName,
203+
@NonNull Class<T> type) {
204+
try {
205+
Field field = binding.getClass().getField(fieldName);
206+
Object value = field.get(binding);
207+
if (type.isInstance(value)) {
208+
return type.cast(value);
209+
}
210+
} catch (NoSuchFieldException | IllegalAccessException e) {
211+
Log.w(TAG, "Unable to access binding field " + fieldName, e);
212+
}
213+
return null;
214+
}
215+
216+
@NonNull
217+
private static String toBindingClassName(@NonNull String resourceName) {
218+
StringBuilder builder = new StringBuilder(resourceName.length());
219+
boolean capitalize = true;
220+
for (int i = 0; i < resourceName.length(); i++) {
221+
char c = resourceName.charAt(i);
222+
if (c == '_') {
223+
capitalize = true;
224+
} else {
225+
builder.append(capitalize ? Character.toUpperCase(c) : c);
226+
capitalize = false;
227+
}
228+
}
229+
builder.append("Binding");
230+
return builder.toString();
231+
}
169232
}

‎app/src/main/java/com/d4rk/androidtutorials/java/ui/components/NoCodeAdFragment.java‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ protected void onBindingCreated(@NonNull T binding, @Nullable Bundle savedInstan
4747
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
4848
@Nullable Bundle savedInstanceState) {
4949
binding = inflateBinding(inflater, container);
50-
View adView = binding.getRoot().findViewById(R.id.ad_view);
51-
AdUtils.loadBanner(adView);
50+
AdUtils.loadBanner(getAdView(binding));
5251
onBindingCreated(binding, savedInstanceState);
5352
return binding.getRoot();
5453
}
5554

55+
@NonNull
56+
protected abstract View getAdView(@NonNull T binding);
57+
5658
@Override
5759
public void onDestroyView() {
5860
super.onDestroyView();

‎app/src/main/java/com/d4rk/androidtutorials/java/ui/components/navigation/BaseActivity.java‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,17 @@
33
import android.annotation.SuppressLint;
44
import android.os.Bundle;
55
import android.view.Menu;
6-
import android.view.View;
76

87
import androidx.annotation.Nullable;
98
import androidx.appcompat.app.ActionBar;
109
import androidx.appcompat.app.AppCompatActivity;
1110
import androidx.appcompat.view.menu.MenuBuilder;
1211

13-
import com.d4rk.androidtutorials.java.R;
14-
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
15-
1612
public abstract class BaseActivity extends AppCompatActivity {
1713

1814
@Override
1915
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
2016
super.onPostCreate(savedInstanceState);
21-
View container = findViewById(R.id.container);
22-
if (container != null) {
23-
EdgeToEdgeDelegate.apply(this, container);
24-
}
2517
ActionBar actionBar = getSupportActionBar();
2618
if (actionBar != null) {
2719
actionBar.setDisplayHomeAsUpEnabled(true);

‎app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/AndroidStudioFragment.java‎

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
import com.d4rk.androidtutorials.java.ads.AdUtils;
3131
import com.d4rk.androidtutorials.java.ads.views.NativeAdBannerView;
3232
import com.d4rk.androidtutorials.java.databinding.FragmentAndroidStudioBinding;
33+
import com.d4rk.androidtutorials.java.databinding.ItemPreferenceBinding;
34+
import com.d4rk.androidtutorials.java.databinding.ItemPreferenceCategoryBinding;
35+
import com.d4rk.androidtutorials.java.databinding.ItemPreferenceWidgetOpenInNewBinding;
3336
import com.google.android.gms.ads.AdListener;
3437
import com.google.android.gms.ads.LoadAdError;
3538
import com.google.android.material.button.MaterialButton;
36-
import com.google.android.material.card.MaterialCardView;
37-
import com.google.android.material.imageview.ShapeableImageView;
3839
import com.google.android.material.shape.CornerFamily;
3940
import com.google.android.material.shape.ShapeAppearanceModel;
40-
import com.google.android.material.textview.MaterialTextView;
4141

4242
import org.xmlpull.v1.XmlPullParser;
4343
import org.xmlpull.v1.XmlPullParserException;
@@ -375,13 +375,19 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
375375
adView.setNativeAdUnitId(R.string.native_ad_lessons_list_unit_id);
376376
return new AdHolder(adView);
377377
} else if (viewType == TYPE_CATEGORY) {
378-
View view = LayoutInflater.from(parent.getContext())
379-
.inflate(R.layout.item_preference_category, parent, false);
380-
return new CategoryHolder(view);
378+
ItemPreferenceCategoryBinding binding = ItemPreferenceCategoryBinding.inflate(
379+
LayoutInflater.from(parent.getContext()),
380+
parent,
381+
false
382+
);
383+
return new CategoryHolder(binding);
381384
} else {
382-
View view = LayoutInflater.from(parent.getContext())
383-
.inflate(R.layout.item_preference, parent, false);
384-
return new LessonHolder(view);
385+
ItemPreferenceBinding binding = ItemPreferenceBinding.inflate(
386+
LayoutInflater.from(parent.getContext()),
387+
parent,
388+
false
389+
);
390+
return new LessonHolder(binding);
385391
}
386392
}
387393

@@ -424,40 +430,36 @@ static class AdHolder extends RecyclerView.ViewHolder {
424430
}
425431

426432
static class LessonHolder extends RecyclerView.ViewHolder {
427-
final MaterialCardView card;
428-
final ShapeableImageView icon;
429-
final MaterialTextView title;
430-
final MaterialTextView summary;
431-
final FrameLayout widgetFrame;
432-
final MaterialButton externalButton;
433-
434-
LessonHolder(@NonNull View itemView) {
435-
super(itemView);
436-
card = (MaterialCardView) itemView;
437-
icon = itemView.findViewById(android.R.id.icon);
438-
title = itemView.findViewById(android.R.id.title);
439-
summary = itemView.findViewById(android.R.id.summary);
440-
widgetFrame = itemView.findViewById(android.R.id.widget_frame);
441-
LayoutInflater.from(itemView.getContext())
442-
.inflate(R.layout.item_preference_widget_open_in_new, widgetFrame, true);
443-
externalButton = widgetFrame.findViewById(R.id.open_in_new);
433+
private final ItemPreferenceBinding binding;
434+
private final ItemPreferenceWidgetOpenInNewBinding widgetBinding;
435+
436+
LessonHolder(@NonNull ItemPreferenceBinding binding) {
437+
super(binding.getRoot());
438+
this.binding = binding;
439+
widgetBinding = ItemPreferenceWidgetOpenInNewBinding.inflate(
440+
LayoutInflater.from(binding.getRoot().getContext()),
441+
binding.widgetFrame,
442+
true
443+
);
444444
}
445445

446446
void bind(Lesson lesson, boolean first, boolean last) {
447447
if (lesson.iconRes != 0) {
448-
icon.setImageResource(lesson.iconRes);
449-
icon.setVisibility(View.VISIBLE);
448+
binding.icon.setImageResource(lesson.iconRes);
449+
binding.icon.setVisibility(View.VISIBLE);
450450
} else {
451-
icon.setVisibility(View.GONE);
451+
binding.icon.setVisibility(View.GONE);
452452
}
453-
title.setText(lesson.title);
453+
binding.title.setText(lesson.title);
454454
if (lesson.summary != null) {
455-
summary.setText(lesson.summary);
456-
summary.setVisibility(View.VISIBLE);
455+
binding.summary.setText(lesson.summary);
456+
binding.summary.setVisibility(View.VISIBLE);
457457
} else {
458-
summary.setVisibility(View.GONE);
458+
binding.summary.setVisibility(View.GONE);
459459
}
460460
boolean showExternalButton = lesson.opensInBrowser && lesson.intent != null;
461+
FrameLayout widgetFrame = binding.widgetFrame;
462+
MaterialButton externalButton = widgetBinding.openInNew;
461463
widgetFrame.setVisibility(showExternalButton ? View.VISIBLE : View.GONE);
462464
externalButton.setVisibility(showExternalButton ? View.VISIBLE : View.GONE);
463465
externalButton.setEnabled(showExternalButton);
@@ -486,30 +488,30 @@ private void applyCorners(boolean first, boolean last) {
486488
itemView.getResources().getDisplayMetrics());
487489
float dp24 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24,
488490
itemView.getResources().getDisplayMetrics());
489-
ShapeAppearanceModel.Builder builder = card.getShapeAppearanceModel().toBuilder()
491+
ShapeAppearanceModel.Builder builder = binding.lessonCard.getShapeAppearanceModel().toBuilder()
490492
.setTopLeftCorner(CornerFamily.ROUNDED, first ? dp24 : dp4)
491493
.setTopRightCorner(CornerFamily.ROUNDED, first ? dp24 : dp4)
492494
.setBottomLeftCorner(CornerFamily.ROUNDED, last ? dp24 : dp4)
493495
.setBottomRightCorner(CornerFamily.ROUNDED, last ? dp24 : dp4);
494-
card.setShapeAppearanceModel(builder.build());
496+
binding.lessonCard.setShapeAppearanceModel(builder.build());
495497
}
496498
}
497499

498500
static class CategoryHolder extends RecyclerView.ViewHolder {
499-
final MaterialTextViewtitle;
501+
privatefinal ItemPreferenceCategoryBindingbinding;
500502

501-
CategoryHolder(@NonNull ViewitemView) {
502-
super(itemView);
503-
title = itemView.findViewById(android.R.id.title);
503+
CategoryHolder(@NonNull ItemPreferenceCategoryBindingbinding) {
504+
super(binding.getRoot());
505+
this.binding = binding;
504506
}
505507

506508
void bind(Category category) {
507509
if (category.iconRes != 0) {
508-
title.setCompoundDrawablesRelativeWithIntrinsicBounds(category.iconRes, 0, 0, 0);
510+
binding.title.setCompoundDrawablesRelativeWithIntrinsicBounds(category.iconRes, 0, 0, 0);
509511
} else {
510-
title.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
512+
binding.title.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
511513
}
512-
title.setText(category.title);
514+
binding.title.setText(category.title);
513515
}
514516
}
515517
}

‎app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/basics/sdk/AndroidSDK.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public class AndroidSDK extends UpNavigationActivity {
6464
protected void onCreate(Bundle savedInstanceState) {
6565
super.onCreate(savedInstanceState);
6666
binding = ActivityAndroidSdkBinding.inflate(getLayoutInflater());
67-
setContentView(binding.getRoot()); EdgeToEdgeDelegate.apply(this, binding.scrollView);
67+
setContentView(binding.getRoot());
68+
EdgeToEdgeDelegate.apply(this, binding.scrollView);
6869

6970
AdUtils.loadBanner(binding.adViewBottom);
7071
AdUtils.loadBanner(binding.adView);
@@ -74,7 +75,7 @@ protected void onCreate(Bundle savedInstanceState) {
7475
}
7576

7677
private void createDynamicTable() {
77-
TableLayout tableLayout = binding.cardViewTableLayout.findViewById(R.id.table_layout);
78+
TableLayout tableLayout = binding.tableLayout;
7879
for (AndroidVersion version : androidVersions) {
7980
TableRow row = new TableRow(this);
8081

‎app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/basics/shortcuts/tabs/NavigationAndSearchingShortcutsActivity.java‎

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

33
import android.os.Bundle;
44
import android.view.LayoutInflater;
5-
import android.view.View;
65
import android.view.ViewGroup;
7-
import android.widget.TextView;
86

97
import androidx.annotation.NonNull;
108
import androidx.recyclerview.widget.LinearLayoutManager;
119
import androidx.recyclerview.widget.RecyclerView;
1210

13-
import com.d4rk.androidtutorials.java.R;
1411
import com.d4rk.androidtutorials.java.ads.AdUtils;
1512
import com.d4rk.androidtutorials.java.databinding.ActivityShortcutsNavigationAndSearchingBinding;
13+
import com.d4rk.androidtutorials.java.databinding.ItemShortcutBinding;
1614
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
1715
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
1816

@@ -72,15 +70,14 @@ private static class ShortcutsAdapter extends RecyclerView.Adapter<ShortcutsAdap
7270
@NonNull
7371
@Override
7472
public ShortcutHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
75-
Viewview = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_shortcut, parent, false);
76-
return new ShortcutHolder(view);
73+
ItemShortcutBindingbinding = ItemShortcutBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
74+
return new ShortcutHolder(binding);
7775
}
7876

7977
@Override
8078
public void onBindViewHolder(@NonNull ShortcutHolder holder, int position) {
8179
Shortcut item = items.get(position);
82-
holder.key.setText(item.key);
83-
holder.description.setText(item.description);
80+
holder.bind(item);
8481
}
8582

8683
@Override
@@ -89,13 +86,16 @@ public int getItemCount() {
8986
}
9087

9188
static class ShortcutHolder extends RecyclerView.ViewHolder {
92-
final TextView key;
93-
final TextView description;
89+
private final ItemShortcutBinding binding;
9490

95-
ShortcutHolder(@NonNull View itemView) {
96-
super(itemView);
97-
key = itemView.findViewById(R.id.shortcut_key);
98-
description = itemView.findViewById(R.id.shortcut_description);
91+
ShortcutHolder(@NonNull ItemShortcutBinding binding) {
92+
super(binding.getRoot());
93+
this.binding = binding;
94+
}
95+
96+
void bind(@NonNull Shortcut shortcut) {
97+
binding.shortcutKey.setText(shortcut.key());
98+
binding.shortcutDescription.setText(shortcut.description());
9999
}
100100
}
101101
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /