kotlin開發(fā)經(jīng)驗(yàn)談5

listview的使用

這篇講在koltin中如何使用listview,跟java代碼比起來又會有哪些不同呢
先用java代碼創(chuàng)建一個bookAdapter.繼承自BaseAdapter,實(shí)現(xiàn)那固定的幾個方法,貼一下代碼:

public class BookAdapter2 extends BaseAdapter {
    private List<Book> books = new ArrayList<>();

    @Override
    public int getCount() {
        return books.size();
    }

    @Override
    public Object getItem(int position) {
        return books.get(position);
    }

    @Override
    public long getItemId(int id) {
        return id;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup container) {
        ViewHolder viewHolder;
        Book book = (Book) getItem(position);
        if (convertView == null) {
            convertView = LayoutInflater.from(container.getContext()).inflate(R.layout.view_book_list_item, container, false);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.author.setText(book.getAuthor());
        viewHolder.name.setText(book.getName());
        return convertView;
    }

    static class ViewHolder {
        TextView author;
        TextView name;

        ViewHolder(View itemView) {
            author = itemView.findViewById(R.id.author);
            name = itemView.findViewById(R.id.name);
        }
    }
}

adapter里面最關(guān)鍵的代碼就是getView了。那我們看看轉(zhuǎn)換成kotlin之后改怎么寫,筆者這里沒有使用一鍵轉(zhuǎn)換,有點(diǎn)不太靠譜,還不如自己手敲,看一下得到的最原始的代碼

override fun getView(position: Int, convertView: View?, container: ViewGroup): View {
            val data = getItem(position) as Book
            val view: View
            val viewHolder: ViewHolder
            if (convertView == null) {
                view =  LayoutInflater.from(container.context).inflate(R.layout.view_book_list_item, container, false)
                viewHolder = ViewHolder(view)
                view.tag = viewHolder
            } else {
                view = convertView
                viewHolder = view.tag as ViewHolder
            }

            viewHolder.name.text = data.name
            viewHolder.author.text = data.author
            return view
        }

getView方法在轉(zhuǎn)換為java方法的時候,override fun getView(position: Int, convertView: View?, container: ViewGroup): View{}后兩個參數(shù)都是可空的,而且參數(shù)都是常量了,不能夠當(dāng)做變量用,這個地方得注意一下。
在這里,由于converView可能為null,而且是常量,不能修改值,那么原來的返回converView就不行了,得重新定義一個view,在convertView為空的時候加載布局,非空的時候把converView賦值給view。以上的代碼寫法,是初學(xué)使用kotlin的寫法,但是代碼看起來也還是清晰的。。

那么我們是否有辦法修改優(yōu)化呢,變得更加函數(shù)式風(fēng)格一點(diǎn)呢。

override fun getView(position: Int, convertView: View?, container: ViewGroup): View {
            val data = getItem(position) as Book
            val view: View = convertView ?: LayoutInflater.from(container.context).inflate(R.layout.view_book_list_item, container, false).apply {
                tag = ViewHolder(this)
            }
            (view.tag as ViewHolder).apply {
                name.text = data.name
                author.text = data.author
            }
            return view
        }

直接看這么一段代碼,這個就是我們做了一定程度的代碼優(yōu)化,是的看起來更加偏函數(shù)式編程,思路是直接對view賦值,根據(jù)converView是否為空做區(qū)分,不為空直接復(fù)制,為空的話,先加載布局同時執(zhí)行apply{}代碼塊,設(shè)置viewHolder。
然后就是講viewHolder取出來了,對控件進(jìn)行賦值,思路其實(shí)跟最開始的koltin的思路是一樣的,只不過代碼風(fēng)格上面變化了。
那么是否可以再進(jìn)一步演進(jìn)呢。

override fun getView(position: Int, convertView: View?, container: ViewGroup): View {
            val data = getItem(position) as Book
            return (convertView ?: LayoutInflater.from(container.context).inflate(R.layout.view_book_list_item, container, false).apply {
                tag = ViewHolder(this)
            }).apply {
                (tag as ViewHolder).apply {
                    name.text = data.name
                    author.text = data.author
                    //this@apply.container.isSelected = selectedBooks.contains(data)
                }
            }
        }

這樣看起來就只定義了一個data常量,然后就直接return了convertView。顯得挺簡潔了。
當(dāng)然了這樣的代碼看起來可能不是很直觀,因?yàn)閕f條件不是很明顯,沒有java代碼寫出來的邏輯清晰分明,條件判斷區(qū)分的很顯眼。需要團(tuán)隊(duì)成員熟悉這種寫法才好。初看這段代碼幾乎是一臉懵逼的,都不知道為啥這樣apply{}.apply{}的嵌套代碼,而且直接引用的是類屬性,各種this之類的,不好好的分析代碼,肯定會很困惑的,如果項(xiàng)目里面類似這樣的代碼多了,新成員剛接觸肯定很不適應(yīng)的。在這里就得扯遠(yuǎn)一點(diǎn)了,如何讓代碼變得清晰可讀并且簡潔?

