Android--开发资源管理器/优化ListView显示列表方法

来源:互联网 发布:淘宝旺铺必须开通吗 编辑:程序博客网 时间:2024/05/20 02:22

android:ListView中的getView原理

其实这里的复用技术在列表中是十分常见的,iphone中的tableView也有相关的技术,cell的复用

工作原理:

  1. ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
  2. 一个新的视图被返回并显示

如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!

实际上Android为你缓存了视图。

Android中有个叫做Recycler的构件,下图是他的工作原理:


  1. 如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。
  2. ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。
  3. 当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;   }}


原创粉丝点击