`
yidongkaifa
  • 浏览: 4097591 次
文章分类
社区版块
存档分类
最新评论

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


分享到:
评论

相关推荐

    Android-滑动listview标题置顶listview吸顶效果

    在Android应用开发中,UI设计和用户体验是至关重要的部分,特别是在构建列表视图(ListView)时。本知识点主要探讨如何实现“滑动ListView时标题置顶”和“ListView吸顶效果”,以及如何使安卓系统状态栏透明化。这些...

    android ListView实现显示微信好友列表

    在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据,比如微信的好友列表。本教程将详细介绍如何利用ListView来实现一个类似微信好友列表的界面,同时也会涉及到自定义ImageView和ListView的相关...

    Android ListView边框圆角美化

    在Android开发中,ListView是常用的一种控件,用于展示大量数据列表。为了提升用户体验和界面设计的美观性,我们常常需要对ListView进行定制化,包括设置边框和实现圆角效果。本文将深入探讨如何在Android中实现...

    android listview内存优化

    在Android开发中,ListView是展示大量数据常用的组件,但如果不进行优化,很容易引发内存溢出和界面卡顿问题,特别是当列表中包含大图时。本文将深入探讨如何对ListView进行内存优化,确保10M级别的图片加载时,应用...

    android--ListView实现带标题栏效果(附源码)

    在Android开发中,ListView是一种常用的UI组件,常用于展示大量数据列表。本教程将详细介绍如何在ListView中实现带标题栏的效果。标题栏通常用于显示分类信息或者操作按钮,为用户提供更好的交互体验。以下是对实现...

    安卓listview相关相关-android-swipelistview-支持左右滑动.rar

    在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。`android-swipelistview`是专门为ListView设计的一个开源库,它扩展了ListView的功能,增加了左右滑动的效果,使得用户可以更加直观地进行操作...

    Android实现的ListView-ListViewAdapter(新闻列表事例)

    综上所述,"Android实现的ListView-ListViewAdapter(新闻列表事例)"是一个涵盖了Android基础组件使用、数据绑定、事件处理、性能优化等多个方面的实践案例,对于深入理解Android开发非常有帮助。通过这个实例,...

    android之listview优化+分类显示

    总结来说,优化ListView主要在于提高滚动时的流畅性,减少不必要的资源消耗,而分类显示则需要灵活运用Adapter和数据结构,创建不同类型的View来展示不同的数据。这两者结合,可以让用户在使用应用时有更好的体验。...

    android两列显示两个listview

    在Android开发中,有时我们需要在一个布局中同时展示两个ListView,以实现类似网格或者并排比较的效果。这个场景在处理比如对比列表数据、显示多类别信息等时非常常见。标题"android两列显示两个listview"指的就是...

    Android中Listview分页显示

    在Android开发中,ListView是一种常用的组件,用于展示大量的数据列表,比如联系人、消息等。然而,如果一次性加载所有数据,不仅会消耗大量内存,也可能导致应用运行缓慢。因此,通常采用分页加载(Pagination)的...

    Android ListView性能优化

    在Android开发中,ListView是应用中最常用的控件之一,它用于展示大量的数据列表。然而,随着数据量的增加,ListView可能会出现性能问题,如滚动不流畅、内存消耗过大等。因此,对ListView进行性能优化至关重要。...

    Android ListView选中高亮显示

    在Android开发中,ListView是一种常用的组件,用于展示大量的列表数据。ListView的一大特点就是可以实现滚动效果,节省内存,同时提供良好的用户体验。当我们需要在用户点击ListView的某一项时,让它有明显的视觉...

    Android代码-管理图书分类通过listview来显示有关图书资源信息.zip

    这个"Android代码-管理图书分类通过listview来显示有关图书资源信息.zip"的压缩包,显然提供了一种实例,教我们如何利用ListView来管理图书分类,显示图书资源的相关信息。以下将详细解释这个主题中的关键知识点。 ...

    Android之ListView列表视图实现

    在Android开发中,ListView是展示大量数据的一种常见视图组件,尤其适用于菜单、选项列表等场景。本资源提供了一个完整的Android应用示例,专门讲解如何实现ListView及其交互功能。 首先,ListView的基础在于...

    安卓listview相关相关-Android--ListView返回第一条数据的实现.rar

    在Android开发中,ListView是一个非常重要的组件,常用于展示大量数据列表。本资源"安卓listview相关相关-Android--ListView返回第一条数据的实现.rar"主要关注如何实现在ListView中快速定位到第一条数据。以下是对...

    【Android开发学习29】界面控件之列表控件(ListView)--显示图片和文本

    在Android应用开发中,ListView是十分重要的界面控件,它用于展示可滚动的多项数据,通常用于实现数据列表。在本教程中,我们将深入探讨如何在ListView中同时显示图片和文本,这对于创建用户友好的界面至关重要。 ...

    安卓listview相关相关-android ListView实现显示微信好友列表.rar

    在Android开发中,ListView是一个非常重要的组件,常用于展示大量数据列表,如微信好友列表。本教程将聚焦于如何在Android应用中实现一个类似于显示微信好友列表的ListView。以下是关于ListView及其相关知识点的详细...

    Android的widget使用listview布局

    ListView是一种常用的布局管理器,它允许用户在一个滚动列表中显示大量数据。本教程将深入探讨如何在Android Widget中集成ListView布局,以便在小部件上展示动态、可滚动的数据。 首先,为了创建一个包含ListView的...

    Android-用ListView模仿ExpandableListView

    在Android开发中,ListView是一种常用的组件,用于展示可滚动的列表数据。然而,有时我们希望实现更复杂的列表,比如带有可折叠子项的列表,这时ExpandableListView就派上用场了。不过,如果我们只需要使用ListView...

    android-ListView

    在Android应用开发中,ListView是不可或缺的一个组件,它主要用于展示数据列表,允许用户滚动查看多个条目。ListView的灵活性和可扩展性使得它在各种场景下都能发挥重要作用,如显示天气预报、联系人列表、邮件收件...

Global site tag (gtag.js) - Google Analytics