使用自定義Layout代替ViewHolder

個(gè)人主頁為 The_D的博客

很多人使用 Listview 時(shí),總是用 ViewHolder 的模式來創(chuàng)建,而根據(jù) Customizing Android ListView Rows by Subclassing 中說的,ViewHolder 是一種愚笨的方式永高。在這篇文章中恨豁,作者提出了一個(gè)新的思路,也就是通過自定義的 Layout 來代替 ViewHolder迁匠。

ViewHolder的缺點(diǎn)

  • Adapter 的 getView() 函數(shù)承擔(dān)了很多責(zé)任
  • ViewHolder 類中通常是一些無意義的代碼
  • view 的 tag 需要轉(zhuǎn)換到正確的 holder 類型
  • 違反了封裝性,因?yàn)?adapter/holder 必須知道 item 內(nèi)部有什么 view

demo:

動(dòng)圖
動(dòng)圖

下面來說說如何實(shí)現(xiàn):

首先驹溃,創(chuàng)建item_relative_layout.xml:
item由頭像ImageView城丧,名字TextView和描述TextView構(gòu)成

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:scaleType="fitCenter"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/iv"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="60dp"
        android:textSize="16sp"
        />

    <TextView
        android:id="@+id/description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/iv"
        android:layout_below="@id/tv_title"
        android:layout_marginTop="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginLeft="20dp"
        android:textSize="14sp"
        />

</RelativeLayout>

然后,創(chuàng)建CustomRelativeLayout.java:

public class CustomRelativeLayout extends RelativeLayout {

    //使用ButterKnife注解的方式豌鹤,簡(jiǎn)化了findViewById
    @Bind(R.id.iv)
    ImageView mIv;
    @Bind(R.id.tv_title)
    TextView mTvTitle;
    @Bind(R.id.description)
    TextView mDescription;

    public CustomRelativeLayout(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.item_relative_layout, this);
        ButterKnife.bind(this);
        //因?yàn)槊恳粋€(gè)item的listener都相同亡哄,所以將clickListener寫在這個(gè)類中,如果不同布疙,可寫在adapter的getView()中根據(jù)position設(shè)置不同listener
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getContext(), mTvTitle.getText().toString() + " " + mDescription.getText().toString(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    public void setData(int iv, String title, String description){
        mIv.setImageResource(iv);
        mTvTitle.setText(title);
        mDescription.setText(description);
    }
}

ListAdapter.java:

public class ListAdapter extends BaseAdapter {

    Context mContext;
    int[] images;
    String[] titles;
    String[] descriptions;

    public ListAdapter(Context context) {
        mContext = context;
    }

    public void setData(int[] images, String[] titles, String[] descriptions) {
        this.images = images;
        this.titles = titles;
        this.descriptions = descriptions;
    }

    @Override
    public int getCount() {
        return images.length;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
    
    //相對(duì)于ViewHolder簡(jiǎn)化了getView
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CustomRelativeLayout customRelativeLayout = null;
        if (convertView != null && convertView instanceof CustomRelativeLayout) {
            customRelativeLayout = (CustomRelativeLayout) convertView;
        } else {
            customRelativeLayout = new CustomRelativeLayout(mContext);
        }
        customRelativeLayout.setData(images[position], titles[position], descriptions[position]);
        return customRelativeLayout;
    }
}

UsingCustomLayoutActivity.java:

public class UsingCustomLayoutActivity extends AppCompatActivity {

    @Bind(R.id.lv)
    ListView mLv;
    ListAdapter mListAdapter;
    int[] images = {R.drawable.p1, R.drawable.p2, R.drawable.p3};
    String[] titles = {"The_D", "閆一彪", "Android技術(shù)小鋪"};
    String[] descriptions = {"Android開發(fā)", "Java后端開發(fā)", "我的微信公眾號(hào)蚊惯,專注于Android技術(shù)分享愿卸,歡迎關(guān)注"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_using_custom_layout);
        ButterKnife.bind(this);
        mListAdapter = new ListAdapter(this);
        mListAdapter.setData(images, titles, descriptions);
        mLv.setAdapter(mListAdapter);
    }
}

activity_using_custom_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhangkaiyue.jkdemo.UsingCustomLayoutActivity">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</RelativeLayout>

這種做法的優(yōu)勢(shì):

這樣寫可以使item復(fù)用,并且針對(duì)復(fù)雜的Adapter截型,大大的簡(jiǎn)化了書寫趴荸。對(duì)于一些跟View相關(guān)的邏輯,可以直接寫在CustomRelativeLayout中菠劝,消除了Adapter的冗余赊舶。


我的微信公眾號(hào)
我的微信公眾號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赶诊,隨后出現(xiàn)的幾起案子笼平,更是在濱河造成了極大的恐慌,老刑警劉巖舔痪,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寓调,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡锄码,警方通過查閱死者的電腦和手機(jī)夺英,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滋捶,“玉大人痛悯,你說我怎么就攤上這事≈乜撸” “怎么了载萌?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)巡扇。 經(jīng)常有香客問我扭仁,道長(zhǎng),這世上最難降的妖魔是什么厅翔? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任乖坠,我火速辦了婚禮,結(jié)果婚禮上刀闷,老公的妹妹穿的比我還像新娘熊泵。我一直安慰自己,他們只是感情好涩赢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布戈次。 她就那樣靜靜地躺著,像睡著了一般筒扒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绊寻,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天花墩,我揣著相機(jī)與錄音悬秉,去河邊找鬼。 笑死冰蘑,一個(gè)胖子當(dāng)著我的面吹牛和泌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祠肥,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼武氓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了仇箱?” 一聲冷哼從身側(cè)響起县恕,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剂桥,沒想到半個(gè)月后忠烛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡权逗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年美尸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斟薇。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡师坎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出堪滨,到底是詐尸還是另有隱情胯陋,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布椿猎,位于F島的核電站惶岭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏犯眠。R本人自食惡果不足惜按灶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望筐咧。 院中可真熱鬧鸯旁,春花似錦、人聲如沸量蕊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽残炮。三九已至韭赘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間势就,已是汗流浹背泉瞻。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工脉漏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人袖牙。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓侧巨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鞭达。 傳聞我的和親對(duì)象是個(gè)殘疾皇子司忱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,139評(píng)論 25 707
  • 一、適用場(chǎng)景 ListViewListview是一個(gè)很重要的組件畴蹭,它以列表的形式根據(jù)數(shù)據(jù)的長(zhǎng)自適應(yīng)展示具體內(nèi)容,用...
    Geeks_Liu閱讀 10,669評(píng)論 1 28
  • 借一盞殘燈深夜里清醒 望半杯清茶孤獨(dú)里暖心
    慕晨的記事本閱讀 181評(píng)論 0 0
  • 最近看《教父》這本書坦仍,本來聽說這是什么男人勵(lì)志必讀,可是哪有看一本書就能夠勵(lì)志的呢撮胧,還有《肖申克的救贖》桨踪。也許也是...
    永恒恒閱讀 263評(píng)論 0 1
  • 我是一顆種子 在黑暗里 努力伸展向下,向下芹啥,再向下 吸取大地之精華 我無聲的伸展向上锻离,向上,再向上 尋找那生命之光...
    綠洲玫瑰閱讀 262評(píng)論 0 1