Gallery ImageAdapter ConvertView 始终为 null

发布于 2024-12-09 07:03:26 字数 1193 浏览 1 评论 0原文

我正在使用带有 ImageAdapter 的 Gallery 来加载 ImageViews,从我的资源中提取图像。我的问题是,传递给我的适配器中的 getView() 方法的 ConvertView 始终为 null。这意味着每次调用 getView() 时都会创建一个新的 ImageView。这会导致可怕的性能,因为 GC 会不断运行以擦除所有这些已创建且不再使用的 ImageView。

这显然是一个已知错误:图库的视图缓存已损坏;从不转换视图。

我的两个首选解决方案是: 1. 处理适配器本身中的视图缓存,并处理正确重用它们所需的所有逻辑。 或 2. 包含我自己的 Gallery 小部件副本并尝试修复它,以便它正确返回回收的视图。

我已经开始实施选项一,但很快意识到我并不完全知道如何构建该操作背后的所有逻辑。我开始认为选项二可能更容易。

我在这里找到了图库小部件的代码:http://grepcode.com /file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/widget/Gallery.java

我不完全理解,但我可以看到它正在

child = mAdapter.getView(position, null, this);

第 745 行调用。我(在黑暗中猜测)猜测这是问题的根源。

有没有人有这个错误的经验。或者任何人都可以为我指出正确的方向,以弄清楚回收商的情况如何工作,以便我可以调整这个小部件以使其正常工作?或者甚至建议一些我可能会忽略的替代选项。

编辑:我发现的最好的解决方案是一个名为 EcoGallery 的实现。我可以在线找到参考的唯一地方是这里。为了让它工作,你必须将其中的每个块放在项目中的正确位置。

I am using a Gallery with an ImageAdapter to load it with ImageViews that pull images out of my resources. My problem is that the convertView that gets passed to the getView() method in my adapter is always null. This means that a new ImageView is created each and every time getView() is called. This leads to horrible preformance because the GC is constantly running to wipe away all of these created and no longer used ImageView's.

This is apparently a known bug: Gallery's view cache is broken; never converts views..

My two preferred solutions are either 1. handle a cache of views in the adapter itself and take care of all the logic required to re-use them properly.
or 2. include a my own copy of the Gallery widget and try to fix it so it properly returns recycled views.

I've started implementing option one but am quickly realizing I don't exactly know how to make all of the logic behind that operation. I am begining to think that option two might be easier.

I've found the code for the Gallery widget here: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/widget/Gallery.java

I don't fully understand it, but I can see that it is calling

child = mAdapter.getView(position, null, this);

on line 745. My (shot in the dark) guess that this is the root of the problem.

Does anyone have experience with this bug. Or can anyone point me in the right direction for figuring out how the recycler situation works so that I can tweak this widget to work correctly? Or even suggest some alternate option that I may be overlooking.

EDIT: The best solution that I ever found was an implementation called EcoGallery. The only place I can find reference to it online anymore is here. To get it working you have to put each chunk from there in the correct place within your project.

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

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

发布评论

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

评论(3

别靠近我心 2024-12-16 07:03:26

没有特别遇到该错误的经验,但我之前已经使用第 3 方视图寻呼机(在支持库之前)完成了自定义缓存。

说实话,这真的不是太难。就我而言,我知道屏幕上最多只会显示一项。但我还希望预加载左侧和右侧的项目(这些是从网络上提取数据的网络视图)。所以我有一个包含 3 个视图的简单数组。

[V1, V2, V3]

现在您唯一需要做的就是将适配器中的位置与缓存中的位置相关联。有多种方法可以解决这个问题。当我第一次发现它时,我只是将当前视图设置为 V2,并在翻转寻呼机时旋转数组的项目。因此,翻转到下一个视图会改变我的数组

[V2, V3, V1]

,很容易跟上。或者您可以只进行数学计算并计算缓存相对位置的位置。

另一种方法是创建后进先出队列。通过将视图推入队列来回收视图,当您需要视图时,只需从其中弹出一个视图即可。

No experience with that bug particularly, but I have done custom caching before with a 3rd party view pager (before the support lib).

It's really not too difficult honestly. In my case, I knew there would be, at most, one item on the screen. But I also wanted the item to the left and right to be preloaded (these were webviews pulling data off the net). So I have a simple array of 3 views.

[V1, V2, V3]

Now the only thing you need to do is correlate a position in your adapter to a position in your cache. There's a variety of ways you could tackle this. When I first spiked it out, I just made whatever my current view was to be V2 and the rotated the items of the array around when flipping the pager. So flipping to the next view would alter my array

[V2, V3, V1]

Was simple to keep up with. Or you could just do the math and calculate a position to a relative position of the cache.

Another approach is to create a last in, first out queue. Recycle views by pushing them into the queue, and when you need a view, just pop one from it.

溺渁∝ 2024-12-16 07:03:26

我没有使用 Gallery 小部件的经验,但我经常使用带有图像的 ListView。根据你的问题,并链接到Google问题,他们仍然没有解决这个问题。

因此,有一个带有不错的库(以及其中的示例)的解决方案,可以解决缓存/ajax 问题等等。

链接到

,或者更具体地说,链接到图片示例

如果您下载他们的示例,您会发现他们如何使用 AQuery 实用程序通过 Gallery 小部件实现画廊班级在

com.androidquery.test.image.ImageLoadingGalleryActivity 类。

代码片段:

    final List<Photo> entries;// here only to show what enteries are...

    listAq = new AQuery(this); //define as Action class member, here only to show what it is

    ArrayAdapter<Photo> aa = new ArrayAdapter<Photo>(this, R.layout.gallery_item, entries){

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

            if(convertView == null){
                convertView = getLayoutInflater().inflate(R.layout.gallery_item, parent, false);
            }

            Photo photo = getItem(position);

            AQuery aq = listAq.recycle(convertView);

            aq.id(R.id.name).text(photo.title);

            String tbUrl = photo.tb;

            if(!aq.shouldDelay(position, convertView, parent, tbUrl)){
                aq.id(R.id.tb).image(tbUrl);
                aq.id(R.id.text).text(photo.title).gone();
            }else{
                aq.id(R.id.tb).clear();
                aq.id(R.id.text).text(photo.title).visible();
            }


            return convertView;

        }


    };

    aq.id(R.id.gallery).adapter(aa);

