資料中介者:DataMediator, (ButterKnife最佳拍檔)

LightSun發表於2017-11-14

View基本屬性繫結

/**
 * test data-binding of view: setBackground, setBackgroundColor,setBackgroundResource.setEnable . etc.
 * Created by heaven7 on 2017/9/24.
 */
public class TestViewBindActivity extends BaseActivity {

    @BindView(R.id.v_enable)@BindEnable("enable")
    View mV_enable;

    @BindView(R.id.v_bg) @BindBackground("background")
    View mV_bg;

    @BindView(R.id.v_bg_color)@BindBackgroundColor("backgroundColor")
    View mV_bg_color;

    @BindView(R.id.v_bg_res)@BindBackgroundRes("backgroundRes")
    View mV_bg_res;

    @BindView(R.id.v_visibility)@BindVisibility("visible")
    View mV_visibility;

    private ResHelper mHelper = new ResHelper();
    private Binder<ViewBind> binder;

    @Override
    protected int getLayoutId() {
        return R.layout.ac_test_view_bind;
    }
    @Override
    protected void onInit(Context context, Bundle savedInstanceState) {
        mHelper.init(context);

        final ViewBind data = DataMediatorFactory.createData(ViewBind.class);
        //bind data.
        binder = DataMediatorFactory.bind(this, data);
    }

    @OnClick(R.id.bt_change_bg)
    public void onClickChangeBg(View v){
        //改變背景(drawable)
        binder.getDataProxy().setBackground(mHelper.toggleDrawable());
    }

    @OnClick(R.id.bt_change_bg_color)
    public void onClickChangeBgColor(View v){
        //改變背景(color)
        binder.getDataProxy().setBackgroundColor(mHelper.toggleColor());
    }

    @OnClick(R.id.bt_change_bg_res)
    public void onClickChangeBgRes(View v){
        //改變背景(resource id)
        binder.getDataProxy().setBackgroundRes(mHelper.toggleRes());
    }

    @OnClick(R.id.bt_change_enable)
    public void onClickChangeEnable(View v){
        //改變enable 狀態
        binder.getDataProxy().setEnable(!binder.getData().isEnable());
    }
    @OnClick(R.id.bt_change_visibility)
    public void onClickChangeVisibility(View v){
        binder.getDataProxy().setVisible(!binder.getDataProxy().isVisible());
    }

    @Override
    protected void onDestroy() {
        binder.unbindAll();
        super.onDestroy();
    }

}複製程式碼

下面是 adapter繫結資料.

/**
 * test data-binding in adapter. 所有的@BindView是用的 butterKnife。
 * Created by heaven7 on 2017/11/9 0009.
 */
public class TestDatabindingAdapter extends BaseActivity {

    private static final String TAG = "TD adapter";
    private static final Random sRan = new Random();

    @BindView(R.id.rv)
    RecyclerView mRv;

    protected InternalAdapter mAdapter;

    @Override
    protected int getLayoutId() {
        return R.layout.ac_test_databinding_adapter;
    }

    @Override
    protected void onInit(Context context, Bundle savedInstanceState) {
        mRv.setLayoutManager(new LinearLayoutManager(context));
        mRv.setAdapter(mAdapter = new InternalAdapter(createItems()));
    }

    //random remove item
    @OnClick(R.id.bt_remove)
    public void onClickRemove(View v){
        AdapterItemManager<Student> manager = mAdapter.getItemManager();
        int itemCount = manager.getItemSize();
        final int index = new Random().nextInt(itemCount - 1);
        Logger.i(TAG, "onClickRemove","index = " + index);
        manager.removeItemAt(index);
    }
    @OnClick(R.id.bt_add)
    public void onClickAdd(View v){
        AdapterItemManager<Student> manager = mAdapter.getItemManager();
        int itemCount = manager.getItemSize();
        final int index = new Random().nextInt(itemCount - 1);
        Logger.i(TAG, "onClickAdd","index = " + index);
        manager.addItem(index, createItem().setAge(1));
    }

    public static List<Student> createItems() {
        sIndex = 0;
        List<Student> list = new ArrayList<>();
        //just mock data
        final int count = 20;
        for (int i =0 ; i< count ; i++){
            list.add(createItem());
        }
        return list;
    }
    public static Student createItem(){
        Student data = DataMediatorFactory.createData(Student.class);
        data.setAge(sIndex ++ );
        data.setName("google__" + sRan.nextInt(100));
        return data;
    }

    private static int sIndex = 0;

    public static class InternalAdapter extends DataBindingRecyclerAdapter<Student> {

