Android就业面试技巧系列-技术篇7 (ListView优化)
来源:互联网 发布:独立思考 知乎 编辑:程序博客网 时间:2024/06/06 19:34
Android就业面试技巧系列-技术篇(ListView优化)
UI优化:
listview条目与条目之间的间隙的分割内容 : android:divider="@android :color/transparent"
listview条目之间的间隙 : android:paddingTop="5.0dip"
listview点中的颜色变化 : android:listSelector="@color/transparent"
如果listview有很多个条目 ,在listview的右边 会显示出来一个快速滚动的进度条 :
android:fastScrollEnabled="true"(listview里面的条目至少要滚动5个屏幕以上)
android:scrollbarStyle="outsideOverlay"
android:scrollbars="none"
footer view
header view
快速拖动时候的悬浮提示(window manager)
数据适配性能优化:
a.传统方式:
复用历史缓存的view对象, convertView 减少 采用布局填充器服务 填充布局的次数,达到减少xml->view 操作的次数.
定义了静态的viewholder 储存了 view对象里面控件的引用, view.setTag() view.getTag(); 减少遍历view对象 树状结构的次数.
b.采用了内存缓存,缓存一些经常使用的数据:
服务器上的图片,缓存这些图片,(缓存手机的Rom卡,sd卡)利用softreference把图片给缓存到内存里面;
再比如缓存从数据库中查询出的所有数据,减少查询数据库的动作
c.高级需求:
listview的延时加载:
如果listview里面要显示的有很多的数据, 我们不需要一次把所有的数据都获取出来.
分段的方式 一段一段的把数据下载下来.
注册listview的 onScrollListener(); 发现最后一个可见的条目 为listview里面数据适配器里面的最后的一个条目, 加载更多的内容. listview的分页显示:
服务器需要提供接口, 一次获取一段的数据.
数据库提供接口 ,一次查询一段的数据.
listview的快速拖动的问题:
当listview在滚动状态下,不去加载listview里面真实的图片和内容,而是把一个缩略图加载界面上.
当listview的滚动状态停止的时候 才去真正的更新里面的条目的内容.
如何让你的ListView实现自动滚动呢? Android其实已经考虑到ListView控件的智能滚动操作。
直接在Layout中写即可,注意下面的stackFromBottom以及transcriptMode这两个属性。涉及代码如下:
[Java] 纯文本查看 复制代码
1
2
3
4
5
<ListView[/align]android:id=
"listCWJ"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:stackFromBottom=
"true"
android:transcriptMode=
"alwaysScroll"
/>
复用历史缓存的view对象 convertView ,定义了静态的viewholder 储存了 view对象里面控件的引用,以下为代码:
下面为显示每条数据的xml文件:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"horizontal"
>
<ImageView
android:id=
"@+id/icon"
android:layout_width=
"48dip"
android:layout_height=
"48dip"
/>
<TextView
android:id=
"@+id/text"
android:layout_gravity=
"center_vertical"
android:layout_width=
"0dip"
android:layout_weight=
"1.0"
android:layout_height=
"wrap_content"
/>
</LinearLayout>
Adapter中getView方法代码:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
static
class
ViewHolder{
TextView text;
ImageView icon;
}
public
View getView(
int
position, View convertView, ViewGroup parent){
ViewHolder holder;
if
(convertView ==
null
) {
convertView = mInflater.inflate(R.layout.list_item,
null
);
holder =
new
ViewHolder();
holder.text = (TextView)convertView.findViewButId(R.id.icon));
holder.icon =(ImageView)convertView.findViewButId(R.id.icon));
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((pos &
1
) ==
1
? mIcon1 :mIcon2);
return
convertView;
}
ListView调用Adapter的getView方法获取每一个Item布局,将这些已经获得的Item布局放入缓存,不仅可以提高程序的反应速度,而且可以节省许多流量,将数据进行缓存有两种方法是:一种是将sd卡缓存,另一种是内存缓存,在此分别进行演示。
sd卡缓存:
sd卡缓存是将下载的数据保存到sd卡中,当需要再次使用数据时,就先判断sd卡中是否存在这些数据,如果存在的话,就直接从sd卡中读取,如果不存在的话就从网上下载,然后保存到sd卡中。
内存缓存:
内存优化是将获取到的数据存入到Map集合中,如果再次引用此数据,就直接从Map集合中获取,这样会导致一个问题,如果Map集合中的数据特别多,比如存 取了100万条数据,这样有可能就会导致内存溢出。这是因为Map集合是强引用的集合,如何不把Map集合置为空的话,这个集合Java虚拟机就不会把它 回收掉,当Map中的数据大小超过了内存大小就会导致内存溢出。为了避免这种异常我们要使用软引用softreference,软引用和强引用的区别如 下:
1、softreference 他是java虚拟机给我们提供的一个包装类型。
在包装类型里面的对象,一般情况下,java虚拟机会尽量长时间的保留这个对象。
当java虚拟机内存不足的时候,java虚拟机就会回收softreference里面的对象。
在包装类型里面的对象,一般情况下,java虚拟机会尽量长时间的保留这个对象。
当java虚拟机内存不足的时候,java虚拟机就会回收softreference里面的对象。
2、hardreference 默认new出来的对象都是这种强应用的类型。
只要一个对象还保留的有引用,他就不会被垃圾回收。
Map<String,Bitmap> map;
只要一个对象还保留的有引用,他就不会被垃圾回收。
Map<String,Bitmap> map;
sd卡缓存:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
public
class
MyReadAdapter
extends
BaseAdapter {[/align]
private
List<CollectionEntry> entrys;
public
MyReadAdapter(CollectionFeed feeds) {
entrys = feeds.getEntries();
}
public
int
getCount() {
return
entrys.size();
}
public
Object getItem(
int
position) {
return
entrys.get(position);
}
public
long
getItemId(
int
position) {
return
position;
}
public
View getView(
int
position, View convertView, ViewGroup parent) {
View view = infalter.inflate(R.layout.myread_item,
null
);
final
ImageView iv = (ImageView) view.findViewById(R.id.book_img);
// 获取数据实体
CollectionEntry ce = entrys.get(position);
// 获取图片地址
String iconurl = ce.getSubjectEntry().getLink(
"image"
,
null
).getHref();
int
start = iconurl.lastIndexOf(
"/"
);
int
end = iconurl.length();
final
String iconname = iconurl.substring(start, end);
// Environment.getExternalStorageDirectory()这个是sd卡目录
File file =
new
File(Environment.getExternalStorageDirectory(),
iconname);
// 获取sd卡缓存
if
(file.exists()) {
iv.setImageURI(Uri.fromFile(file));
Log.i(TAG,
"使用sd卡图片"
);
}
else
{
new
LoadImageAsynTask(
new
ImageTaskCallback() {
// 图片获取之后
public
void
onImageLoaded(Bitmap bitmap) {
if
(bitmap !=
null
) {
iv.setImageBitmap(bitmap);
// 把图片存到sd卡上
if
(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try
{
File file =
new
File(Environment
.getExternalStorageDirectory(),
iconname);
FileOutputStream fos =
new
FileOutputStream(
file);
bitmap.compress(CompressFormat.JPEG,
100
, fos);
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
else
{
iv.setImageResource(R.drawable.book);
}
}
// 图片获取之前
public
void
beforeImageLoaded() {
iv.setImageResource(R.drawable.book);
}
}).execute(iconurl);
}
return
view;
}
}
内存缓存:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
Map<String,SoftReference<Bitmap>> map;
public
class
MyReadAdapter
extends
BaseAdapter {
private
List<CollectionEntry> entrys;
public
MyReadAdapter(CollectionFeed feeds) {
entrys = feeds.getEntries();
}
public
int
getCount() {
return
entrys.size();
}
public
Object getItem(
int
position) {
return
entrys.get(position);
}
public
long
getItemId(
int
position) {
return
position;
}
public
View getView(
int
position, View convertView, ViewGroup parent) {
View view = infalter.inflate(R.layout.myread_item,
null
);
final
ImageView iv = (ImageView) view.findViewById(R.id.book_img);
// 获取到数据的实体
CollectionEntry ce = entrys.get(position);
// 获取到图片的Url
String iconurl = ce.getSubjectEntry().getLink(
"image"
,
null
).getHref();
int
start = iconurl.lastIndexOf(
"/"
);
int
end = iconurl.length();
final
String iconname = iconurl.substring(start, end);
// 使用内存缓存
if
(map !=
null
&& map.get(iconname) !=
null
) {
iv.setImageBitmap(map.get(iconname).get());
Log.i(TAG,
"使用内存缓存"
);
}
else
{
new
LoadImageAsynTask(
new
ImageTaskCallback() {
// 图片获取之后
public
void
onImageLoaded(Bitmap bitmap) {
if
(bitmap !=
null
) {
iv.setImageBitmap(bitmap);
// 存放到内存中,
// 软引用类型的bitmap
map.put(iconname,
new
SoftReference<Bitmap>(bitmap));
}
else
{
iv.setImageResource(R.drawable.book);
}
}
// 图片获取之前
public
void
beforeImageLoaded() {
iv.setImageResource(R.drawable.book);
}
}).execute(iconurl);
}
return
view;
}
}
listview的延时加载:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public
class
ListViewForLoading
extends
Activity
implements
OnScrollListener {
private
listViewAdapter adapter =
new
listViewAdapter();
ListView listView;
LinearLayout loadingLayout;
private
Thread mThread;
/**
* 设置布局显示属性
*/
private
LayoutParams mLayoutParams =
new
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
/**
* 设置布局显示目标最大化属性
*/
private
LayoutParams FFlayoutParams =
new
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private
ProgressBar progressBar;
private
Handler handler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
// TODO Auto-generated method stub
switch
(msg.what) {
case
1
:
if
(adapter.count <=
41
) {
adapter.count +=
10
;
int
currentPage = adapter.count /
10
;
Toast.makeText(getApplicationContext(),
"第"
+ currentPage +
"页"
, Toast.LENGTH_LONG).show();
}
else
{
listView.removeFooterView(loadingLayout);
}
//重新刷新Listview的adapter里面数据
adapter.notifyDataSetChanged();
break
;
default
:
break
;
}
}
};
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}
private
void
init() {
// TODO Auto-generated method stub
// 线性布局
LinearLayout layout =
new
LinearLayout(
this
);
// 设置布局 水平方向
layout.setOrientation(LinearLayout.HORIZONTAL);
// 进度条
progressBar =
new
ProgressBar(
this
);
// 进度条显示位置
progressBar.setPadding(
0
,
0
,
15
,
0
);
// 把进度条加入到layout中
layout.addView(progressBar, mLayoutParams);
// 文本内容
TextView textView =
new
TextView(
this
);
textView.setText(
"加载中..."
);
textView.setGravity(Gravity.CENTER_VERTICAL);
// 把文本加入到layout中
layout.addView(textView, FFlayoutParams);
// 设置layout的重力方向,即对齐方式是
layout.setGravity(Gravity.CENTER);
// 设置ListView的页脚layout
loadingLayout =
new
LinearLayout(
this
);
loadingLayout.addView(layout, mLayoutParams);
loadingLayout.setGravity(Gravity.CENTER);
// 得到一个ListView用来显示条目
listView = (ListView) findViewById(R.id.tv);
// 添加到脚页显示
listView.addFooterView(loadingLayout);
// 给ListView添加适配器
listView.setAdapter(adapter);
// 给ListView注册滚动监听
listView.setOnScrollListener(
this
);
}
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
/**[/align] * 要用用于生成显示数据
*
* @author huangbq
*
*/
class
listViewAdapter
extends
BaseAdapter {
int
count =
10
;
public
int
getCount() {
return
count;
}
public
Object getItem(
int
pos) {
return
pos;
}
public
long
getItemId(
int
pos) {
return
pos;
}
public
View getView(
int
pos, View v, ViewGroup p) {
TextView view;
if
(v ==
null
) {
view =
new
TextView(ListViewForLoading.
this
);
}
else
{
view = (TextView) v;
阅读全文
0 0
- Android就业面试技巧系列-技术篇7 (ListView优化)
- Android就业面试技巧系列-技术篇1(内存优化)
- Android就业面试技巧系列-技术篇4(MVP)
- Android就业面试技巧系列-技术篇6 (Handler机制)
- Android就业面试技巧系列-技术篇8 (Volley框架)
- Android就业面试技巧系列-技术篇10 (图片OOM)
- Android就业面试技巧系列-技术篇11 (支付相关)
- Android就业面试技巧系列-技术篇12 (消息推送)
- Android就业面试技巧系列-技术篇2(百度地图)
- Android就业面试技巧系列-技术篇3(屏幕适配)
- Android就业面试技巧系列-技术篇5 (WebView和JS交互)
- Android就业面试技巧系列-技术篇9 (AsyncTask和Handler区别)
- Android ListView优化技巧
- Android ListView优化技巧
- Android优化系列之ListView优化老生常谈
- Android优化系列之ListView优化老生常谈
- android面试重点(一)ListView的优化
- [面试相关] iOS开发就业面试技巧
- 【ML笔记】第三章 线性模型
- 最全三大框架整合(使用映射)——Dept.java
- 物体运动框架
- Shader案例篇二《镜子2》
- poj1474(半平面交)
- Android就业面试技巧系列-技术篇7 (ListView优化)
- 2017第八届浪潮杯山东省赛 K题 codeforces 贪心+背包
- Android中Notification使用及常用属性
- python3.4获取网站40x 50x错误并发邮件通知
- C语言趣味程序(13)
- 最全三大框架整合(使用映射)——Emp.java
- Handler实现Activity和Service通信
- JavaMail 之 搜索邮件
- Android就业面试技巧系列-技术篇8 (Volley框架)