其中 Photo 只是 POJO 对象(从远程获取):

class Photo {
    String tb;
    String url;
    String title;
    String author;
}

R.id.gallery 指的是

 <Gallery
        android:id="@+id/gallery"
        android:layout_width="fill_parent"
        android:layout_height="200dip" />

R.layout.gallery_item 指的是:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="100dip"
        android:layout_height="75dip" >

        <ProgressBar
            android:id="@+id/progress"
            android:layout_width="15dip"
            android:layout_height="15dip"
            android:layout_centerInParent="true" />

        <ImageView
            android:id="@+id/tb"
            style="@style/GalleryItem"
            android:layout_width="100dip"
            android:layout_height="75dip" />

        <TextView
            android:id="@+id/text"
            android:layout_width="100dip"
            android:layout_height="75dip"
            android:gravity="center"
            android:maxLines="4"
            android:padding="15dip"
            android:text="Dummy TextDummy TextDummy TextDummy TextDummy Text"
            android:textColor="#FFFFFFFF"
            android:textSize="8sp" />

    </RelativeLayout>

希望您会发现这个库对解决您的问题很有用。

I do not have experience with Gallery widget, but I'am using a lot ListView with images. According to your problem, and link to Google issue, they still haven't fix this problem.

So, there is solutio with nice library (and examples within it), which solve cache/ajax problems, and much more.

Link to library

or, more concrete, link to image examples

If you download their examples, you will find how they implemented gallery with Gallery widget, using their AQuery utility class in

com.androidquery.test.image.ImageLoadingGalleryActivity class.

Snippet from code:

    final List<Photo> entries;// here only to show what enteries are...

    listAq = new AQuery(this); //define as Action class member, here only to show what it is

    ArrayAdapter<Photo> aa = new ArrayAdapter<Photo>(this, R.layout.gallery_item, entries){

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

            if(convertView == null){
                convertView = getLayoutInflater().inflate(R.layout.gallery_item, parent, false);
            }

            Photo photo = getItem(position);

            AQuery aq = listAq.recycle(convertView);

            aq.id(R.id.name).text(photo.title);

            String tbUrl = photo.tb;

            if(!aq.shouldDelay(position, convertView, parent, tbUrl)){
                aq.id(R.id.tb).image(tbUrl);
                aq.id(R.id.text).text(photo.title).gone();
            }else{
                aq.id(R.id.tb).clear();
                aq.id(R.id.text).text(photo.title).visible();
            }


            return convertView;

        }


    };

    aq.id(R.id.gallery).adapter(aa);

Where Photo is just POJO object (fetched from remote):

class Photo {
    String tb;
    String url;
    String title;
    String author;
}

R.id.gallery refers to

 <Gallery
        android:id="@+id/gallery"
        android:layout_width="fill_parent"
        android:layout_height="200dip" />

And R.layout.gallery_item refers to:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="100dip"
        android:layout_height="75dip" >

        <ProgressBar
            android:id="@+id/progress"
            android:layout_width="15dip"
            android:layout_height="15dip"
            android:layout_centerInParent="true" />

        <ImageView
            android:id="@+id/tb"
            style="@style/GalleryItem"
            android:layout_width="100dip"
            android:layout_height="75dip" />

        <TextView
            android:id="@+id/text"
            android:layout_width="100dip"
            android:layout_height="75dip"
            android:gravity="center"
            android:maxLines="4"
            android:padding="15dip"
            android:text="Dummy TextDummy TextDummy TextDummy TextDummy Text"
            android:textColor="#FFFFFFFF"
            android:textSize="8sp" />

    </RelativeLayout>

Hope you'll find this library useful in solving your problem.

请止步禁区 2024-12-16 07:03:26

我已经按照 dskinner 的建议使用自定义缓存解决了这个问题。

我预先计算(项目的屏幕宽度/最小宽度)一次可以在屏幕上的图库中显示的最大项目数,并添加更多项目(图库将需要额外的内容来显示左侧和右侧的项目)滚动浏览它)。我创建了一个这种大小的数组 - 视图根据请求创建并放置在缓存中。使用position % cachesize 来确定调用 getView 时要返回哪个缓存视图。

I've gotten around this by using a custom cache as dskinner suggests.

I pre-calculate (screenwidth/minwidth of item) the max # of items that can be show in the gallery on the screen at one time and add a few more (the gallery will need extra to show items on the left and right as you scroll thru it). I create an array of this size - the views get created as requested and placed in the cache. Use position % cachesize to figure out which cached view to return when getView is called.

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