Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2020 Droid Knights - FindViewBindings

Veronikapj
September 05, 2020

2020 Droid Knights - FindViewBindings

xml 뷰를 코드에 바인딩 하는 방법을 비교합니다. FindViewById, Butter Knife, Kotlin Android Extensions Plug in, Data Binding, View Binding 을 다루었습니다.

Veronikapj

September 05, 2020
Tweet

More Decks by Veronikapj

Other Decks in Programming

Transcript

  1. GJOE7JFX#Z*E #VUUPO BOESPJEJEt! JECVUUPO@PL Button okButton = findViewById(R.id.button_ok) public final

    class R { /* ... */ public static final int button_ok = 0x7f090133; /* ... */ } )PXUP6TF
  2. GJOE7JFX#Z*E 1SPCMFNT$BTUJOH Button okButton = (Button)findViewById(R.id.button_ok) "1* "1* Button okButton

    = findViewById(R.id.button_ok) ImageView okButton = findViewById(R.id.button_ok) $MBTT$BTU&YDFQUJPO #VUUPO BOESPJEJEt! JECVUUPO@PL
  3. GJOE7JFX#Z*E 1SPCMFNT$BTUJOH Button okButton = (Button)findViewById(R.id.button_ok) @Nullable public final View

    findViewById(@IdRes int id) { if (id < 0) { return null; } return findViewTraversal(id); } "1* 7JFXKBWB
  4. GJOE7JFX#Z*E 1SPCMFNT$BTUJOH @Nullable public final <T extends View> T findViewById(@IdRes

    int id) { if (id == NO_ID) { return null; } return findViewTraversal(id); } "1* Button okButton = findViewById(R.id.button_ok) 7JFXKBWB
  5. GJOE7JFX#Z*E @Nullable public final <T extends View> T findViewById(@IdRes int

    id) { if (id == NO_ID) { return null; } return findViewTraversal(id); } "1* Button okButton = findViewById(R.id.button_ok) 7JFXKBWB 1SPCMFNT/VMM1PJOUFS&YDFQUJPO /VMM1PJOUFS&YDFQUJPO
  6. #PJMFSQMBUFDPEF class SomethingView @JvmOverloads constructor( context: Context, attrs: AttributeSet? =

    null, defStyleAttr: Int = 0 ) : RelativeLayout(context, attrs, defStyleAttr) { private val itemGroup: LinearLayout private val itemGroupTitle: TextView private val someText: ImageView private val someText2: TextView private val someImage: ImageView private val someImage2: ImageView private val itemImage: ImageView private val itemImage2: ImageView /* .... */ init { View.inflate(context, R.layout.some_view, this) itemGroup = findViewById(R.id.item_group) itemGroupTitle = findViewById(R.id.item_group_title) someText = findViewById(R.id.some_text) someText2 = findViewById(R.id.some_text2) someImage = findViewById(R.id.some_image) someImage2 = findViewById(R.id.some_image2) itemImage = findViewById(R.id.item_image) itemImage2 = findViewById(R.id.item_image2) /* ... */ } } GJOE7JFX#Z*E 1SPCMFNT
  7. GJOE7JFX#Z*E )JEEFO$PTUT @Nullable public final <T extends View> T findViewById(@IdRes

    int id) { if (id == NO_ID) { return null; } return findViewTraversal(id); } protected <T extends View> T findViewTraversal(@IdRes int id) { if (id == mID) { return (T) this; } } View.java return null;
  8. 7JFX(SPVQKBWB @Override protected <T extends View> T findViewTraversal(@IdRes int id)

    { if (id == mID) { return (T) this; } final View[] where = mChildren; final int len = mChildrenCount; for (int i = 0; i < len; i++) { View v = where[i]; if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) { v = v.findViewById(id); if (v != null) { return (T) v; } } } return null; }
  9. 7JFX(SPVQKBWB @Override protected <T extends View> T findViewTraversal(@IdRes int id)

    { if (id == mID) { return (T) this; } final View[] where = mChildren; final int len = mChildrenCount; for (int i = 0; i < len; i++) { View v = where[i]; if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) { v = v.findViewById(id); if (v != null) { return (T) v; } } } return null; } 1PPSQFSGPSNBODF
  10. #VUUFS,OJGF )PXJU8PSLT ButterKnife.bind(this); public class SimpleActivity_ViewBinding implements Unbinder { /*

    ... */ view = Utils.findRequiredView(source, R.id.hello, "field 'hello', method 'sayHello', and method 'sayGetOffMe'"); target.hello = Utils.castView(view, R.id.hello, "field 'hello'", Button.class); } /FX+BWB$MBTT0SJHJOBM$MBTT@7JFX#JOEJOH
  11. #VUUFS,OJGF )PXJU8PSLT view = Utils.findRequiredView(source, R.id.hello, "field 'hello', method 'sayHello',

    and method 'sayGetOffMe'") public static View findRequiredView(View source, @IdRes int id, String who) { View view = source.findViewById(id); if (view != null) { return view; } /* … */ }
  12. ,PUMJO"OESPJE&YUFOTJPOT )PXUP6TF <TextView android:id=“@+id/textViewFirst"/> import kotlinx.android.synthetic.main.fragment_first.* import kotlinx.android.synthetic.main.fragment_first.view.* textViewFirst.text =

    "Hello, World" import kotlinx.android.synthetic.{product flavor}.{layout}.* apply plugin: 'kotlin-android-extensions' CVJMEHSBEMF main.fragment_first kotlinx.android.synthetic 4ZOUIFUJD1SPQFSUZ
  13. ,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT private HashMap _$_findViewCache; public View _$_findCachedViewById(int var1) {

    if (this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(var1); if (var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; }
  14. ,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT private HashMap _$_findViewCache; public View _$_findCachedViewById(int var1) {

    if (this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(var1); if (var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; }
  15. ,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT 'SBHNFOU public void onDestroyView() { super.onDestroyView(); this._$_clearFindViewByIdCache(); }

    public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } }
  16. ,PUMJO"OESPJE&YUFOTJPOT $BVUJPO fun Fragment.b() { textViewFirst.text = "Hidden view" textViewFirst.visibility

    = View.INVISIBLE } 6TFE 7JFX$BDIF /PU6TFE 7JFX$BDIF <TextView android:id=“@+id/textViewFirst"/> class FirstFragment : Fragment() fun FirstFragment.a() { textViewFirst.text = "Hidden view" textViewFirst.visibility = View.INVISIBLE } import kotlinx.android.synthetic.main.activity_main.*
  17. ,PUMJO"OESPJE&YUFOTJPOT $BVUJPO fun FirstFragment.a() { textViewFirst.text = "Hidden view" textViewFirst.visibility

    = View.INVISIBLE } 6TFE7JFX$BDIF public final void a(@NotNull FirstFragment $this$a) { . . . TextView var10000 = (TextView)$this$a._$_findCachedViewById(id.textViewFirst) . . . var10000 = (TextView)$this$a._$_findCachedViewById(id.textViewFirst) . . . var10000.setVisibility(4) } %FDPNQJMF
  18. ,PUMJO"OESPJE&YUFOTJPOT $BVUJPO fun Fragment.b() { textViewFirst.text = "Hidden view" textViewFirst.visibility

    = View.INVISIBLE } /PU6TFE7JFX$BDIF public final void b(@NotNull Fragment $this$b) { TextView var10000 = (TextView)$this$b.getView().findViewById(id.textViewFirst); . . . var10000.setText((CharSequence)"Hidden view"); var10000 = (TextView)$this$b.getView().findViewById(id.textViewFirst); . . . var10000.setVisibility(4); } %FDPNQJMF
  19. ,PUMJO"OESPJE&YUFOTJPOT $BVUJPO <TextView android:id=“@+id/textViewFirst"/> class FirstFragment : Fragment() fun FirstFragment.a()

    { textViewFirst.text = "Hidden view" textViewFirst.visibility = View.INVISIBLE } fun Fragment.b() { textViewFirst.text = "Hidden view" textViewFirst.visibility = View.INVISIBLE } 6TFE 7JFX$BDIF /PU6TFE 7JFX$BDIF import kotlinx.android.synthetic.main.activity_main.*
  20. class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .)

    : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } import kotlinx.android.synthetic.main.layout_custom.view.* class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .) : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } ,PUMJO"OESPJE&YUFOTJPOT
  21. ,PUMJO"OESPJE&YUFOTJPOT $BVUJPO public void onBindViewHolder(@NotNull ViewHolder holder, int position) {

    if (holder instanceof SearchAdapter.CustomViewHolder) { View var10000 = holder.itemView; TextView var8 = (TextView)var10000.findViewById(id.itemTitle1); var8.setText((CharSequence)”hello1"); View var3 = holder.itemView; var8 = (TextView)var3.findViewById(id.itemTitle2); var8.setText((CharSequence)"hello2"); } } %FDPNQJMF import kotlinx.android.synthetic.main.layout_custom.view.* public void onBindViewHolder(@NotNull ViewHolder holder, int position) { if (holder instanceof SearchAdapter.CustomViewHolder) { View var10000 = holder.itemView; var8.setText((CharSequence)”hello1"); View var3 = holder.itemView; var8.setText((CharSequence)"hello2"); } }
  22. class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .)

    : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } import kotlinx.android.synthetic.main.layout_custom.view.* class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .) : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } holder: RecyclerView.ViewHolder holder.itemView holder.itemView ,PUMJO"OESPJE&YUFOTJPOT
  23. class SearchAdapter : RecyclerView.Adapter<CustomViewHolder>() { override fun onCreateViewHolder(. . .)

    : CustomViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: CustomViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } import kotlinx.android.synthetic.main.layout_custom.view.* if (holder is CustomViewHolder) { } } ,PUMJO"OESPJE&YUFOTJPOT
  24. class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .)

    : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } class CustomViewHolder(private val customLayout: CustomLayout) : RecyclerView.ViewHolder(customLayout) } import kotlinx.android.synthetic.main.layout_custom.view.* class SearchAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(. . .) : RecyclerView.ViewHolder { return CustomViewHolder(CustomLayout(parent.context)) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is CustomViewHolder) { holder.itemView.itemTitle1.text = "hello1" with(holder.itemView) { itemTitle2.text = “hello2" } } } holder.itemView holder.itemView customLayout: CustomLayout holder.customLayout.itemTitle1.text = "hello1" with(holder.customLayout) { itemTitle2.text = “hello2" } ,PUMJO"OESPJE&YUFOTJPOT
  25. %BUB#JOEJOH 7JFX#JOEJOH )PXUP6TF CVJMEHSBEMF %BUB#JOEJOH 7JFX#JOEJOH Gradle 3.6 dataBinding {

    enabled = true } viewBinding { enabled = true } Gradle 4.0 buildFeatures { dataBinding = true } buildFeatures { viewBinding = true }
  26. %BUB#JOEJOH )PXUP6TF 4BNQMF"DUJWJUZYNM class SampleActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding : ActivitySampleBinding = DataBindingUtil.setContentView(this, R.layout.activity_sample) binding.dataBindingFirst.text = "hello data binding!” } } ActivitySampleBinding = LayoutFileName + Binding = activity_sample.xml + Binding ( android:id=“@+id/data_binding_first” ) dataBindingFirst
  27. 7JFX#JOEJOH )PXUP6TF class SampleViewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) val binding = ActivityViewSampleBinding.inflate(layoutInflater) setContentView(binding.root) } } 4BNQMF7JFX"DUJWJUZYNM $BVUJPO /P 3MBZPVUBDUJWJUZ@WJFX@TBNQMF binding.viewBindingFirst.text = "hello view binding!"
  28. 7JFX#JOEJOH $BVUJPO 'SBHNFOU private var _binding: ResultProfileBinding? = null private

    val binding get() = _binding!! override fun onCreateView(. . .): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null } _binding = ResultProfileBinding.inflate(inflater, container, false)
  29. %BUB#JOEJOH )PXJUXPSLT public abstract class ActivitySampleBinding extends ViewDataBinding { @NonNull

    public final TextView dataBindingFirst; protected ActivitySampleBinding( . . . TextView dataBindingFirst) { super(. . .); this.dataBindingFirst = dataBindingFirst; } @NonNull public static ActivitySampleBinding inflate(. . .) { return inflate(. . ., DataBindingUtil.getDefaultComponent()); } } val binding : ActivitySampleBinding = DataBindingUtil.setContentView(this, R.layout.activity_sample)
  30. %BUB#JOEJOH )PXJUXPSLT <Layout layout="activity_sample" filePath=“app/src/main/res/layout/activity_sample.xml" . . . rootNodeType="android.widget.LinearLayout"> <Targets>

    <Target tag="layout/activity_sample_0" view="LinearLayout"> <Expressions/> <location startLine="2" startOffset="4" endLine="14" endOffset="18"/> </Target> <Target id="@+id/data_binding_first" view="TextView"> <Expressions/> <location startLine="8" startOffset="8" endLine="13" endOffset="13"/> </Target> </Targets> </Layout> <Target tag=“layout/activity_sample_0”> <Target id=“@+id/data_binding_first"> BDUJWJUZ@TBNQMFYNMBDUJWJUZ@TBNQMFMBZPVUYNM
  31. %BUB#JOEJOH )PXJUXPSLT <Target tag=“layout/activity_sample_0”> BDUJWJUZ@TBNQMFMBZPVUYNM @Override public ViewDataBinding getDataBinder(DataBindingComponent component,

    View view, int layoutId) { final Object tag = view.getTag(); . . . switch(localizedLayoutId) { case LAYOUT_ACTIVITYSAMPLE: { if ("layout/activity_sample_0".equals(tag)) return new ActivitySampleBindingImpl(component, view); . . . } } %BUB#JOEFS.BQQFS*NQMDMBTT
  32. public class ActivitySampleBindingImpl extends ActivitySampleBinding { @Nullable 
 private static

    final SparseIntArray sViewsWithIds; static { . . . sViewsWithIds = new android.util.SparseIntArray(); sViewsWithIds.put(R.id.data_binding_first, 1); } public ActivitySampleBindingImpl( @Nullable ..DataBindingComponent bindingComponent, @NonNull View root) { this(bindingComponent, root, mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds)); } } %BUB#JOEJOH <Target id=“@+id/data_binding_first"> BDUJWJUZ@TBNQMFYNMBDUJWJUZ@TBNQMFMBZPVUYNM
  33. private static void mapBindings(. . .) { . . .

    Object objTag = view.getTag(); final String tag = (objTag instanceof String) ? (String) objTag : null; boolean isBound = false; if (isRoot && tag != null && tag.startsWith("layout")) { . . . } else if (tag != null && tag.startsWith(BINDING_TAG_PREFIX)) { . . . if (bindings[tagIndex] == null) { bindings[tagIndex] = view; } isBound = true; } else { . . . } if (!isBound) { final int id = view.getId(); if (id > 0) { int index; if (viewsWithIds != null && (index = viewsWithIds.get(id, -1)) >= 0 && bindings[index] == null) { bindings[index] = view; } } } } %BUB#JOEJOH <Target id=“@+id/data_binding_first" > "DUJWJUZ@TBNQMFMBZPVUYNM
  34. private static void mapBindings(. . .) { . . .

    Object objTag = view.getTag(); final String tag = (objTag instanceof String) ? (String) objTag : null; boolean isBound = false; if (isRoot && tag != null && tag.startsWith("layout")) { . . . } else if (tag != null && tag.startsWith(BINDING_TAG_PREFIX)) { . . . if (bindings[tagIndex] == null) { bindings[tagIndex] = view; } isBound = true; } else { . . . } if (!isBound) { final int id = view.getId(); if (id > 0) { int index; if (viewsWithIds != null && (index = viewsWithIds.get(id, -1)) >= 0 && bindings[index] == null) { bindings[index] = view; } } } } %BUB#JOEJOH <Target id=“@+id/data_binding_first" > "DUJWJUZ@TBNQMFMBZPVUYNM
  35. %BUB#JOEJOH )PXJUXPSLT <Target id=“@+id/data_binding_first" > tag=“binding_1”> BDUJWJUZ@TBNQMFMBZPVUYNM BDUJWJUZ@TBNQMFYNM <layout> <data>

    <variable name=“textValue" type="String" /> </data> <TextView android:id=“@+id/data_binding_first” > </layout> android:text=“@{textValue}" />
  36. 7JFX#JOEJOH )PXJUXPSLT public final class ActivityViewSampleBinding implements ViewBinding { @NonNull

    public final TextView viewBindingFirst; ... @NonNull public static ActivityViewSampleBinding bind(@NonNull View rootView) { ... missingId: { id = R.id.data_binding_first; TextView viewBindingFirst = rootView.findViewById(id); if (dataBindingFirst == null) { break missingId; } return new ActivityViewSampleBinding( (LinearLayout) rootView, dataBindingFirst); } )); } } ... @NonNull public static ActivityViewSampleBinding bind(@NonNull View rootView) { ... missingId: { id = R.id.data_binding_first; if (dataBindingFirst == null) { break missingId; } return new ActivityViewSampleBinding( (LinearLayout) rootView, dataBindingFirst); } )); }