Android適配器Adapter與ListView和RecycleView的簡單使用
在使用ListView和RecycleView之前,我們得先了解適配器的概念。
適配器
具體來說,適配器Adapter是一個接口。
官方文檔中是這樣描述的:
An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a android.view.View for each item in the data set.
簡單來說,適配器充當著數(shù)據(jù)與視圖之間交互的橋梁,將數(shù)據(jù)以合適的方式顯示出來。其屬于MVC模式(數(shù)據(jù)模式,控制器,視圖)的一種具體情況。
MVC模式:
Adapeter的繼承體系:
適配器中還有許多重要的方法:
getView(int position,View convertView,ViewGroup parent) :
這應(yīng)該是適配器中最重要的方法了,這個方法會在每個子項被滾動到屏幕內(nèi)的時候被調(diào)用,用于加載視圖。
getItem(int positon):
用于獲取在數(shù)據(jù)集中第position位置的實例。
該方法也會在我們設(shè)置監(jiān)聽器后用來簡單地獲取數(shù)據(jù)。
getItemId(int position)
用于獲取在數(shù)據(jù)集中第position位置的實例對應(yīng)的ID。
不同getItem的是,某些方法(如onclicklistener的onclick方法)有id這個參數(shù),而這個id參數(shù)就是取決于getItemId()這個返回值的。
getCount()
返回一共有幾項數(shù)據(jù)。
我們主要介紹的是ArrayAdapter類的使用,主要通過對該類進行繼承重寫來實現(xiàn)我們自己的適配器。
ListView的簡單用法
1.設(shè)計一個布局以顯示列表中的每一個子項
這里我簡單地用一個圖片+文本的形式顯示一個子項,在layout下新建一個布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="50dp"> <ImageView android:id="@+id/Image1" android:layout_width="50dp" android:layout_height="50dp" /> <TextView android:id="@+id/Text1" android:layout_width="0dp" android:layout_height="50dp" android:layout_weight="1" /> </LinearLayout>
2.創(chuàng)建一個中間類以在適配器中加載布局,由于僅有一個圖片和一個文本框,所以這里該類比較簡單:
public class ItemOne { private int imageId; //用于存儲圖片的id值 private String text; //用于存儲文本框要顯示的內(nèi)容 public ItemOne(String text,int imageId) { this.text = text; this.imageId = imageId; } public String getText() { return text; } public int getImageId() { return imageId; } }
3.重點:創(chuàng)建自己的適配器類:
public class MyAdapter extends ArrayAdapter<ItemOne> { private int layoutID;//僅僅用作一個中間變量,用于將構(gòu)造方法中的ResoruceId(即步驟一中創(chuàng)建的子項布局Id)傳遞給getView方法 public MyAdapter(Context context, int ResoruceId, List<ItemOne> data) { super(context,ResoruceId,data); //調(diào)用父類的一種構(gòu)造方法 layoutID = ResoruceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { ItemOne itemOne = getItem(position); //獲取具體的中間類的實例, //這里的position其實就是itemOne在具體的List或者Array(構(gòu)造方法中傳入的List)中的索引 View view = LayoutInflater.from(getContext()).inflate(layoutID, parent,false); //此處是創(chuàng)建具體的子項,調(diào)用靜態(tài)的LayoutInflater.from()從給定的上下文中獲取LayoutInflater實例,再調(diào)用其inflate方法將具體的子項布局加載進來。 //inflate方法的第一個參數(shù)是子項布局的Id,第二個是父布局。第三個是是否給這個View添加父布局,這里我們傳入false就行了,因為一旦View有父布局,其就不能添加入ListView之中了。 ImageView imageView = (ImageView) view.findViewById(R.id.Image1); TextView textView = (TextView) view.findViewById(R.id.Text1); //從之前加載入的子項的布局中獲取具體的微件 imageView.setImageResource(itemOne.getImageId()); textView.setText(itemOne.getText()); //為微件設(shè)置圖片源和要顯示的文本,此處要顯示的內(nèi)容與之前的中間類相關(guān) return view; } }
4.在活動中具體加載和使用ListView:
1.首先我們要在主布局中創(chuàng)建一個ListView
<?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"> <ListView android:id="@+id/listview1" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
2.在主活動中調(diào)用并加載ListView :
public class MainActivity extends AppCompatActivity { private ArrayList<ItemOne> myList = new ArrayList<>(); //一個數(shù)據(jù)列表,用于存儲具體的數(shù)據(jù) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMyItem(); ListView listView = (ListView) findViewById(R.id.listview1); //獲取ListView實例 MyAdapter adapter = new MyAdapter(this,R.layout.item_layout,myList); //創(chuàng)建自定義的適配器 listView.setAdapter(adapter); //給listView設(shè)置適配器 } private void initMyItem()//初始化數(shù)據(jù)列表 { for(int i = 0; i < 20;i++) { ItemOne itemOne = new ItemOne("Item "+ i,R.drawable.qq1); myList.add(itemOne); } } }
這樣就能具體實現(xiàn)一個簡單的ListView:
關(guān)于ListView性能的優(yōu)化
在上面的例子中其實ListView的運行效率是很低的,因為getView()方法每次都會將布局加載一遍,一旦數(shù)據(jù)量過大就會產(chǎn)生卡頓。 我們可以觀察getView方法的參數(shù)中有一個convertView參數(shù),該參數(shù)用于將之前加載好的布局進行緩存。所以我們可以判斷convertView參數(shù)是否為空來決定是否加載布局以提升性能:
更改適配器中的getView方法 public View getView(int position, View convertView, ViewGroup parent) { ItemOne itemOne = getItem(position); View view; if(convertView != null) { view = convertView; }else{ view = LayoutInflater.from(getContext()).inflate(layoutID, parent,false); } ImageView imageView = (ImageView) view.findViewById(R.id.Image1); TextView textView = (TextView) view.findViewById(R.id.Text1); imageView.setImageResource(itemOne.getImageId()); textView.setText(itemOne.getText()); return view; }
既然我們能夠緩存之前的view,那我們還可以借助緩存的view繼續(xù)對性能進行優(yōu)化。
public View getView(int position, View convertView, ViewGroup parent) { ItemOne itemOne = getItem(position); View view; ViewHolder viewHolder = new ViewHolder(); if(convertView != null) { view = convertView; viewHolder = (ViewHolder) view.getTag();//重新獲取viewHolder實例 }else{ view = LayoutInflater.from(getContext()).inflate(layoutID,parent,false); viewHolder.imageView= (ImageView) view.findViewById(R.id.Image1); viewHolder.textView = (TextView) view.findViewById(R.id.Text1); view.setTag(viewHolder); //將viewHolder存儲在view中 } viewHolder.imageView.setImageResource(itemOne.getImageId()); viewHolder.textView.setText(itemOne.getText()); return view; } class ViewHolder{ ImageView imageView; TextView textView; } }
在這里我們自建了一個內(nèi)部類ViewHolder用于存儲具體的微件,并將其存儲在view中,如果view已經(jīng)被緩存過,則說明其中的微件已經(jīng)綁定過,所以直接拿出來用就行了。
ListView的鼠標監(jiān)聽事件
ListView的鼠標監(jiān)聽事件與Button的監(jiān)聽事件十分相似,不同的點就在于具體實現(xiàn)的接口,調(diào)用的方法不同:
修改onCreate方法 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMyItem(); ListView listView = (ListView) findViewById(R.id.listview1); MyAdapter adapter = new MyAdapter(this,R.layout.item_layout,myList); listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView. OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ItemOne itemOne = myList.get(position); //獲取具體實例 Log.d("MainActivity",itemOne.getText()); } }); }
這里簡單對ListView設(shè)置了一個適配器的監(jiān)聽器,每次點擊就獲取相應(yīng)實例并且將其text通過日志打印出來.
RecyclerView的簡單用法
RecyclerView的用法和ListView十分相似:
1.創(chuàng)建具體的適配器
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> { private List<ItemOne> mList; static class ViewHolder extends RecyclerView.ViewHolder{ ImageView imageView; TextView textView; public ViewHolder(View view) { super(view); imageView = (ImageView) view.findViewById(R.id.Image1); textView = (TextView) view.findViewById(R.id.Text1); } } public RecycleAdapter(List<ItemOne> list) { mList = list; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_layout,parent,false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(ViewHolder holder,int position) { ItemOne itemOne = mList.get(position); holder.imageView.setImageResource(itemOne.getImageId()); holder.textView.setText(itemOne.getText()); } @Override public int getItemCount(){ return mList.size(); } }
我們首先新創(chuàng)建一個適配器類繼承RecyclerView.Adapter。在適配器中我們創(chuàng)建了一個靜態(tài)內(nèi)部類ViewHolder繼承RecyclerView.ViewHold,這個類主要是在后面的方法中使用的。
由于繼承了RecyclerView.Adapter,該類需要重寫三個方法分別用于創(chuàng)建ViewHolder,綁定ViewHolder和返回數(shù)據(jù)一共有多少項.
2.在主活動中配置適配器:
public class MainActivity extends AppCompatActivity { private ArrayList<ItemOne> myList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMyItem(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.Re1); LinearLayoutManager layoutManager = new LinearLayoutManager(this); //設(shè)置線性布局管理器 recyclerView.setLayoutManager(layoutManager); RecycleAdapter adapter = new RecycleAdapter(myList); recyclerView.setAdapter(adapter); } private void initMyItem() { for(int i = 0; i < 20;i++) { ItemOne itemOne = new ItemOne("Item "+ i,R.drawable.qq1); myList.add(itemOne); } } }
與ListView不同的可能就是RecyclerView還需要額外設(shè)置布局方式,這里我們創(chuàng)建的是最簡單的線性布局,效果與ListView一樣。RecyclerView還有其他的布局模式,我們可以自行去體驗。
到此這篇關(guān)于Android適配器Adapter與ListView和RecycleView的簡單使用的文章就介紹到這了,更多相關(guān)Android適配器Adapter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android Studio綁定下拉框數(shù)據(jù)詳解
這篇文章主要為大家詳細介紹了Android Studio綁定下拉框數(shù)據(jù),Android Studio綁定網(wǎng)絡(luò)JSON數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10Android實現(xiàn)保存QQ賬號與密碼功能(文件存儲)
這篇文章主要介紹了Android保存QQ賬號與密碼,文件存儲是Android中最基本的一種數(shù)據(jù)存儲方式,它與Java中的文件存儲類似,都是通過I/O流形式把數(shù)據(jù)直接存儲到文件中,下面我們一起來看一下如何用Android實現(xiàn)文件存儲功能吧2022-04-04Android使用Retrofit實現(xiàn)自定義Converter解析接口流程詳解
Retrofit是一個RESTful的HTTP網(wǎng)絡(luò)請求框架的封裝,網(wǎng)絡(luò)請求的工作本質(zhì)上是OkHttp完成,而Retrofit僅負責網(wǎng)絡(luò)請求接口的封裝2023-03-03Android開發(fā)TextView內(nèi)的文字實現(xiàn)自動換行
這篇文章主要為大家介紹了Android開發(fā)TextView內(nèi)的文字實現(xiàn)自動換行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06viewpager實現(xiàn)自動循環(huán)輪播圖
這篇文章主要為大家詳細介紹了viewpager實現(xiàn)自動循環(huán)輪播圖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-01-01Android 點擊ImageButton時有“按下”的效果的實現(xiàn)
這篇文章主要介紹了 Android 點擊ImageButton時有“按下”的效果的實現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-03-03