Android数据绑定dataBinding的使用方法

想要使用Android数据绑定:dataBinding,大体分为6步:build.gradle中添加配置、编写bean数据类、编写Adapter适配器类、编写Adapter适配器的layout布局文件、编写java界面文件、编写java界面的layout布局文件。
本文以在Fragment中使用RecyclerView列表的界面来介绍。

1.build.gradle中添加配置:在主module的build.gradle中添加配置

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

2.编写bean数据类: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.编写Adapter适配器类: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.编写Adapter适配器的layout布局文件: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.编写java界面文件: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.编写java界面的layout布局文件: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>


 

猜你喜欢

转载自blog.csdn.net/chenzhengfeng/article/details/107066067