수색…


비고

설정

데이터 바인딩을 사용하기 전에 build.gradle 에서 플러그인을 활성화해야합니다.

android {
    ....
    dataBinding {
        enabled = true
    }
}

참고 : 데이터 바인딩이 1.5.0 버전의 Android Gradle 플러그인에 추가되었습니다.

클래스 이름 바인딩

데이터 바인딩 플러그인은 레이아웃의 파일 이름을 파스칼 케이스로 변환하고 끝에 "바인딩"을 추가하여 바인딩 클래스 이름을 생성합니다. 따라서 item_detail_activity.xml 라는 이름의 클래스가 생성됩니다 ItemDetailActivityBinding .

자원

기본 텍스트 필드 바인딩

Gradle (모듈 : 앱) 구성

android {
    ....
    dataBinding {
        enabled = true
    }
}

데이터 모델

public class Item {
    public String name;
    public String description;

    public Item(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

레이아웃 XML

첫 번째 단계는 레이아웃을 <layout> 태그로 묶고 <data> 요소를 추가하고 데이터 모델에 <variable> 요소를 추가하는 것입니다.

그런 다음 @{model.fieldname} 사용하여 데이터 모델의 필드에 XML 속성을 바인딩 할 수 있습니다. 여기서 model 은 변수의 이름이고 fieldname 은 액세스하려는 필드입니다.

item_detail_activity.xml :

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.description}"/>

   </LinearLayout>
</layout>

바인딩으로 올바르게 구성된 각 XML 레이아웃 파일의 경우 Android Gradle 플러그인은 해당 클래스 인 바인딩을 생성합니다. 우리가 레이아웃 이름 item_detail_activity을 가지고 있기 때문에, 해당 생성 바인딩 클래스라고 ItemDetailActivityBinding .

이 바인딩은 다음과 같이 Activity에서 사용할 수 있습니다.

public class ItemDetailActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ItemDetailActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.item_detail_activity);
       Item item = new Item("Example item", "This is an example item.");
       binding.setItem(item);
    }
}

접근 자 메서드로 바인딩

모델에 비공개 메소드가있는 경우 데이터 바인딩 라이브러리를 통해 메소드의 전체 이름을 사용하지 않고도 뷰에서 액세스 할 수 있습니다.

데이터 모델

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

레이아웃 XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <!-- Since the "name" field is private on our data model,
            this binding will utilize the public getName() method instead. -->
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

   </LinearLayout>
</layout>

클래스 참조하기

데이터 모델

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

레이아웃 XML

Java에서와 마찬가지로 참조 된 클래스를 가져와야합니다.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <import type="android.view.View"/>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <!-- We reference the View class to set the visibility of this TextView -->
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"
           android:visibility="@{item.name == null ? View.VISIBLE : View.GONE"/>

   </LinearLayout>
</layout>

주 : 패키지 java.lang.* 은 시스템에 의해 자동으로 임포트됩니다. ( JVM for Java 마찬가지 임)

조각에서 데이터 바인딩

데이터 모델

public class Item {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name){
        this.name = name;
    }

}

레이아웃 XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="item" type="com.example.Item"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{item.name}"/>

   </LinearLayout>
</layout>

파편

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    FragmentTest binding = DataBindingUtil.inflate(inflater, R.layout.fragment_test, container, false);
    Item item = new Item();
    item.setName("Thomas");
    binding.setItem(item);
    return binding.getRoot();
}

내장 된 양방향 데이터 바인딩

양방향 데이터 바인딩은 다음 특성을 지원합니다.

요소 속성
AbsListView android:selectedItemPosition
CalendarView android:date
CompoundButton android:checked
DatePicker
  • android:year
  • android:month
  • android:day
EditText android:text
NumberPicker android:value
RadioGroup android:checkedButton
RatingBar android:rating
SeekBar android:progress
TabHost android:currentTab
TextView android:text
TimePicker
  • android:hour
  • android:minute
ToggleButton android:checked
Switch android:checked

용법

<layout ...>
    <data>
        <variable type="com.example.myapp.User" name="user"/>
    </data>
    <RelativeLayout ...>
        <EditText android:text="@={user.firstName}" .../>
    </RelativeLayout>
</layout>

바인딩 표현식 @={} 에는 양방향 바인딩에 필요한 추가 = 가 있습니다. 양방향 바인딩 식에서는 메서드를 사용할 수 없습니다.

RecyclerView 어댑터의 데이터 바인딩

RecyclerView 어댑터에서 데이터 바인딩을 사용할 수도 있습니다.

데이터 모델

public class Item {
    private String name;

    public String getName() {
        return name;
    }
}

XML 레이아웃

<TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@{item.name}"/>

어댑터 클래스

