其实这里的复用技术在列表中是十分常见的,iphone中的tableView也有相关的技术,cell的复用
工作原理:
- ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
- 一个新的视图被返回并显示
如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!
实际上Android为你缓存了视图。
Android中有个叫做Recycler的构件,下图是他的工作原理:

- 如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。
- ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。
- 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。
下面给出一个实例,这个例子实现的是资源管理器:
请看实现截图:
下面给出具体的实现代码:
1.总体布局文件
<?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"
android:background="@drawable/white"
>
<TextView
android:id="@+id/mPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5px"
android:textSize="18sp"
android:textColor="@drawable/blue"
/>
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
2.既然有ListView,当然需要子View的布局文件
<?xml version="1.0" encoding="utf-8"?>
<!-- 每一个ListView中的TetxView都是这样布局的 -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView android:id="@+id/icon"
android:layout_width="30dip"
android:layout_height="30dip"
/>
<TextView android:id="@+id/text"
android:layout_gravity="center_vertical"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:textColor="@drawable/black"
/>
</LinearLayout>
3.自定义的Adapter,为ListView提供数据显示
public class MyAdapter extends BaseAdapter
{
private LayoutInflater mInflater;
private Bitmap mIcon1;
private Bitmap mIcon2;
private Bitmap mIcon3;
private Bitmap mIcon4;
//每一项的名字和每一项的路径名
private List<String> items;
private List<String> paths;
public MyAdapter(Context context,List<String> it,List<String> pa)
{
mInflater = LayoutInflater.from(context);
items = it;
paths = pa;
mIcon1 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.back01);
mIcon2 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.back02);
mIcon3 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.folder);
mIcon4 = BitmapFactory.decodeResource(context.getResources(),
R.drawable.doc);
}
@Override
public int getCount()
{
return items.size();
}
@Override
public Object getItem(int position)
{
return items.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
/*
* 使用的是优化版本,则返回的一定是convertView,且一般都是固定的模式
* 注意:这里只是设置View的样式,并不包含相应的实现功能
* @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
*/
@Override
public View getView(int position,View convertView,ViewGroup parent)
{
ViewHolder holder;
if(convertView == null)
{
convertView = mInflater.inflate(R.layout.file_row, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
// public void setTag (Object tag)
// Added in API level 1
// Sets the tag associated with this view. A tag can be used to mark a view in its hierarchy and does not have to be unique within the hierarchy. Tags can also be used to store data within a view without resorting to another data structure.
//
// Parameters
// tag an Object to tag the view with
convertView.setTag(holder);
}
else
{
// public Object getTag ()
// Added in API level 1
// Returns this view's tag.
//
// Returns
// the Object stored in this view as a tag
holder = (ViewHolder) convertView.getTag();
}
//存储文件的名称和文件的路径
File f=new File(paths.get(position).toString());
if(items.get(position).toString().equals("b1"))
{
holder.text.setText("Back to /");
holder.icon.setImageBitmap(mIcon1);
}
else if(items.get(position).toString().equals("b2"))
{
holder.text.setText("Back to ..");
holder.icon.setImageBitmap(mIcon2);
}
else
{
//这时这一项是文件或者是文件夹
holder.text.setText(f.getName());
if(f.isDirectory())
{
holder.icon.setImageBitmap(mIcon3);
}
else
{
holder.icon.setImageBitmap(mIcon4);
}
}
return convertView;
}
/*
* ListView中子View是什么样的格式,这个类就定义成什么样的模式
*/
/* class ViewHolder */
private class ViewHolder
{
TextView text;
ImageView icon;
}
}
4.主程序文件
public class EX05_11 extends ListActivity
{
/* 变量声明
items:存放显示的名称
paths:存放文件路径
rootPath:起始目录 */
private List<String> items=null;
private List<String> paths=null;
private String rootPath="/";
private TextView mPath;
@Override
protected void onCreate(Bundle icicle)
{
super.onCreate(icicle);
/* 加载main.xml Layout */
setContentView(R.layout.main);
/* 初始化mPath,用以显示目前路径 */
mPath=(TextView)findViewById(R.id.mPath);
getFileDir(rootPath);
}
/* 取得文件架构的method */
private void getFileDir(String filePath)
{
/* 设定目前所存路径 */
mPath.setText(filePath);
items=new ArrayList<String>();
paths=new ArrayList<String>();
File f=new File(filePath);
//找到f下的所有文件的列表
File[] files=f.listFiles();
if(!filePath.equals(rootPath))
{
/* 第一笔设定为[并到根目录] */
items.add("b1");
paths.add(rootPath);
/* 第二笔设定为[并到上一层] */
items.add("b2");
paths.add(f.getParent());
}
/* 将所有文件存入ArrayList中 */
for(int i=0;i<files.length;i++)
{
File file=files[i];
items.add(file.getName());
paths.add(file.getPath());
}
/* 使用自定义的MyAdapter来将数据传入ListActivity */
setListAdapter(new MyAdapter(this,items,paths));
}
/* 设定ListItem被按下时要做的动作 */
@Override
protected void onListItemClick(ListView l,View v,int position,long id)
{
File file=new File(paths.get(position));
if(file.canRead())
{
if (file.isDirectory())
{
/* 如果是文件夹就运行getFileDir() */
getFileDir(paths.get(position));
}
else
{
/* 如果是文件就运行openFile() */
openFile(file);
}
}
else
{
/* 弹出AlertDialog显示权限不足 */
new AlertDialog.Builder(this)
.setTitle("Message")
.setMessage("权限不足!")
.setPositiveButton("OK",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
}
}).show();
}
}
/* 手机打开文件的method */
private void openFile(File f)
{
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
/* 调用getMIMEType()来取得MimeType */
String type = getMIMEType(f);
/* 设定intent的file与MimeType */
intent.setDataAndType(Uri.fromFile(f),type);
startActivity(intent);
}
/* 判断文件MimeType的method */
private String getMIMEType(File f)
{
String type="";
String fName=f.getName();
/* 取得扩展名 */
String end=fName.substring(fName.lastIndexOf(".")+1,
fName.length()).toLowerCase();
/* 依扩展名的类型决定MimeType */
if(end.equals("m4a")||end.equals("mp3")||end.equals("mid")||
end.equals("xmf")||end.equals("ogg")||end.equals("wav"))
{
type = "audio";
}
else if(end.equals("3gp")||end.equals("mp4"))
{
type = "video";
}
else if(end.equals("jpg")||end.equals("gif")||end.equals("png")||
end.equals("jpeg")||end.equals("bmp"))
{
type = "image";
}
else
{
type="*";
}
/* 如果无法直接打开,就弹出软件列表给用户选择 */
//在后缀中并没有加入后缀
type += "/*";
return type;
}
}
分享到:
相关推荐
在Android应用开发中,UI设计和用户体验是至关重要的部分,特别是在构建列表视图(ListView)时。本知识点主要探讨如何实现“滑动ListView时标题置顶”和“ListView吸顶效果”,以及如何使安卓系统状态栏透明化。这些...
在Android开发中,ListView是常用的一种控件,用于展示大量数据列表。为了提升用户体验和界面设计的美观性,我们常常需要对ListView进行定制化,包括设置边框和实现圆角效果。本文将深入探讨如何在Android中实现...
在Android开发中,有时我们需要在一个布局中同时展示两个ListView,以实现类似网格或者并排比较的效果。这个场景在处理比如对比列表数据、显示多类别信息等时非常常见。标题"android两列显示两个listview"指的就是...
在Android开发中,ListView是一种常用的UI组件,常用于展示大量数据列表。本教程将详细介绍如何在ListView中实现带标题栏的效果。标题栏通常用于显示分类信息或者操作按钮,为用户提供更好的交互体验。以下是对实现...
在Android开发中,ListView是展示大量数据常用的组件,但如果不进行优化,很容易引发内存溢出和界面卡顿问题,特别是当列表中包含大图时。本文将深入探讨如何对ListView进行内存优化,确保10M级别的图片加载时,应用...
ListView是一种常用的布局管理器,它允许用户在一个滚动列表中显示大量数据。本教程将深入探讨如何在Android Widget中集成ListView布局,以便在小部件上展示动态、可滚动的数据。 首先,为了创建一个包含ListView的...
总结来说,优化ListView主要在于提高滚动时的流畅性,减少不必要的资源消耗,而分类显示则需要灵活运用Adapter和数据结构,创建不同类型的View来展示不同的数据。这两者结合,可以让用户在使用应用时有更好的体验。...
在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。`android-swipelistview`是专门为ListView设计的一个开源库,它扩展了ListView的功能,增加了左右滑动的效果,使得用户可以更加直观地进行操作...
综上所述,"Android实现的ListView-ListViewAdapter(新闻列表事例)"是一个涵盖了Android基础组件使用、数据绑定、事件处理、性能优化等多个方面的实践案例,对于深入理解Android开发非常有帮助。通过这个实例,...
在Android开发中,ListView是一个非常常见的组件,用于展示大量数据列表。然而,由于ListView需要频繁地创建和销毁视图(View)以适应用户的滚动操作,这可能会导致性能问题。为了解决这个问题,开发者通常会使用...
在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表,比如联系人、消息等。然而,如果一次性加载所有数据,不仅会消耗大量内存,也可能导致应用运行缓慢。因此,通常采用分页加载(Pagination)的...
在Android开发中,ListView是应用中最常用的控件之一,它用于展示大量的数据列表。然而,随着数据量的增加,ListView可能会出现性能问题,如滚动不流畅、内存消耗过大等。因此,对ListView进行性能优化至关重要。...
在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。ListView的一大特点就是可以实现滚动效果,节省内存,同时提供良好的用户体验。当我们需要在用户点击ListView的某一项时,让它有明显的视觉...
这个"Android代码-管理图书分类通过listview来显示有关图书资源信息.zip"的压缩包,显然提供了一种实例,教我们如何利用ListView来管理图书分类,显示图书资源的相关信息。以下将详细解释这个主题中的关键知识点。 ...
在Android应用开发中,ListView是常用的组件之一,用于展示大量数据列表。本篇文章将深入探讨如何在Android中编写ListView列表选项栏,包括使用系统默认的ListView以及自定义multiple ListView的方法。 首先,...
在Android开发中,ListView是展示大量数据的一种常见视图组件,尤其适用于菜单、选项列表等场景。本资源提供了一个完整的Android应用示例,专门讲解如何实现ListView及其交互功能。 首先,ListView的基础在于...
在Android开发中,ListView是一个非常重要的组件,常用于展示大量数据列表。本资源"安卓listview相关相关-Android--ListView返回第一条数据的实现.rar"主要关注如何实现在ListView中快速定位到第一条数据。以下是对...
在Android应用开发中,ListView是十分重要的界面控件,它用于展示可滚动的多项数据,通常用于实现数据列表。在本教程中,我们将深入探讨如何在ListView中同时显示图片和文本,这对于创建用户友好的界面至关重要。 ...
在Android开发中,ListView是一个非常重要的组件,常用于展示大量数据列表,如微信好友列表。本教程将聚焦于如何在Android应用中实现一个类似于显示微信好友列表的ListView。以下是关于ListView及其相关知识点的详细...
这个“Android--开发--PopupWindow下拉列表”资源包可能包含了一系列示例代码和教程,帮助开发者深入理解和运用PopupWindow来创建下拉列表。 首先,PopupWindow是Android SDK中的一个类,继承自View类,它提供了...