How to use Android data binding dataBinding

Want to use Android data binding: dataBinding, roughly divided into 6 steps: add configuration in build.gradle, write bean data class, write Adapter adapter class, write Adapter layout file, write java interface file, write java interface layout layout file.
This article introduces the interface of using RecyclerView list in Fragment.

1. Add configuration in build.gradle: add configuration in build.gradle of main module

android {
  ......
  //开启dataBinding功能支持
  dataBinding {
    enabled = true
  }
  ......
}

2. Write bean data classes: Scene, SceneViewBean

/**
 * 原始bean数据类
 */
public class Scene {
    public static final String TYPE_PLATFORM = "platform";
    public static final String TYPE_MANUALLY = "manually";
    private String id;
    private String name;
    private String type;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

/**
 * 数据绑定bean数据类
 */
public class SceneViewBean {
    private Scene scene;
    public ObservableField<String> name = new ObservableField<>();
    public ObservableBoolean isPlatform = new ObservableBoolean(false);
    public ObservableInt background = new ObservableInt(0);

    public void setArguments(Scene scene) throws Exception {
        this.scene = scene;
        name.set(scene.getName());
        switch (scene.getType()) {
            case Scene.TYPE_PLATFORM:
                isPlatform.set(true);
                background.set(R.drawable.bg_scene_platform);
                break;
            default:
                background.set(R.drawable.bg_scene_manually);
                break;
        }
    }

    public Scene getScene() {
        return scene;
    }
}

3. Write the Adapter adapter class: RecyclerViewSceneAdapter

import android.databinding.DataBindingUtil;
import com.test.databinding.AdapterSceneItemBinding; // Binding类的包路径为:app包名+.databinding.+layout文件名转为小驼峰方式+Binding

public class RecyclerViewSceneAdapter extends RecyclerView.Adapter<RecyclerViewSceneAdapter.ViewHolder> {
    private static final String TAG = RecyclerViewSceneAdapter.class.getSimpleName();
    private Context mContext;
    private List<SceneViewBean> sceneViewList;
    private int focusSelection = -1;
    private Handler handler = new Handler();

    public RecyclerViewSceneAdapter(Context context, List<SceneViewBean> sceneViewList) {
        this.mContext = context;
        this.sceneViewList = sceneViewList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(this.mContext);
        AdapterSceneItemBinding binding = DataBindingUtil.inflate(inflater, R.layout.adapter_scene_item, parent, false);
        return new ViewHolder(binding.getRoot());
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
        AdapterSceneItemBinding binding = DataBindingUtil.getBinding(holder.itemView);
        binding.setBean(sceneViewList.get(position));
        binding.executePendingBindings();
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onItemClicked(sceneViewList.get(position));
            }
        });
        holder.itemView.setTag(UIUtil.TAG_SCENE_CARD);
        if (position == focusSelection) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    holder.itemView.requestFocus();
                }
            }, 200);
            focusSelection = -1;
        }
    }

    /**
     * 支持dataBinding方式设置ImageView的resource
     * 不加此方法会导致drawable资源无法使用
     * 如果项目中有多个文件使用了dataBinding方式设置drawable资源的背景,只需要添加一次即可
     */
    @BindingAdapter({"android:background"})
    public static void setBackgroundResource(ImageView imageView, int resource) {
        imageView.setBackgroundResource(resource);
    }

    public void setFocusSelection(int focusPosition) {
        this.focusSelection = focusPosition;
    }

    private void onItemClicked(SceneViewBean sceneViewBean) {
        Scene scene = sceneViewBean.getScene();
        String id = scene.getId();
        String type = scene.getType();
        if (Scene.TYPE_MANUALLY.equals(type)) {
            Toast.makeText(mContext, "Click manually scene! id=" + id, Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, "Click platform scene! id=" + id, Toast.LENGTH_SHORT).show();
        }
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}

