Slide 1

Slide 1 text

4QFBLFSM FindViewBindings, 뷰를 바인딩하는 모든 방법. ߓ೙઱

Slide 2

Slide 2 text

*OUSP GJOE7JFX#Z*E #VUUFS,OJGF ,PUMJO"OESPJE&YUFOTJPOT %BUB#JOEJOH 7JFX#JOEJOH

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

GJOE7JFX#Z*E @Nullable public final 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

Slide 8

Slide 8 text

#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

Slide 9

Slide 9 text

GJOE7JFX#Z*E )JEEFO$PTUT @Nullable public final T findViewById(@IdRes int id) { if (id == NO_ID) { return null; } return findViewTraversal(id); } protected T findViewTraversal(@IdRes int id) { if (id == mID) { return (T) this; } } View.java return null;

Slide 10

Slide 10 text

7JFX(SPVQKBWB @Override protected 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; }

Slide 11

Slide 11 text

7JFX(SPVQKBWB @Override protected 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

Slide 12

Slide 12 text

#VUUFS,OJGF )PXUP6TF IUUQKBLFXIBSUPOHJUIVCJPCVUUFSLOJGF %FQSFDBUFE This tool is now deprecated. Please switch to view binding

Slide 13

Slide 13 text

#VUUFS,OJGF )PXUP6TF @BindView(R.id.hello) Button helloButton; #VUUPO BOESPJEJEt!JEIFMMPu ButterKnife.bind(this); helloButton.setText(sayHello);

Slide 14

Slide 14 text

#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

Slide 15

Slide 15 text

#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; } /* … */ }

Slide 16

Slide 16 text

,PUMJO"OESPJE&YUFOTJPOT )PXUP6TF 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

Slide 17

Slide 17 text

,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT 5PPMTª,PUMJO 4IPX,PUMJO#ZUF$PEF #ZUFDPEF%FDPNQJMF

Slide 18

Slide 18 text

,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT TextView var10000 = (TextView)this._$_findCachedViewById(id.textViewFirst) Intrinsics.checkExpressionValueIsNotNull(var10000, "textViewFirst") var10000.setText((CharSequence)"Hello, World") import kotlinx.android.synthetic.main.fragment_first.* textViewFirst.text = "Hello, World" 5PPMTª,PUMJO 4IPX,PUMJO#ZUF$PEF #ZUFDPEF%FDPNQJMF

Slide 19

Slide 19 text

,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; }

Slide 20

Slide 20 text

,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; }

Slide 21

Slide 21 text

,PUMJO"OESPJE&YUFOTJPOT )PXJU8PSLT 'SBHNFOU public void onDestroyView() { super.onDestroyView(); this._$_clearFindViewByIdCache(); } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } }

Slide 22

Slide 22 text

'SBHNFOU"EEFE 'SBHNFOU%FTUSPZFE 'SBHNFOU7JFX$SFBUFE 'SBHNFOU7JFX%FTUSPZFE 'SBHNFOU -JGF$ZDMF 'SBHNFOU 7JFX-JGF$ZDMF

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

,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

Slide 25

Slide 25 text

,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

Slide 26

Slide 26 text

,PUMJO"OESPJE&YUFOTJPOT $BVUJPO 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.*

Slide 27

Slide 27 text

,PUMJO"OESPJE&YUFOTJPOT $BVUJPO $VTUPN-BZPVU MBZPVU@DVTUPNYNM

Slide 28

Slide 28 text

class SearchAdapter : RecyclerView.Adapter() { 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() { 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

Slide 29

Slide 29 text

,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"); } }

Slide 30

Slide 30 text

class SearchAdapter : RecyclerView.Adapter() { 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() { 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

Slide 31

Slide 31 text

class SearchAdapter : RecyclerView.Adapter() { 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

Slide 32

Slide 32 text

class SearchAdapter : RecyclerView.Adapter() { 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() { 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

Slide 33

Slide 33 text

%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 }

Slide 34

Slide 34 text

%BUB#JOEJOH )PXUP6TF BDUJWJUZ@TBNQMFYNM &MFNFOUTBSFXSBQQFEJOBMBZPVUUBH &YQSFTTJPOTBSFEFGJOFEJOTJEFBEBUB

Slide 35

Slide 35 text

%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

Slide 36

Slide 36 text

7JFX#JOEJOH )PXUP6TF BDUJWJUZ@WJFX@TBNQMFYNM tools:viewBindingIgnore=“true" >

Slide 37

Slide 37 text

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!"

Slide 38

Slide 38 text

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)

Slide 39

Slide 39 text

'SBHNFOU"EEFE 'SBHNFOU%FTUSPZFE 'SBHNFOU7JFX$SFBUFE 'SBHNFOU7JFX%FTUSPZFE 'SBHNFOU -JGF$ZDMF 'SBHNFOU 7JFX-JGF$ZDMF

Slide 40

Slide 40 text

%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)

Slide 41

Slide 41 text

%BUB#JOEJOH )PXJUXPSLT BDUJWJUZ@TBNQMFYNMBDUJWJUZ@TBNQMFMBZPVUYNM

Slide 42

Slide 42 text

%BUB#JOEJOH )PXJUXPSLT 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

Slide 43

Slide 43 text

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 BDUJWJUZ@TBNQMFYNMBDUJWJUZ@TBNQMFMBZPVUYNM

Slide 44

Slide 44 text

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 "DUJWJUZ@TBNQMFMBZPVUYNM

Slide 45

Slide 45 text

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 "DUJWJUZ@TBNQMFMBZPVUYNM

Slide 46

Slide 46 text

%BUB#JOEJOH )PXJUXPSLT tag=“binding_1”> BDUJWJUZ@TBNQMFMBZPVUYNM BDUJWJUZ@TBNQMFYNM android:text=“@{textValue}" />

Slide 47

Slide 47 text

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); } )); }

Slide 48

Slide 48 text

&OE GJOE7JFX#Z*E )JEEFO$PTUT &YDFQUJPOT #VUUFS,OJGF "OOPUBUJPO1SPDFTTPS GJOE7JFXCZ*E ,PUMJO"OESPJE&YUFOTJPOT 7JFX$BDIJOH GJOE7JFXCZ*E %BUB#JOEJOH "OOPUBUJPO Processor, Tag 7JFX#JOEJOH GJOE7JFX#Z*E

Slide 49

Slide 49 text

Thank you