No ViewHolder!!! 一個非官方的純java版 databinding(拒絕xml配置).

寫在前面

咱們的目標是 No ViewHolder and No Adapter.html

官方的databinding的確十分厲害,各類xml綁定,而後自動生成一波文件,各類吊的飛起,不過容易讓人抓不住重點。爲了加深理解,我寫了這個純java版databindng, 不須要xml各類配置android:text="@{...}",同時進一步加了綁定Adapterjava

時間倉促,只粗略的實現了小部分功能。基於註解的性能也有待優化,但它已經極大地提高了個人開發效率。以爲它不錯的話,能夠一塊兒維護這個項目,向No ViewHolder的目標邁進~android

預覽

常規的電商首頁

所需代碼量

實現這樣一個帶Header, 帶上拉加載的列表須要多少代碼呢?git

  • 兩個無聊的 javabean
  • 一個輪播控件
  • 一個Activity(真的不含 Adapter 啊)
  • 而後沒有而後了。。。

特性

  • data -> view的單向綁定
  • 支持經常使用控件的綁定,同時增長了官方沒有的Adapter綁定。支持Header上拉加載
  • 代碼極其簡潔, 無需實例化View, 也沒有Adapter, 連ViewHoler 也沒有。。。
  • 支持綁定行爲的自定義
  • 配合 Rxjava + Lambda 簡直上天

源碼

github.com/fashare2015…github

gralde 依賴

// 1. Add it in your root build.gradle at the end of repositories:
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

// 2. Add the dependency in your app/build.gradle
dependencies {
        compile 'com.github.fashare2015:NoViewHolder:1.0.1'
}複製代碼

綁定 Data 和 View

這一塊和官方差很少,只是xml配置換成了java註解配置。app

綁定單個 View

首先,你手頭有一個javabean,就是你在圖中看到的妹子列表Item如:maven

public class MeiZhi {
    @BindImageView(id=R.id.iv_image, placeHolder = R.mipmap.ic_launcher)
    public String url;  // 把 url 綁定在 ImageView 上
    @BindTextView(id=R.id.tv_title)
    public String desc; // 把 desc 綁定在 TextView 上
}複製代碼

基本等同於官方的android:text="@{meizhi.desc}",用過databinding的話應該秒懂的。。。ide

綁定列表

固然,服務端返回的確定是個妹子的列表,你手頭還會有一個HomeInfo的東東。性能

public class HomeInfo {
    // 妹子列表區
    @BindRecyclerView(id = R.id.rv_meizhi, layout = R.layout.item_meizhi)
    private List<MeiZhi> results = new ArrayList<>();   // 把 List 綁定在 RecyclerView 上

    // banner
    @BindViewPager(id = R.id.vp_banner, layout = R.layout.item_banner)
    private List<MeiZhi> bannerInfo;    // 把 List 綁定在 ViewPager 上
}複製代碼

這部分是官方沒有的,相應的還提供了 @BindListViewgradle

綁定 header

像上面的配置,banner和妹子列表是分開的,不會一塊兒滑動的。所以,提供了向RecyclerView中添加Header的註解——@BindRvHeader.
讓咱們把banner加進RecyclerView

public class HomeInfo {
    // 妹子列表區
    @BindRecyclerView(id = R.id.rv_meizhi, layout = R.layout.item_meizhi)
    private List<MeiZhi> results = new ArrayList<>();   // 把 List 綁定在 RecyclerView 上

    // banner
    @BindRvHeader(id = R.id.rv_meizhi, layout = R.layout.layout_banner, itemType = 0) // 增長這一行 !!!
    @BindViewPager(id = R.id.vp_banner, layout = R.layout.item_banner)
    private List<MeiZhi> bannerInfo;    // 把 List 綁定在 ViewPager 上
}複製代碼

綁定點擊事件

提供了@BindItemClick@BindClick

public class MainActivity extends AppCompatActivity {
    ...
    @BindItemClick(id = R.id.vp_banner)
    NoOnItemClickListener<MeiZhi> clickBanner = (view, data, pos) -> toast("click Banner: " + pos + ", "+ data.toString());

    @BindItemClick(id = R.id.rv_meizhi)
    NoOnItemClickListener<MeiZhi> clickMeiZhi = (view, data, pos) -> toast("click MeiZhi: " + pos + ", "+ data.toString());
}複製代碼

更新 UI

前面只是一系列綁定關係的配置,還須要一個接口觸發他們:

  • 初始化:根據 R.id.XXX 初始化相應的 View 和 Adapter,爲後續更新UI作準備
mNoViewHolder = new NoViewHolder.Builder(this)
                .initView(new HomeInfo()) // 必定要提供`註解信息`的類,不然沒法初始化。
                .build();複製代碼
  • 更新UI: mNoViewHolder.notifyDataSetChanged(homeInfo);
    自動根據 homeInfo 裏提供的註解信息,找到相應的控件,並把數據刷新上去。
// 在請求的 onSuccess() 中刷新界面,本例使用了 Rxjava 和 lambda
homeInfoObservable.subscribe(homeInfo -> {
        mHomeInfo.getResults().addAll(homeInfo.getResults());           // 更新 妹子列表 info
        if(homeInfo.getResults().size() >= 6)
            mHomeInfo.setBannerInfo(homeInfo.getResults().subList(0, 6));   // 更新 bannerInfo

        mNoViewHolder.notifyDataSetChanged(mHomeInfo);  // mHomeInfo 發生變化, 通知 UI 及時刷新
}複製代碼

全局配置——自定義行爲

當你須要自定義的時候 (好比替換圖片加載庫,默認Glide)。能夠這樣:
以下,即把@BindTextView的行爲override掉了。

static NoViewHolder.Options mDataOptions = new NoViewHolder.DataOptions()
            .setBehaviors(new BindTextView.Behavior() {
                @Override
                public void onBind(TextView targetView, BindTextView annotation, Object value) {
                    targetView.setText("fashare 到此一遊" + value);
                }
            });

    static {
        NoViewHolder.setDataOptions(mDataOptions);
    }複製代碼

總結

水平有限,實現的比較粗糙。但我以爲這個思路還行,用起來簡潔性也絲絕不比官方的差。以爲它不錯的話,能夠一塊兒維護這個項目,向No ViewHolder的目標邁進~

一些相似實現

github.com/Kelin-Hong/…

github.com/evant/bindi…

感謝

github.com/hongyangAnd… (基於它封裝的)

github.com/mcxtzhang/a…

徹底掌握Android Data Binding

[譯]關於 Android Adapter,你的實現方式可能一直都有問題

相關文章
相關標籤/搜索