        public InternalAdapter(List<Student> mDatas) {
            super(mDatas, true);
        }
        @Override
        public DataBindingViewHolder<Student> onCreateViewHolderImpl(ViewGroup parent, int layoutId) {
            return new InnerViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(layoutId, parent, false));
        }
        @Override
        protected int getItemLayoutId(int position, Student student) {
            return R.layout.item_test_recycler_list;
        }
    }
    public static class InnerViewHolder extends DataBindingRecyclerAdapter.DataBindingViewHolder<Student>{

        @BindView(R.id.tv_name) @BindText("name")
        TextView mTv_name;

        @BindView(R.id.tv_age) @BindText("age")
        TextView mTv_age;

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

        @Override
        protected void onPreCreateDataBinding(View itemView) {
            ButterKnife.bind(this, itemView);
        }

        @OnClick(R.id.tv_name)
        public void onClickName(View v){
            //here just toast
            Toast.makeText(v.getContext(), "onClickName is called, pos = "
                    + getAdapterPosition2(), Toast.LENGTH_SHORT).show();
        }
        @OnClick(R.id.tv_age)
        public void onClickAge(View v){
            //here just toast
            Toast.makeText(v.getContext(), "onClickAge is called, pos = "
                    + getAdapterPosition2(), Toast.LENGTH_SHORT).show();
        }
        @OnClick(R.id.bt_change_item)
        public void onClickChangeItem(View v){
            final int pos = getAdapterPosition2();
            getDataProxy()
                    .setAge((int) (System.currentTimeMillis() % 99))
                    .setId(pos)
                    .setName("google+__" + pos);
            //Note: no need notifyItemChanged here.
        }
    }
}複製程式碼

adapter繫結資料 , 用GridLayoutManger 並且新增header 示例.

/**
 * data-binding adapter with header.
 * Created by heaven7 on 2017/11/11.
 */
//TestDatabindingAdapter 請看上面
public class DataBindingAdapterWithHeader extends TestDatabindingAdapter {

    @BindView(R.id.rv)
    RecyclerView mRv;

    @Override
    protected int getLayoutId() {
        return R.layout.ac_databinding_adapter_with_header;
    }

    @Override
    protected void onInit(Context context, Bundle savedInstanceState) {
        TestDatabindingAdapter.InternalAdapter adapter =
                new TestDatabindingAdapter.InternalAdapter(createItems());
        GridLayoutManager glp = RecyclerViewUtils.createGridLayoutManager(adapter, context, 2);
        mRv.setLayoutManager(glp);
        adapter.addHeaderView(getLayoutInflater().inflate(R.layout.header_data_binding,
                mRv, false));

        mRv.setAdapter(mAdapter = adapter);
    }
}複製程式碼

ImageView圖片繫結.

自定義Binder.

/**
 * test self Binder. this demo will show how to override binder method for data-binding.
 * Created by heaven7 on 2017/11/13 0013.
 */
@BinderClass(TestSelfBinderActivity.MyBinder.class)
public class TestSelfBinderActivity extends TestImageViewBindActivity implements ImageLoader{

    @Override
    protected void onInit(Context context, Bundle savedInstanceState) {
        mResHelper.init(context);

        final ImageViewBind data = DataMediatorFactory.createData(ImageViewBind.class);
        mBinder = DataMediatorFactory.createDataBinding(this)
                .bind(data, new DataBinding.SimpleParameterSupplier() {
                    @Override
                    protected Object getImageLoader() {
                        return TestSelfBinderActivity.this;
                    }
                }, null);
    }

    @Override
    public void loadImage(String url,final ImageView iv) {
        Glide.with(iv.getContext())
                .load(url)
                .into(new SimpleTarget<Drawable>(200, 200) {
                    @Override
                    public void onResourceReady(Drawable resource,
                                                Transition<? super Drawable> transition) {
                        iv.setImageDrawable(resource);
                    }
                });

    }

    public static class MyBinder<T> extends AndroidBinder<T>{

        /**
         * create binder for target data mediator. this constructor must be public .
         *
         * @param mMediator the target data mediator.
         */
        public MyBinder(DataMediator<T> mMediator) {
            super(mMediator);
        }

        @Override
        public Binder<T> bindImageUrl(String property, Object imageView, Object imageLoader) {
            if(!(imageView instanceof ImageView)){
                throw new IllegalArgumentException("the view must be ImageView");
            }
            if(imageLoader instanceof ImageLoader){
                ImageView iv = (ImageView) imageView;
                Toaster.show(iv.getContext(), "start using self MyBinder with image loader.");
                return bind(property, new ImageUrlBinderCallback<T>(iv, getPropertyInterceptor(),
                        (ImageLoader)imageLoader));
            }
            return super.bindImageUrl(property, imageView, imageLoader);
        }
    }

    private static class ImageUrlBinderCallback<T> extends SimpleBinderCallback2<T> {

        final ImageLoader mLoader;
        public ImageUrlBinderCallback(ImageView tv, PropertyInterceptor interceptor,
                                      ImageLoader loader) {
            super(tv, interceptor);
            this.mLoader = loader;
        }
        @Override
        protected void apply(Property prop, View view, Object newValue) {
            mLoader.loadImage((String) newValue, (ImageView) view);
        }
    }
}複製程式碼

繫結一組屬性到一個view?

use @BindsView and @BindsTextView.

小結

常用的屬性繫結都已實現, 想要實現自定義。 使用自定義Binder和BinderFactory即可。
Adapter資料繫結支援對item的 ‘增刪改查-即CRUD’, 支援header, footer.
當然這個框架的能力遠不止此。只要你仔細看專案的示例程式,更多驚喜等著你。
經過1.4.1版本後, 它的資料繫結 可以完美搭配ButterKnife了。

地址: github.com/LightSun/da….

相關文章