安卓APP_ 控件(10)—— ListView可上下滑动的列表(重要)与ViewHolder优化
摘自:安卓APP_ 控件(10)—— ListView可上下滑動的列表(重要)與ViewHolder優化
作者:丶PURSUING
發布時間: 2021-04-12 23:28:27
網址:https://blog.csdn.net/weixin_44742824/article/details/115618378
目錄
- 項目運行效果
- (1)創建ListView
- (2)創建新的item布局
- (3)創建 javaBean
- (4)創建數據中間橋梁:Adapter
- (5)listView的點擊效果
- 更多細節在代碼中體現
- 重點:優化getView中需要多次調用的 `findViewById`
- 知識掃盲
- (1)什么是ViewHolder
- (2)什么是setTag
- (3)什么是javaBean
項目運行效果
ListView實現效果一睹為快
可以進行上下的滑動,也可以對每一個條目進行點擊,每個條目稱為ListView的item。
(1)創建ListView
在activity_main.xml下創建ListView,默認顯示效果如下:
當然,還要對每一個item填充數據,并且每一個item實際上就是一種布局,所以要給item進行布局。
(2)創建新的item布局
根據項目需求進行設置,這里僅用TestView做簡單的演示。
(3)創建 javaBean
設置完以上兩個布局后,就要設置數據。ListView數據都是從網上獲取的,在item下可能會有好幾個數據,所以一般會去創建一個java的Bean類。
使用代碼生成器,生成name的設置方法與獲取方法
(快捷鍵為alt+Insert)
(4)創建數據中間橋梁:Adapter
用for循環模擬從網上獲取的數據,數據如何填充listview這個對象呢?有個輔助類:Adapter
Adapter(適配器)
Adapter是用來幫助填出數據的中間橋梁,簡單點說就是將各種數據以合適的形式顯示在View中給用戶看。
在MainActivity.java中調用了Adapter,如下:
而Adapter的實現細節還要看下文的“更多細節在代碼中體現”。
(5)listView的點擊效果
實際上listView給我們提供有監聽事件:
效果如下圖
更多細節在代碼中體現
Mainactivity.java
public class MainActivity extends AppCompatActivity {private List<Bean> data = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);for(int i = 0;i< 100;i++){Bean bean = new Bean();bean.setName("zhua"+i);data.add(bean);}//拿到listview的對象ListView listview = findViewById(R.id.lv);//數據如何填充這個對象呢?把數據放到Adapter里面去listview.setAdapter(new myAdapter(data,this));//listview的監聽事件listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Override//方法重寫,點擊后打印positionpublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Log.e("zhua", "onItemClick: "+position );}});} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
activity_main.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="wrap_content"android:orientation="vertical"><ListViewandroid:id="@+id/lv"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
myAdapter.java
//繼承BaseAdapter后實現其方法 public class myAdapter extends BaseAdapter {private List<Bean> data;private Context context;//存放數據,以及把context放進去的構造方法public myAdapter(List<Bean> data, Context context){this.data = data;this.context = context;}@Override//返回listview能夠顯示多少數據:data有多少顯示多少public int getCount() {return data.size();}@Override//獲取itempublic Object getItem(int position) {return null;}@Override//獲取itemidpublic long getItemId(int position) {return position;}@Override//返回每一個item條目并給它進行一個設值后返回到界面上。//每次在顯示的時候,都會調用getview給每一個item進行賦值public View getView(int position, View convertView, ViewGroup parent) {//因為item是可以復用的,上下滑動界面時會不斷地進行判斷,為了防止convertView不斷創建,要進行判斷if(convertView == null){//先拿到item條目的布局 渲染layout.list_item,渲染后給到convertViewconvertView = LayoutInflater.from(context).inflate(R.layout.list_item,parent,false);}//需要把data創建的那些值,傳到textView每一個item上面(這個值在項目中是從網上獲取的)TextView textView = convertView.findViewById(R.id.tv);//getView并不是只會調用一次,而是界面每顯示一個item的時候都會創建一次textView.setText(data.get(position).getName());//這樣就把name設置到了textview上面Log.e("zhua", "getView: "+position);return convertView;}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
Bean.java
public class Bean {String name;public String getName() {return name;}public void setName(String name) {this.name = name;} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
list_item.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="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/tv"android:textSize="30sp"android:layout_width="wrap_content"android:layout_height="wrap_content"/>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
重點:優化getView中需要多次調用的 findViewById
但是上面的使用方法,并不是ListView的最優解,因為在myAdapter.java中,每次調用getView都會間接調用方法findViewByld,這非常耗時,效率不高。
優化后的myAdapter.java:每次在getView調用的時候就節省了findViewByld的調用時間。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
其他補充:
知識掃盲
(1)什么是ViewHolder
ViewHolder通常出現在適配器里,為的是listview滾動的時候快速設置值,而不必每次都重新創建很多對象,從而提升性能。
在android開發中Listview是一個很重要的組件,它以列表的形式根據數據的長自適應展示具體內容,用戶可以自由的定義listview每一列的布局,但當listview有大量的數據需要加載的時候,會占據大量內存,影響性能,這時候就需要按需填充并重新使用view來減少對象的創建。
ListView加載數據都是在public View getView(int position, View convertView, ViewGroup parent) {}方法中進行的(要自定義listview都需要重寫listadapter:如BaseAdapter,SimpleAdapter,CursorAdapter的等的getvView方法)。
優化listview的加載速度就要讓convertView匹配列表類型,并最大程度上的重新使用convertView。 getview的最慢的加載方式是每一次都重新定義一個View載入布局,再加載數據。而最快的方式是定義一個ViewHolder,將convetView的tag設置為ViewHolder,不為null時重新使用即可。
(2)什么是setTag
我們使用View,大多數情況就是為了向用戶展示一定的數據,因此,view的使用又總是離不開數據的。基本很多人的做法都會把數據以及view分開,但是其實在Android開發的view中已經有api接口可以完成一定量數據的存儲了,這就是——View.setTag()以及View.getTag()
功力不夠,應用場景暫時看不懂,先掛著:Android View中setTag的二三事
(3)什么是javaBean
Java語言欠缺屬性、事件、多重繼承功能。所以,如果要在Java程序中實現一些面向對象編程的常見需求,只能手寫大量膠水代碼。Java Bean正是編寫這套膠水代碼的慣用模式或約定。
舉例詳解
總結
以上是生活随笔為你收集整理的安卓APP_ 控件(10)—— ListView可上下滑动的列表(重要)与ViewHolder优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中常用的集合
- 下一篇: 安卓APP_ 布局(7) —— View