4. Write the layout file of the Adapter adapter: R.layout.adapter_scene_item

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <!--使用dataBinding的话,根标签要用layout-->
    <data>
        <!--类似于java文件的import导入包-->
        <import type="android.view.View" />
        <!--类似于java文件的属性定义,name表示属性名,type表示属性类型-->
        <variable
            name="bean"
            type="com.test.adapter.SceneViewBean" />
    </data>

    <RelativeLayout
        android:layout_width="@dimen/scene_card_width"
        android:layout_height="@dimen/scene_card_height"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:focusable="true">

        <ImageView
            android:id="@+id/img_select_bg"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@{bean.background}" />

        <TextView
            android:id="@+id/txt_scene_name"
            style="@style/scene_card_title_text_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="@dimen/scene_card_title_margin_left"
            android:layout_marginTop="@dimen/scene_card_title_margin_left"
            android:layout_marginRight="@dimen/scene_card_title_margin_right"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="@{bean.name}" />

        <TextView
            android:id="@+id/txt_scene_auto"
            style="@style/scene_card_auto_text_style"
            android:layout_width="@dimen/scene_card_auto_width"
            android:layout_height="@dimen/scene_card_auto_height"
            android:layout_alignParentLeft="true"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="@dimen/scene_card_title_margin_left"
            android:layout_marginBottom="@dimen/scene_card_auto_margin_bottom"
            android:background="@drawable/bg_scene_auto"
            android:gravity="center"
            android:text="@string/scene_info_auto"
            android:visibility="@{bean.isPlatform? View.VISIBLE : View.GONE}" />

    </RelativeLayout>
</layout>

5. Write java interface file: MainSceneFragment

import android.databinding.DataBindingUtil;
import com.test.databinding.FragmentMainDeviceBinding; // Binding类的包路径为:app包名+.databinding.+layout文件名转为小驼峰方式+Binding

public class MainSceneFragment extends Fragment {
    private static final String TAG = MainSceneFragment.class.getSimpleName();
    private Context mContext;
    private FragmentMainSceneBinding dataBinding;
    private DataManager dataManager;
    private List<SceneViewBean> sceneList = new ArrayList<>();
    private RecyclerViewSceneAdapter baseSceneAdapter;

    public static MainSceneFragment newInstance() {
        Bundle args = new Bundle();
        MainSceneFragment fragment = new MainSceneFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        dataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_main_scene, container, false);
        rootView = dataBinding.getRoot();
        mContext = getContext();
        this.dataManager = DataManager.getInstance();
        initData();
        return dataBinding.getRoot();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (!hidden) {
            initSceneList();
        }
    }

    public void initData() {
        initSceneData();
        initDeviceData();
    }

    private void initSceneData() {
        GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 3);
        gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
        dataBinding.recycleScene.setLayoutManager(gridLayoutManager); // Binding类中获取某个组件,也是转为小驼峰方式
        baseSceneAdapter = new RecyclerViewSceneAdapter(mContext, sceneList);
        dataBinding.recycleScene.setAdapter(baseSceneAdapter);
        dataBinding.recycleScene.setFocusable(false);
        dataBinding.recycleScene.setSelectedItemAtCentered(true);
        initSceneList();
    }

    private void initSceneList() {
        sceneList.clear();
        List<Scene> scenes = dataManager.getMainSceneList();
        for (Scene scene : scenes) {
            SceneViewBean sceneViewBean = new SceneViewBean();
            try {
                sceneViewBean.setArguments(scene);
            } catch (Exception x) {
                x.printStackTrace();
            }
            sceneList.add(sceneViewBean);
        }
        rootView.post(new Runnable() {
            @Override
            public void run() {
                baseSceneAdapter.notifyDataSetChanged();
            }
        });
    }
}

6. Write the layout file of the java interface: R.layout.fragment_main_scene

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <!--使用dataBinding的话,根标签要用layout-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/layout_scene"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginTop="@dimen/main_tab_height"
            android:orientation="vertical">

            <TextView
                style="@style/smart_scene_title_text_style"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/device_title_margin_left"
                android:layout_marginTop="@dimen/scene_title_margin_top"
                android:text="@string/smart_scene" />

            <com.open.androidtvwidget.leanback.recycle.RecyclerViewTV
                android:id="@+id/recycle_scene"
                android:layout_width="match_parent"
                android:layout_height="@dimen/scene_main_list_height"
                android:paddingLeft="@dimen/scene_main_list_padding_left"
                android:paddingTop="@dimen/scene_main_list_padding_top"
                android:paddingRight="@dimen/scene_main_list_padding_right" />
        </LinearLayout>

    </RelativeLayout>
</layout>


 

Guess you like

Origin blog.csdn.net/chenzhengfeng/article/details/107066067