public class ListItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Activity host;
    private List<Item> items;

    public ListItemAdapter(Activity activity, List<Item> items) {
        this.host = activity;
        this.items = items;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // inflate layout and retrieve binding
        ListItemBinding binding = DataBindingUtil.inflate(host.getLayoutInflater(),
                R.layout.list_item, parent, false);

        return new ItemViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Item item = items.get(position);

        ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
        itemViewHolder.bindItem(item);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    private static class ItemViewHolder extends RecyclerView.ViewHolder {
        ListItemBinding binding;

        ItemViewHolder(ListItemBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        void bindItem(Item item) {
            binding.setItem(item);
            binding.executePendingBindings();
        }
    }
}

Binding으로 Listener를 클릭하십시오.

clickHandler 용 인터페이스 만들기

public interface ClickHandler {
    public void onButtonClick(View v);
}

레이아웃 XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="handler"
            type="com.example.ClickHandler"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="click me"
            android:onClick="@{handler.onButtonClick}"/>
    </RelativeLayout>
</layout>

활동에서 이벤트 처리

public class MainActivity extends Activity implements ClickHandler {

    private ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setHandler(this);
    }

    @Override
    public void onButtonClick(View v) {
        Toast.makeText(context,"Button clicked",Toast.LENGTH_LONG).show();
    }
}

람다 표현식을 사용한 맞춤 이벤트

인터페이스 정의

public interface ClickHandler {
    public void onButtonClick(User user);
}

Model 클래스 만들기

public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

레이아웃 XML

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="handler"
            type="com.example.ClickHandler"/>

        <variable
            name="user"
            type="com.example.User"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:onClick="@{() -> handler.onButtonClick(user)}"/>
    </RelativeLayout>
</layout>

활동 코드 :

public class MainActivity extends Activity implements ClickHandler {

    private ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setUser(new User("DataBinding User"));
        binding.setHandler(this);
    }

    @Override
    public void onButtonClick(User user) {
        Toast.makeText(MainActivity.this,"Welcome " + user.getName(),Toast.LENGTH_LONG).show();
    }
}

XML 코드에서는 사용할 수 없지만 Java 코드에서 설정할 수있는 일부 뷰 수신기의 경우 사용자 정의 바인딩을 사용하여 바인딩 할 수 있습니다.

사용자 정의 클래스

public class BindingUtil {
    @BindingAdapter({"bind:autoAdapter"})
    public static void setAdapter(AutoCompleteTextView view, ArrayAdapter<String> pArrayAdapter) {
        view.setAdapter(pArrayAdapter);
    }
    @BindingAdapter({"bind:onKeyListener"})
    public static void setOnKeyListener(AutoCompleteTextView view , View.OnKeyListener pOnKeyListener)
    {
        view.setOnKeyListener(pOnKeyListener);
    }
}

핸들러 클래스

public class Handler extends BaseObservable {
    private ArrayAdapter<String> roleAdapter;
       
    public ArrayAdapter<String> getRoleAdapter() {
        return roleAdapter;
    }
    public void setRoleAdapter(ArrayAdapter<String> pRoleAdapter) {
        roleAdapter = pRoleAdapter;
    }
}

XML

<layout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/tools" >

    <data>
        <variable
            name="handler"
            type="com.example.Handler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <AutoCompleteTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:singleLine="true"
            bind:autoAdapter="@{handler.roleAdapter}" />

    </LinearLayout>
</layout>

데이터 바인딩의 기본값

미리보기 창에는 데이터 바인딩 표현식에 대한 기본값이 표시됩니다.

예 :

android:layout_height="@{@dimen/main_layout_height, default=wrap_content}"

디자인하는 동안 wrap_content 를 취하고 미리보기 창에서 wrap_content 역할을합니다.

또 다른 예는 다음과 같습니다.

android:text="@{user.name, default=`Preview Text`}"

미리보기 창에 미리 Preview Text 가 표시되지만 장치 / 에뮬레이터에서 실행하면 실제로 바인딩 된 텍스트가 표시됩니다

사용자 정의 변수를 사용한 데이터 바인딩 (int, boolean)

때로는 단일 값을 기반으로보기 숨기기 / 표시 같은 기본 작업을 수행해야합니다. 단 하나의 변수에 대해서는 모델을 만들 수 없거나 모델을 만드는 것이 좋지 않습니다. DataBinding은 이러한 작업을 수행하기위한 기본 데이터 유형을 지원합니다.

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="android.view.View" />

        <variable
            name="selected"
            type="Boolean" />

    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World"
            android:visibility="@{selected ? View.VISIBLE : View.GONE}" />

    </RelativeLayout>
</layout>

그 값을 Java 클래스에서 설정합니다.

binding.setSelected(true);

대화 상자의 데이터 바인딩

public void doSomething() {
    DialogTestBinding binding = DataBindingUtil
            .inflate(LayoutInflater.from(context), R.layout.dialog_test, null, false);

    Dialog dialog = new Dialog(context);
    dialog.setContentView(binding.getRoot());
    dialog.show();
}

BindingAdapter에서 위젯을 참조로 전달합니다.

레이아웃 XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
   
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

        <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        app:imageUrl="@{url}"
        app:progressbar="@{progressBar}"/>

   </LinearLayout>
</layout>

BindingAdapter 메서드

@BindingAdapter({"imageUrl","progressbar"})
public static void loadImage(ImageView view, String imageUrl, ProgressBar progressBar){
    Glide.with(view.getContext()).load(imageUrl)
                        .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        progressBar.setVisibility(View.GONE);
                        return false;
                    }
                }).into(view);
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow