其实这里的复用技术在列表中是十分常见的,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中的ListView控件的优化方法.pdf
Android应用开发中ListView组件性能优化的研究.pdf
Android ListView的优化,在做Android项目的时候,在用到ListView 界面及数据显示,这个时候如果资源过大,对项目来说,用户体验肯定是不好的,这里就对如何优化做了详细介绍: Adapter的作用就是ListView界面与数据...
|--ListView优化之控制getView实现复杂显示 |--ListView优化之标准写法 |--listview老虎机 界面设计 水果机 |--listview页面跳转 数据库交互 事务 dao biz 层 |--Log的收集 |--Manager下的info |--Manager之...
实用Android开发工具和资源精选 APK权限大全 - Android必懂知识 最无私的Android资料(书籍+代码)分享[总结] Android中文帮助教程(非常合适新手入门) android程序编写及调试新手入门 大家一起学Android(Windows...
Android控件ListView的使用及优化技巧.pdf
Android中的ListView组件原理分析与优化.pdf
《Android开发案例驱动教程》 配套代码。 注: 由于第12,13,14章代码太大,无法上传到一个包中。 这三节代码会放到其他压缩包中。 作者:关东升,赵志荣 Java或C++程序员转变成为Android程序员 采用案例驱动模式...
ListView是Android开发中最常用的控件之一,但在使用Adapter的时候若不进行合理的优化,容易造成资源浪费、代码冗余的情况,导致开发出来的APP性能低下。经过合理的封装后,项目中使用到的多个ListView能够复用同一...
1.5 使用Android SDK开发最终用户应用程序 1.5.1 Android模拟器 1.5.2 Android UI 1.5.3 Android基础组件 1.5.4 高级UI概念 1.5.5 Android Service组件 1.5.6 Android媒体和电话组件 1.5.7 ...
1.直接在XML中创建ListView用entries属性附上一个数组资源 其中divider属性是设置分割线可以使用颜色和drawable资源分割 <ListView android:id=@+id/listView1 android:layout_width=match_parent android:...
PropertyValuesHolder->相对于直接使用ObjectAnimator方法资源更优化 AnimatorSet->可以按指定的顺序执行动画,而不是同时执行(Animator不可重用) ValueAnimator->可以完全自定义自己的动画 FloatMenu 说明:...
第1章 Android计算平台简介 1.1 面向新PC的全新平台 1.2 Android的历史 1.3 Dalvik VM剖析 1.4 理解Android软件栈 1.5 使用Android SDK开发最终用户应用程序 1.5.1 Android模拟器 1.5.2 ...
java smack源码 优秀推荐:、 本着开源的精神,无私奉献自己的代码好的优秀博客添加也会陆续更新中.... ...Android插件化开发与动态加载 Android 热更新 安卓开发值得关注的库 安卓资源相关 git Androi
学习资源来自于幕课网,非常好的学习AsyncTask的例子,并且作者讲解了ListView的优化技巧,非常实用,值得一赞! ### 学习微信的设计,你会发现一些不一样的细节。 说实话,微信一直是应该学习的模楷,很多方面都...
可以作为本地相册按照时间的顺序进行列表,也可以作为按照日期进行listview列表,例如支付宝账单的形式,资源工程没有进行优化,功能都可以使用
Android系统本身有很多的资源,包括各种各样的字符串、图片、动画、样式和布局等等,这些都可以在应用程序中直接使用。这样做的好处很多,既可以减少内存的使用,又可以减少部分工作量,也可以缩减程序安装包的大小...