欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android入門(mén)之實(shí)現(xiàn)自定義Adapter

 更新時(shí)間:2022年11月15日 10:28:01   作者:TGITCIC  
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)自定義Adapter,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Android有一定的幫助,需要的可以參考一下

介紹

在上一篇“SimpleAdapter“章節(jié)中,我們看到了把:ListView和Listview內(nèi)部詳細(xì)頁(yè)面進(jìn)行分離的Adapter的設(shè)計(jì)手法。

可是,這個(gè)SimpleAdapter的構(gòu)造函數(shù)不夠錄活、苦澀難懂。很難滿足我們實(shí)際大多生產(chǎn)場(chǎng)景的開(kāi)發(fā)。

因此,今天我們就要來(lái)看一個(gè)更人性化的“自定義BaseAdapter“。實(shí)際生產(chǎn)應(yīng)用場(chǎng)景開(kāi)發(fā)中充斥著自定義BaseAdapter,因此必須要提及它并且圍繞著這個(gè)extends BaseAdapter我們要持續(xù)說(shuō)不少高級(jí)特性。

先來(lái)看一下課程最終要實(shí)現(xiàn)的目標(biāo)

有喵、有汪、有金錢(qián)。還多了表頭和表尾。

我們這次就要使用真正的面向業(yè)務(wù)邏輯、面向?qū)ο蟮氖址▉?lái)實(shí)現(xiàn)這個(gè)界面。

設(shè)計(jì)

上述界面其實(shí)和上一篇例子相仿,使用到了:1個(gè)ImageView、兩個(gè)TextView。

只不過(guò)這次我們用的是標(biāo)準(zhǔn)MVC模式的自定義Adapter。

項(xiàng)目結(jié)構(gòu)

是不是很詳盡?保姆式教程,不詳盡不稱為“保姆”。

先來(lái)看UI端代碼

UI端代碼

這一塊和上一篇幾乎相似,沒(méi)有什么太多變化

activity_main.xml文件

很簡(jiǎn)單,沒(méi)有任何神密可言,就一個(gè)“光桿”Listview的存在。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">
 
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

customized_layout.xml文件

內(nèi)容也是very easy,屬于“常規(guī)損人和”,和上一篇無(wú)異。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 定義一個(gè)用于顯示頭像的ImageView -->
    <ImageView
        android:id="@+id/touxiang"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:baselineAlignBottom="true"
        android:paddingLeft="8dp" />
 
    <!-- 定義一個(gè)豎直方向的LinearLayout,把QQ呢稱與說(shuō)說(shuō)的文本框設(shè)置出來(lái) -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
 
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="8dp"
            android:textColor="#1D1D1C"
            android:textSize="20sp" />
 
        <TextView
            android:id="@+id/description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="8px"
            android:textColor="#B4B4B9"
            android:textSize="14sp" />
 
    </LinearLayout>
</LinearLayout>

后端代碼

PetBean.java

package org.mk.android.demo.democustomizedadapter;
 
import java.io.Serializable;
 
public class PetBean implements Serializable {
    private String name = "";
    private int imgId;
    private String description = "";
 
    public int getImgId() {
        return imgId;
    }
 
    public void setImgId(int imgId) {
        this.imgId = imgId;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public PetBean(int touxiang, String name, String description) {
        this.imgId = touxiang;
        this.name = name;
        this.description = description;
    }
}

這個(gè)Java Bean里分別就對(duì)應(yīng)著一個(gè)ImageView,兩個(gè)TextView。

始終記得,把Image傳遞給到Adapter用的是一個(gè)int值,它來(lái)源于:R.drawable.圖片名稱(不帶.即postfix)。

PetAdapter.java

package org.mk.android.demo.democustomizedadapter;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
import java.util.List;
 
public class PetAdapter extends BaseAdapter {
    private List<PetBean> data;
    private Context ctx;
 
    public PetAdapter(List<PetBean> data, Context ctx) {
        this.data = data;
        this.ctx = ctx;
    }
 
    @Override
    public int getCount() {
        if (data != null) {
            return data.size();
        }
        return 0;
    }
 
    @Override
    public Object getItem(int i) {
        return null;
    }
 
