亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android入門之實現(xiàn)自定義Adapter

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

介紹

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

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

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

先來看一下課程最終要實現(xiàn)的目標

有喵、有汪、有金錢。還多了表頭和表尾。

我們這次就要使用真正的面向業(yè)務邏輯、面向對象的手法來實現(xiàn)這個界面。

設計

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

只不過這次我們用的是標準MVC模式的自定義Adapter。

項目結構

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

先來看UI端代碼

UI端代碼

這一塊和上一篇幾乎相似,沒有什么太多變化

activity_main.xml文件

很簡單,沒有任何神密可言,就一個“光桿”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ī)損人和”,和上一篇無異。

<?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">
    <!-- 定義一個用于顯示頭像的ImageView -->
    <ImageView
        android:id="@+id/touxiang"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:baselineAlignBottom="true"
        android:paddingLeft="8dp" />
 
    <!-- 定義一個豎直方向的LinearLayout,把QQ呢稱與說說的文本框設置出來 -->
    <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;
    }
}

這個Java Bean里分別就對應著一個ImageView,兩個TextView。

始終記得,把Image傳遞給到Adapter用的是一個int值,它來源于: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;
    }
}

代碼導讀

整個自定義的Adapter是extends自BaseAdapter,這個BaseAdapter在extends后有幾個方法需要進行覆蓋:

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

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

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

3.public Object getItem(int i),這個方法我們在后一步,高級定制化Adapter里會進一步用到,目前在此我們直接return null就完事了,不用作糾結;

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

5.public View getView(int i, View view, ViewGroup viewGroup) ,這個函數(shù)是核心,它的故事長了,來看一步步導讀:

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

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

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

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

接著我們來說,這塊代碼看似沒邏輯那為什么會有:View Holder?這是一個什么鬼?前面我們提到了一句:

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

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

接著我們就來看交程序交互后端代碼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,"金錢豹","這是金錢豹"));
        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增加了一個表頭,一個表尾。表頭表尾分別對應著兩個layout xml文件,它們位于我們項目的res\layout目錄下。

注:

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

表頭樣式-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>

運行效果

自己動一下手試試就能找到自定義Adapter的感覺。自定義Adapter的作用很大、使用場景也很多。我們后面會繼續(xù)強化自定義Adapter的業(yè)務場景的使用。 

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

相關文章

最新評論