【问题标题】:Android: Reusing embedded views in gridview [Solution Posted]Android:在 gridview 中重用嵌入式视图 [已发布解决方案]
【发布时间】:2012-01-02 23:19:17
【问题描述】:

我正在尝试重用其中包含图像和文本视图的框架布局,但我认为我做的不对。代码有效,显示正确,但性能很差,我相信这是因为每次适配器回到项目位置时我都会创建一个新的 ImageView 和 TextView。

谁能告诉我如何在不创建新对象的情况下重用嵌入的 ImageView(称为 i)和 TextView(称为 t)?我对 Java 很陌生,这是我构建 Android 应用程序的尝试。

        public View getView(int position, View convertView, ViewGroup parent) {  

            FrameLayout F;
            FrameLayout ImageBorder;
            FrameLayout TextBG;

            ImageView i;
            TextView t;

            if(convertView == null) {
                F = new FrameLayout(mContext);

            } else {
                F = (FrameLayout) convertView;
            }

            ImageBorder = new FrameLayout(F.getContext());
            FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,300,Gravity.BOTTOM);
            ImageBorder.setLayoutParams(params1);

            i = new ImageView(F.getContext()); 
            TextBG = new FrameLayout(F.getContext());
            t = new TextView(F.getContext());

            F.setBackgroundColor(Color.BLACK);
            ImageBorder.setPadding(2, 2, 2, 2);
            ImageBorder.setBackgroundColor(Color.BLACK);

            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,40,Gravity.BOTTOM);

            TextBG.setLayoutParams(params);
            TextBG.setBackgroundColor(Color.BLACK);
            TextBG.setAlpha(.6f);

            t.setLayoutParams(params);

            t.setGravity(Gravity.CENTER_VERTICAL);

            String pathToPhoto = FileList.get(position).toString();
            String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");

            fileDescription = fileDescription.replaceAll(".jpg","");
            fileDescription = fileDescription.toUpperCase();


            Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);

             if (bm == null) {
                ImageDownloader downloader = new ImageDownloader(i);
                downloader.execute("thumb", pathToPhoto, "400", "400");
             } else {

                i.setImageBitmap(bm);
                i.setScaleType(ImageView.ScaleType.CENTER_CROP);

                t.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
                t.setText(" " + fileDescription);

             }

             ImageBorder.addView(i);
             ImageBorder.addView(TextBG);
             ImageBorder.addView(t);

             F.addView(ImageBorder);

             return F;  

        }  
    } 

提前谢谢你!

[编辑]

-------------- 解决方案---------------- -------------------------------------

这是我根据以下反馈实施的解决方案!谢谢!

        public View getView(int position, View convertView, ViewGroup parent) {  

            View ReturnThisView;
            ViewHolder holder;

            LayoutInflater inflater;
            holder = new ViewHolder();

            if(convertView == null) {
                inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                ReturnThisView = inflater.inflate(R.layout.imagecell, null);
                ReturnThisView.setTag(holder);
            } else {
                ReturnThisView = convertView;
            }

            holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc);
            holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail);

            String pathToPhoto = FileList.get(position).toString();
            String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");

            fileDescription = fileDescription.replaceAll(".jpg","");
            fileDescription = fileDescription.toUpperCase();

            Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);

             if (bm == null) {
                ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail);
                downloader.execute("thumb", pathToPhoto, "400", "400");
             } else {

                holder.ImageThumbnail.setImageBitmap(bm);
                holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);

                holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
                holder.TextDescription.setText(" " + fileDescription);

             }

             return ReturnThisView;
        }  
    }

    static class ViewHolder {
    TextView TextDescription;
    ImageView ImageThumbnail;
}

【问题讨论】:

    标签: android gridview android-imageview android-framelayout


    【解决方案1】:
    1. 不要为每个元素动态创建视图,而是创建一个 XML 布局文件,比如 row.xml。
    2. 如果您检测到convertView == null 使用inflater 为新行充气
    3. 使用 View#findViewById 定位您的 TextView 和 ImageView
    4. 创建一个 Holder 对象,该对象将帮助保存对新找到的 TextView 和 ImageView 的引用
    5. 将持有人保存为标签,以便convertView.setTag(holder)
    6. 对于现有的 convertView,通过 holder = convertView.getTag() 查找 Holder 对象
    7. 为这两个保存的对象设置文本和图像,例如holder.txt.setText("Foo")
    8. Android 适配器将完成剩下的工作,即重复使用膨胀行的实例

    可以说,即使对于您的代码,您也可以执行一次视图初始化和布局,并使用 Holder 模式来避免重新初始化元素,但我认为 XML 会给您带来更好的体验

    【讨论】:

    • 非常感谢您的帮助!我已经将这个解决方案实现了一半,但我不知道持有者对象是什么以及如何实现。是一个允许我同时保存图像和文本视图的对象吗?我试图寻找解释,但找不到任何关于使用 Holder 对象的好信息。
    • 重申一下 - Holder(或您决定给它起的任何名称)是一个简单的 POJO(数据)对象,用于保存引用。在复杂的情况下,我通常会在 Holder 中添加一些行为,例如 reset() 方法
    【解决方案2】:

    您提供的解决方案不准确。 ViewHolder 主要用于避免膨胀视图和多次调用 findViewById()。

    在您的代码中,

    • 您不应该每次都创建一个新的持有者对象!相反,您应该仅在您的 convertView = null 时创建一个新的视图,然后将其保存在 ReturnThisView 标记中。如果convertView 不为null,那么你应该加载你之前保存的那个viewholder。

    • 您避免膨胀视图,做得很好 (y),但您仍然使用 findViewById()。仅当 convertView = null 并且您正在初始化视图持有者中的视图时才使用 findViewById()。如果 convertView 不为 null,则只需使用您加载的 viewHolder 对象中保存的视图即可。

    这是一个例子:

     public View getView(int position, View convertView, ViewGroup parent) {  
    
            View ReturnThisView;
            ViewHolder holder;
    
            LayoutInflater inflater;
    
    
            if(convertView == null) {
                inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                ReturnThisView = inflater.inflate(R.layout.imagecell, null);
                holder = new ViewHolder();
                holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc);
                holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail);
                ReturnThisView.setTag(holder);
            } else {
                ReturnThisView = convertView;
                holder = (ViewHolder)ReturnThisView.getTag();
            }
    
    
    
            String pathToPhoto = FileList.get(position).toString();
            String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/","");
    
            fileDescription = fileDescription.replaceAll(".jpg","");
            fileDescription = fileDescription.toUpperCase();
    
            Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto);
    
             if (bm == null) {
                ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail);
                downloader.execute("thumb", pathToPhoto, "400", "400");
             } else {
    
                holder.ImageThumbnail.setImageBitmap(bm);
                holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
    
                holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large);
                holder.TextDescription.setText(" " + fileDescription);
    
             }
    
             return ReturnThisView;
        }  
    }
    
    static class ViewHolder {
    TextView TextDescription;
    ImageView ImageThumbnail;
    

    }

    我是从这个site学到的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 2010-10-06
      相关资源
      最近更新 更多