    @Override
    public long getItemId(int i) {
        return i;
    }
 
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        MyViewHolder viewHolder=null;
        if (view == null) {
            view = LayoutInflater.from(ctx).inflate(R.layout.customized_layout, viewGroup, false);
            viewHolder=new MyViewHolder();
            viewHolder.touxiang = (ImageView) view.findViewById(R.id.touxiang);
            viewHolder.name = (TextView) view.findViewById(R.id.name);
            viewHolder.description = (TextView) view.findViewById(R.id.description);
            view.setTag(viewHolder);
        }else{
            viewHolder=(MyViewHolder)view.getTag();
        }
        if (data != null) {
            viewHolder.touxiang.setBackgroundResource(data.get(i).getImgId());
            viewHolder.name.setText(data.get(i).getName());
            viewHolder.description.setText(data.get(i).getDescription());
            return view;
        }
        return null;
    }
 
    static class MyViewHolder {
        public ImageView touxiang;
        public TextView name;
        public TextView description;
    }
}

代碼導(dǎo)讀

整個(gè)自定義的Adapter是extends自BaseAdapter,這個(gè)BaseAdapter在extends后有幾個(gè)方法需要進(jìn)行覆蓋:

1.構(gòu)造函數(shù),構(gòu)造函數(shù)里需要兩個(gè)參數(shù):

  • 第一個(gè)參數(shù),構(gòu)造函數(shù)里把自定義的數(shù)據(jù)源在上一例里我們用的是List<Map<String,Object>>(不夠面向?qū)ο螅?,而這邊就是List<我們的ViewBean>傳進(jìn)去;
  • Context,如果在MainActivity.java里,我們就可以用這樣的形式來(lái)傳這個(gè)參數(shù):Context ctx = MainActivity.this;

2.public int getCount() ,它返回的就是你的ListView里有多少行的這個(gè)size即我們?cè)跇?gòu)造方法里傳入的這個(gè)List<ViewBean>的size;

3.public Object getItem(int i),這個(gè)方法我們?cè)诤笠徊?,高?jí)定制化Adapter里會(huì)進(jìn)一步用到,目前在此我們直接return null就完事了,不用作糾結(jié);

4.public long getItemId(int i),這邊的int i其實(shí)是position,我們可以這么干:直接return i即可,它其實(shí)是一種“一行行從List<ViewBean>取出數(shù)據(jù)做渲染”用的;

5.public View getView(int i, View view, ViewGroup viewGroup) ,這個(gè)函數(shù)是核心,它的故事長(zhǎng)了,來(lái)看一步步導(dǎo)讀:

這個(gè)方法的作用就是一條條把List<ViewBean>數(shù)據(jù)取出來(lái)作渲染用的,它依賴于這一句話:LayoutInflater.from(ctx).inflate(R.layout.customized_layout,

viewGroup, false);這個(gè)語(yǔ)句被調(diào)用的次數(shù)=List.size(),每調(diào)用一次這條語(yǔ)句,Android界面會(huì)渲染一次(一次開(kāi)銷);

每一個(gè)ListView內(nèi)的行顯示的內(nèi)容根據(jù)List<ViewBean>里每一行不同的內(nèi)容會(huì)有不同的顯示,在這邊的一行指的就是:一個(gè)ImageView+兩個(gè)TextView的渲染。因此你要做的就是一個(gè)個(gè)“控制件名.set屬性(List里取出相應(yīng)的該行的這個(gè)數(shù)組的屬性件)”,因此才有了如此的寫(xiě)法:name.setText(data.get(i).getName());如:description.setText(data.get(i).getDescription());如:touxiang.setBackgroundResource(data.get(i).getImgId());這樣的東西。隨便說(shuō)一句:此處的i帶的正是getView里的(int i...)里的這個(gè)i,這個(gè)i對(duì)應(yīng)著你的List<ViewBean>里當(dāng)前的“游標(biāo)”;

全部一個(gè)個(gè)set完了后,把這個(gè)view return出去;

接著我們來(lái)說(shuō),這塊代碼看似沒(méi)邏輯那為什么會(huì)有:View Holder?這是一個(gè)什么鬼?前面我們提到了一句:

LayoutInflater.from(ctx).inflate(R.layout.customized_layout, viewGroup, false);這個(gè)語(yǔ)句被調(diào)用的次數(shù)=List.size(),每調(diào)用一次這條語(yǔ)句,Android界面會(huì)渲染一次,這個(gè)動(dòng)作其實(shí)是很開(kāi)銷資源的。比如說(shuō)我的List<ViewBean>里有100條數(shù)據(jù),Android會(huì)界面渲染100次。其實(shí)這個(gè)渲染只是一個(gè)“一次性”的事,在這邊只要渲染一次就夠了,其余99次是多余重復(fù)的。渲染太多會(huì)造成這個(gè)Android極其吃手機(jī)的“運(yùn)存”。所以我們使用了一個(gè)小技巧:只在這個(gè)View為空時(shí)做一次渲染。渲染過(guò)后就不要再渲染了,直接填充界面控件內(nèi)的屬性值就行了。因此才有了第一個(gè)if (view == null) {的判斷。

那么ViewHolder呢?還是沒(méi)有解釋ViewHolder的作用。我們前面解決了這個(gè)LayoutInflater.from(ctx).inflate的重復(fù)調(diào)用問(wèn)題,但是讀者們知道嗎?你在getView方法里的findViewById(R.id.description)這樣的東西也是會(huì)每次被重復(fù)調(diào)用一次的,舉例來(lái)說(shuō):你有3個(gè)控件,在List<ViewBean>里有3行數(shù)據(jù),你以為你只調(diào)用了3次findViewById?其實(shí)是調(diào)用了總計(jì)3*3=9次,即調(diào)用第二個(gè)控件的findViewById時(shí)它依舊會(huì)重復(fù)調(diào)用第一個(gè)控件的findViewById。這個(gè)動(dòng)作也是開(kāi)銷Android的運(yùn)存和cpu的。那么我們同樣為了減少findViewById的重復(fù)調(diào)用,因此我們使用一個(gè)MyViewHolder,讓其和我們的ViewBean(此處就是PetBean)一樣的結(jié)構(gòu),它專門(mén)是用于保存已經(jīng)被調(diào)用過(guò)findViewById的狀態(tài)(TAG)。然后使用view.setTag和view.getTag來(lái)做狀態(tài)保留。如果這個(gè)Tag存在那么不用再findViewById一次了。如果不存在再findViewById一次;

接著我們就來(lái)看交程序交互后端代碼MainActivity.java

MainActivity.java

package org.mk.android.demo.democustomizedadapter;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ListView;
 
import java.util.ArrayList;
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
    private List<PetBean> data = null;
    private Context ctx;
    private PetAdapter adapter = null;
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ctx = MainActivity.this;
        listView = (ListView) findViewById(R.id.listView);
        data = new ArrayList<PetBean>();
        data.add(new PetBean(R.drawable.cat,"貓","這是一只貓"));
        data.add(new PetBean(R.drawable.dog,"狗","這是一只狗"));
        data.add(new PetBean(R.drawable.jingqianbao,"金錢(qián)豹","這是金錢(qián)豹"));
        adapter = new PetAdapter((List<PetBean>) data, ctx);
        final LayoutInflater inflater = LayoutInflater.from(this);
        View headView = inflater.inflate(R.layout.view_header, null, false);
        View footView = inflater.inflate(R.layout.view_footer, null, false);
        listView.addHeaderView(headView);
        listView.addFooterView(footView);
        listView.setAdapter(adapter);
    }
}

我們這次為我們的ListView增加了一個(gè)表頭,一個(gè)表尾。表頭表尾分別對(duì)應(yīng)著兩個(gè)layout xml文件,它們位于我們項(xiàng)目的res\layout目錄下。

注:

記得在調(diào)用addHeaderView和addFootView的動(dòng)作必須位于setAdapter(adapter)語(yǔ)句前;

表頭樣式-view_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:textSize="18sp"
        android:text="表頭"
        android:gravity="center"
        android:background="#43BBEB"
        android:textColor="#FFFFFF"/>
</LinearLayout>

表尾樣式-view_footer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:textSize="18sp"
        android:text="表尾"
        android:gravity="center"
        android:background="#ECE9E6"
        android:textColor="#0C0C0C"/>
</LinearLayout>

運(yùn)行效果

自己動(dòng)一下手試試就能找到自定義Adapter的感覺(jué)。自定義Adapter的作用很大、使用場(chǎng)景也很多。我們后面會(huì)繼續(xù)強(qiáng)化自定義Adapter的業(yè)務(wù)場(chǎng)景的使用。 

到此這篇關(guān)于Android入門(mén)之實(shí)現(xiàn)自定義Adapter的文章就介紹到這了,更多相關(guān)Android自定義Adapter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論