個人有一些看法,清晰可讀簡潔,我覺得得從邏輯的角度上來說

邏輯上得清晰,無論是if條件判斷,多重if/else判斷,還是循環(huán)嵌套,遞歸,或者是其他的設(shè)計(jì)模式等邏輯上一定得清晰,讀代碼的人能夠知道你是怎么區(qū)分的,依據(jù)條件是什么,是否分類的完善,邏輯跳轉(zhuǎn)是否合理正常等。

代碼可讀性強(qiáng),寫出來的代碼,讓團(tuán)隊(duì)成員看著不困惑,就如同知名的開源項(xiàng)目那樣,大神寫出來的java代碼,基本上做過java開發(fā)的同學(xué)都是能夠看懂的,java語言決定了它的代碼寫出來的就是這樣的套路,只不過在大神的手里,寫出來可讀性,邏輯性都很高。讓人覺得代碼寫的很漂亮,很清爽。代碼的流轉(zhuǎn)執(zhí)行過程比較符合正常人的思維習(xí)慣等,這樣的代碼容易給開發(fā)者一種親切感

簡潔,簡潔還是得是邏輯上簡潔,更多的時候不要過度沉迷于代碼層面了,比如說,某某一個驗(yàn)證碼控件,不同業(yè)務(wù)都有自己的特殊場景,這種情況下不好復(fù)用的話,就按業(yè)務(wù)拆離,不要為了節(jié)省代碼,而將這兩三個業(yè)務(wù)的代碼都放在一起,而且還堆纏在一起,這樣不太好,還不如為每一個業(yè)務(wù)做一個獨(dú)立的封裝,出現(xiàn)部分重復(fù)的代碼是可以接受的,一定要記住,我們需要的是邏輯上的簡潔,在舉個例子形容,比如說圖片加載組件picasso,或者是Glide等,我在項(xiàng)目中使用了其中一個,那么我需要考慮到以后存在換組件的問題而封裝一個抽象層嗎(當(dāng)然了這個例子可能舉的不好,但是這里我還是想說下這個),我覺得是沒有必要的,這種組件api已經(jīng)足夠簡單了,使用也是極其方便,而且還很方面開發(fā)者擴(kuò)展一些特殊的需求,比如說加載通知欄的icon等場景,使用組件原生api已經(jīng)足夠方便,足夠簡潔了,我覺得在做封裝是沒有必要的,等你真正覺得需要換的時候,半天到一天就換過來了,畢竟我也是做過這種工作,不覺得有多麻煩。更何況做的封裝,不見的能夠滿足所有的場景,難道等不滿足的時候在重新寫一個新的方法嗎,或者就是直接調(diào)用原生組件的api呢? 反正我覺得沒必要。這就是我的技術(shù)理念。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,052評論 25 709
  • 上一章 | 目錄 chapter.7 欺詐師(1) 我靠欺騙收獲觀眾的笑容,靠欺騙隱瞞血腥的秘密,靠欺騙贏得虛偽的...
    葳蕤之魂閱讀 1,270評論 0 1
  • HTML是什么? 定義:HTML 是用來描述網(wǎng)頁的一種語言 HTML 指的是超文本標(biāo)記語言: HyperText ...
    Eugene_iOS閱讀 479評論 0 0

友情鏈接更多精彩內(nèi)容