Android:重用 gridview 中的嵌入视图 [已发布解决方案]

发布于 2024-12-25 01:44:06 字数 4640 浏览 3 评论 0原文

我正在尝试重用其中包含图像和文本视图的框架布局,但我认为我做得不对。代码有效并且显示正确,但性能非常差,我相信这是因为每次适配器返回到项目位置时我都会创建一个新的 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;
}

I am trying to reuse a framelayout that has an image and textview inside it but I don't think I am doing this right. The code works and the display is right but the performance is very poor and I believe it is because I creating a new ImageView and TextView every time the adapters goes back to the item position.

Can someone tell me how to reuse the embedded ImageView (called i) and TextView (called t) without creating new objects? I am very new to Java and this is my attempt at building a Android application.

        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;  

        }  
    } 

Thank you in advance!

[EDIT]

--------------------------- SOLUTION -----------------------------------------------------

Here is solution that I implemented based on the feedback below! Thank you!

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

煮茶煮酒煮时光 2025-01-01 01:44:06
  1. 不要为每个元素动态创建视图,而是创建一个 XML 布局文件(例如 row.xml)。
  2. 如果您检测到 convertView == null 使用 inflater 膨胀新行
  3. 使用 View#findViewById 定位您的 TextView 和 ImageView
  4. 创建一个 Holder 对象,该对象将帮助保存对新找到的 TextView 和 ImageView 的引用
  5. 将 Holder 保存为标签所以 convertView.setTag(holder)
  6. 对于现有的convertView,通过执行 holder = ConvertView.getTag() 找到 Holder 对象,
  7. 为这两个保存的设置文本和图像对象,例如 holder.txt.setText("Foo")
  8. Android 适配器将完成剩下的工作,直至重用膨胀行的实例

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

  1. Instead of dynamically creating your View for each element create an XML layout file, say row.xml.
  2. If you detect that convertView == null inflate new row by using inflater
  3. Locate your TextView and ImageView using View#findViewById
  4. Create a Holder object which will help hold references to your newly found TextView and ImageView
  5. Save holder as a tag so convertView.setTag(holder)
  6. For existing convertView find Holder object by doing holder = convertView.getTag()
  7. Set text and image for these two saved objects, e.g. holder.txt.setText("Foo")
  8. Android adapter will do the rest as far as reusing instances of inflated rows

Arguably even for your code you can do view initialization and layout once and use Holder pattern to avoid re-initialization of the elements but I think XML will give you better experience

等风来 2025-01-01 01:44:06

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

在您的代码中,

  • 您不应该每次都创建一个新的持有者对象!相反,您应该仅当您的convertView = null 时创建一个新的viewholder,然后将其保存在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;

}

我从这个网站

The solution you provided is not accurate. The ViewHolder is mainly used to avoid inflating the view and calling findViewById() more than once.

In your code,

  • You should not create a new holder object every time! Instead, you should create a new viewholder only when your convertView = null, then save it in the ReturnThisView tag. If the convertView is not null, then you should load that viewholder you saved before.

  • You avoided inflating the view, so well done (y), but you still use findViewById(). Only use findViewById() when convertView = null and you are initializing the views in the view holder. If convertView is not null, then just use the saved views in the viewHolder object you loaded.

Here is an example:

 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;

}

I learned it from this site.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文