ListView之BaseAdapter的基本使用以及ViewHolder模式

转载自点击打开链接

这篇文章适合初学者,高手绕道,当然不知道ViewHolder的“高手”可以停下来。 

 话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView、GridView、Gallery、Spinner等等。它是直接继承自接口类Adapter的,使用BaseAdapter时需要重写很多方法,其中最重要的当属getView,因为这会涉及到ListView优化等问题,其他的方法可以参考链接的文章

BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置,比如

1
SimpleAdapter adapter = new SimpleAdapter( this , getData(), R.layout.list_item, new String[]{ "img" , "title" , "info" , new int[]{R.id.img, R.id.title, R.id.info}});

但是在BaseAdapter中需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如

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
class MyAdapter extends BaseAdapter
     {
         private Context context;
         public MyAdapter(Context context)
         {
             this .context = context;
         }
         @Override
         public int getCount() {
             // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数)
             return 0;
         }
         @Override
         public Object getItem(int position) {
             // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项)
             return null ;
         }
         @Override
         public long getItemId(int position) {
             // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id)
             return 0;
         }
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             // Get a View that displays the data at the specified position in the data set.
             return null ;
         }
                                                                                                                             
     }

这里面没什么难度,但是这个getView方法必须好好处理,也是最麻烦的

第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式

1
2
3
4
5
6
7
8
9
10
11
12
@Override
         public View getView(int position, View convertView, ViewGroup parent) {
             View item = mInflater.inflate(R.layout.list_item, null );
             ImageView img = (ImageView)item.findViewById(R.id.img)
             TextView title = (TextView)item.findViewById(R.id.title);
             TextView info = (TextView)item.findViewById(R.id.info);
             img.setImageResource(R.drawable.ic_launcher);
             title.setText( "Hello" );
             info.setText( "world" );
                                                                                                                         
             return item;
         }

第二种ListView优化:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public View getView(int position, View convertView, ViewGroup parent) {
             if (convertView == null )
             {
                 convertView = mInflater.inflate(R.layout.list_item, null );
             }
                                                                                             
             ImageView img = (ImageView)convertView.findViewById(R.id.img)
             TextView title = (TextView)convertView.findViewById(R.id.title);
             TextView info = (TextView)ConvertView.findViewById(R.id.info);
             img.setImageResource(R.drawable.ic_launcher);
             title.setText( "Hello" );
             info.setText( "world" );
                                                                                             
             return convertView;
         }

第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)

如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。

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
//在外面先定义,ViewHolder静态类
static class ViewHolder
{
     public ImageView img;
     public TextView title;
     public TextView info;
}
//然后重写getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
     ViewHolder holder;
     if (convertView == null )
     {
         holder = new ViewHolder();
         convertView = mInflater.inflate(R.layout.list_item, null );
         holder.img = (ImageView)item.findViewById(R.id.img)
         holder.title = (TextView)item.findViewById(R.id.title);
         holder.info = (TextView)item.findViewById(R.id.info);
         convertView.setTag(holder);
     } else
     {
         holder = (ViewHolder)convertView.getTag();
     }
         holder.img.setImageResource(R.drawable.ic_launcher);
         holder.title.setText( "Hello" );
         holder.info.setText( "World" );
     }
                                                                                                 
     return convertView;
}

到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了

在这里,官方给出了解释

提升Adapter的两种方法

To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary

(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary

(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked

(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们

要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())

实例:用BaseAdapter来自定义ListView布局
main.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version= "1.0" encoding= "utf-8" ?>
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     android:layout_width= "fill_parent"
     android:layout_height= "fill_parent"
     android:orientation= "vertical" >
     <ListView
         android:id= "@+id/lv"
         android:layout_width= "fill_parent"
         android:layout_height= "wrap_content"
         android:fastScrollEnabled= "true"
         />
</LinearLayout>

list_item.xml

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
<?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= "horizontal" >
     <ImageView
         android:id= "@+id/img"
         android:layout_width= "wrap_content"
         android:layout_height= "wrap_content"
         />
     <LinearLayout
         android:layout_width= "fill_parent"
         android:layout_height= "wrap_content"
         android:orientation= "vertical"
         >
         <TextView
             android:id= "@+id/tv"
             android:layout_width= "wrap_content"
             android:layout_height= "wrap_content"
             android:textSize= "20sp"
         />
         <TextView
             android:id= "@+id/info"
             android:layout_width= "wrap_content"
             android:layout_height= "wrap_content"
             android:textSize= "14sp"
             />
     </LinearLayout>
                                                             
</LinearLayout>

Activity

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.loulijun.demo17;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class Demo17Activity extends Activity {
     private ListView lv;
     private List<Map<String, Object>> data;
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
         lv = (ListView)findViewById(R.id.lv);
         //获取将要绑定的数据设置到data中
         data = getData();
         MyAdapter adapter = new MyAdapter( this );
         lv.setAdapter(adapter);
     }
                                                     
     private List<Map<String, Object>> getData()
     {
         List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
         Map<String, Object> map;
         for (int i=0;i<10;i++)
         {
             map = new HashMap<String, Object>();
             map.put( "img" , R.drawable.ic_launcher);
             map.put( "title" , "跆拳道" );
             map.put( "info" , "快乐源于生活..." );
             list.add(map);
         }
         return list;
     }
                                                     
     //ViewHolder静态类
     static class ViewHolder
     {
         public ImageView img;
         public TextView title;
         public TextView info;
     }
                                                     
     public class MyAdapter extends BaseAdapter
     {  
         private LayoutInflater mInflater = null ;
         private MyAdapter(Context context)
         {
             //根据context上下文加载布局,这里的是Demo17Activity本身,即this
             this .mInflater = LayoutInflater.from(context);
         }
         @Override
         public int getCount() {
             //How many items are in the data set represented by this Adapter.
             //在此适配器中所代表的数据集中的条目数
             return data.size();
         }
         @Override
         public Object getItem(int position) {
             // Get the data item associated with the specified position in the data set.
             //获取数据集中与指定索引对应的数据项
             return position;
         }
         @Override
         public long getItemId(int position) {
             //Get the row id associated with the specified position in the list.
             //获取在列表中与指定索引对应的行id
             return position;
         }
                                                         
         //Get a View that displays the data at the specified position in the data set.
         //获取一个在数据集中指定索引的视图来显示数据
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             ViewHolder holder = null ;
             //如果缓存convertView为空,则需要创建View
             if (convertView == null )
             {
                 holder = new ViewHolder();
                 //根据自定义的Item布局加载布局
                 convertView = mInflater.inflate(R.layout.list_item, null );
                 holder.img = (ImageView)convertView.findViewById(R.id.img);
                 holder.title = (TextView)convertView.findViewById(R.id.tv);
                 holder.info = (TextView)convertView.findViewById(R.id.info);
                 //将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag
                 convertView.setTag(holder);
             } else
             {
                 holder = (ViewHolder)convertView.getTag();
             }
             holder.img.setBackgroundResource((Integer)data.get(position).get( "img" ));
             holder.title.setText((String)data.get(position).get( "title" ));
             holder.info.setText((String)data.get(position).get( "info" ));
                                                             
             return convertView;
         }
                                                         
     }
}

运行结果如下:

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值