`
nanjingjiangbiao_T
  • 浏览: 2593565 次
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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; 
  }
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics