奇怪的 ArrayAdapter 行为

发布于 2024-10-08 13:23:57 字数 1814 浏览 4 评论 0原文

我正在为基于 Android 的平板电脑编写一个应用程序。虽然我在开发方面已经取得了很大的进展,但有一个我不理解且无法消除的错误。我有一个带有自定义 ArrayAdapter 的 GridView,其中包含一些可下载的项目。该网格中的每个项目都是可单击的相对布局,如下所示:

<RelativeLayout>
  <FrameLayout />
  <TextView />
  <TextView />
  <ProgressBar />   
</RelativeLayout>

单击某个项目时,应用程序将尝试在 SD 卡上找到它并显示它。如果失败,它将开始在自己的线程中下载。文件下载方法是非常标准的,除了两件事 - 如前所述,它有自己的线程,并且在下载每个数据块(目前为 2048 字节)后更新进度栏:

while ((n = in.read(b,0,chunkSize)) >= 0) {
    out.write(b,0,n);

    if (handler != null && progressbar != null) {
        /* Update progressbar:*/
        currentBytes += n;
        final int nbytes = currentBytes;
        handler.post(new Runnable() {
            public void run() {
                progressbar.setProgress(nbytes);
            }
        });
    }
}

这完美地工作出色地。这是它在现实世界中的样子(点击第三个图标后;这些项目只是占位符,但下载的文件是真实的):

[我无法发布图像(没有足够的代表),所以这里有一个链接]

< a href="http://i52.tinypic.com/20zb8jq.png" rel="nofollow">http://i52.tinypic.com/20zb8jq.png

同时我可以开始第二个下载它仍然可以完美运行。我还可以在最后添加元素,它也会起作用。然而,有一个小问题。每当我使用启动新活动的搜索按钮并返回到此活动时,相同的网格视图将如下所示:

[我无法发布图像,只有一个超链接(没有足够的代表),所以这里有一个链接一个空格]

http://i54.tinypic.com/16kqgxg.png

它仍在下载正确的元素,它只是显示错误的进度条。下载完成后该杂志仍会显示。另一个不需要的效果是所有项目,甚至那些正在下载和带有进度条的项目,都设置为可点击(我在开始下载之前禁用它)。这是更新适配器的代码(有点缩短,但没关系):

List<Magazine> newList = cm.getMyMags(); // Returns a list of current magazines
List<Magazine> oldList = cachedAdapter.mags; // I use List.toArray() method in getView in Adapter.

for (Magazine mag : newList) {
    if (!oldList.contains(mag)) {
        cachedAdapter.add(mag);
    }
}

我知道这不是最有效的方法,但现在我关心的只是让它工作。
我尝试更新列表本身并调用notifyDataSetChanged(),但它给出了完全相同的结果。 有谁知道什么可能会导致这个问题?

感谢您抽出时间。

I'm writing an application for Android-based tablets. While I have come very far in development, there is one bug I don't understand and can't get rid of. I have a GridView with a custom ArrayAdapter, which contains some downloadable items in it. Each item in this grid is a clickable relative layout, which looks something like this:

<RelativeLayout>
  <FrameLayout />
  <TextView />
  <TextView />
  <ProgressBar />   
</RelativeLayout>

When an item is clicked, the app will try to find it on sd-card and show it. If it fails, then it will start downloading it in it's own thread. File-downloading method is very standard, except for two things things - it has, as said, it's own thread and it updates progress-bar after downloading each data-chunk (which, at this moment, is 2048 bytes):

while ((n = in.read(b,0,chunkSize)) >= 0) {
    out.write(b,0,n);

    if (handler != null && progressbar != null) {
        /* Update progressbar:*/
        currentBytes += n;
        final int nbytes = currentBytes;
        handler.post(new Runnable() {
            public void run() {
                progressbar.setProgress(nbytes);
            }
        });
    }
}

This works perfectly well. Here's how it looks like in the real world (after clicking on 3rd icon; these items are just placeholders, but the downloaded files are real):

[I couldn't post an image (not enough rep), so here's a link]

http://i52.tinypic.com/20zb8jq.png

In the same time I can start a second download and it will still work perfectly. I can also add elements at the end and it will work too. There is a slight problem, however. Whenever I use a search button, which starts a new activity, and go back to this activity, same gridview will look like this:

[I couldn't post an image and only one hyperlink (not enough rep), so here's a link with a space]

http:// i54.tinypic.com/16kqgxg.png

It's still downloading the right element, it just shows the wrong progressbar. The magazine will still be shown after downloading completes. Another unwanted effect is that ALL items, even those downloading and with progress bars, are set to be clickable (I disable it before starting downloading). Here is the code (a bit shortened, but it doesn't matter) updating the adapter:

List<Magazine> newList = cm.getMyMags(); // Returns a list of current magazines
List<Magazine> oldList = cachedAdapter.mags; // I use List.toArray() method in getView in Adapter.

for (Magazine mag : newList) {
    if (!oldList.contains(mag)) {
        cachedAdapter.add(mag);
    }
}

I know it's not the most efficient way to do this, but right now all I care about is making it work.
I tried to update the list itself and call notifyDataSetChanged(), but it gave exactly the same results.
Does anyone know what might cause this problem?

Thank you for your time.

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文