【问题标题】:how could I improve the appearance of ListView我怎样才能改善 ListView 的外观
【发布时间】:2011-07-27 13:59:34
【问题描述】:

目前我面临以下问题 - 我创建了一个自定义 ListView (1 x ImageView + 2 x 文本视图)。它显示来自 I-net 的内容,这是一个 XML 文件。

我在做什么 - 我正在使用 AsyncTask 在后台运行下载 XML 内容并通过调用 ListView 的过程>publishProgress(...) 方法用于 doInBackground(...) 方法中的每个列表项。当 doInBackground(...) 完成时,我已经收集了我想要显示的每个图像的 URL,然后从 onPostExecute(...) 方法我开始下载图像并为每个下载的图像更新 UI。对我来说问题是 ListView 在开始下载可绘制文件并更新列表之前应该至少填写一些项目。目前 ListView 显示单个项目,当填充下一个项目时,所有图像都已下载。我调试了应用程序,我看到我在 onPostExecute(...) 方法中停止了一个并想要获取 ListView 项的数量,它只返回一个,正如它所显示的那样。

有没有办法在开始下载之前强制出现 Listview 的项目,或者这是因为我拥有的 I-net 连接足够好,下载没有延迟图片。

我忘了只提到每张图片都不超过 10KB。

这是我的自定义AsyncTask

private class DownloadFilesTask extends AsyncTask<String, Object, List<RSSItem>> {
        protected void onPreExecute() {
            super.onPreExecute();

            la.clear();
        }
        protected List<RSSItem> doInBackground(String... urls) {
            parse(urls[0]);

            if (feed == null) { return null; }

            rssList = feed.getAllItems();
            Iterator<RSSItem> iterator = rssList.iterator();

            while(iterator.hasNext()) {
                if (isCancelled()) return null; 
                RSSItem rss = iterator.next();
                publishProgress(rss);
            }

            return rssList;
        }
        protected void onProgressUpdate(Object... progress) {
            super.onProgressUpdate(progress);

            la.add((RSSItem)progress[0]);
            la.notifyDataSetChanged();
        }
        protected void onPostExecute(List<RSSItem> result) {
            super.onPostExecute(result);

            Drawable downloadedImage;
            for (int z = 0; z < rssList.size(); z++) {
                downloadedImage = downloadImage(rssList.get(z).getImageURL());
                ((RSSItem)rssList.get(z)).setImage(downloadedImage);
                la.notifyDataSetChanged();
            }
        }
        protected void onCancelled() {
            super.onCancelled();
        }
    }

这是自定义 Listadapter

private class ListAdapter extends ArrayAdapter<RSSItem> {

        private List<RSSItem> items;

        public ListAdapter(Context context, int textViewResourceId, List<RSSItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

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

            if (v == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.list_item, null);
            }

            RSSItem item = items.get(position);

            if (item != null) {
                ImageView itemImage = (ImageView) v.findViewById(R.id.ivImage);
                TextView title = (TextView) v.findViewById(R.id.tvTitle);
                TextView description = (TextView) v.findViewById(R.id.tvDescription);
                if (item.getImage() != null) {
                    itemImage.setBackgroundDrawable(item.getImage());
                } else {
                    itemImage.setBackgroundDrawable(getResources().getDrawable(R.drawable.icon));
                }
                if (title != null) {
                    title.setText(item.getTitle());
                }
                if (description != null) {
                    description.setText(item.getDescription());
                }
            }

            return v;
        }
    }

...和 ​​Item 类:

public class RSSItem {
    private String data = null;
    private String description = null;
    private Drawable image = null;
    private String imageUrl = null;
    private String title = null;

    RSSItem() {
    }

    public void setData(String data) {
        this.data = data;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setImageURL(String imageURL) {
        this.imageUrl = imageURL;
    }

    public void setImage(Drawable image) {
        this.image = image;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getData() {
        return data;
    }

    public String getDescription() {
        return description;
    }

    public Drawable getImage() {
        return image;
    }

    public String getImageURL() {
        return imageUrl;
    }

    public String getTitle() {
        return title;
    }
}

@修改:

私有类 DownloadFilesTask 扩展 AsyncTask> { 受保护的无效onPreExecute(){ super.onPreExecute();

        la.clear();
    }

    protected List<RSSItem> doInBackground(String... urls) {
        parse(urls[0]);

        if (feed == null) { return null; }

        rssList = feed.getAllItems();
        publishProgress(true);

        Drawable downloadedImage;
        for (int z = 0; z < rssList.size(); z++) {
            downloadedImage = downloadImage(rssList.get(z).getImageURL());
            ((RSSItem)rssList.get(z)).setImage(downloadedImage);
        }
        return rssList;
    }

    protected void onProgressUpdate(Object... progress) {
        super.onProgressUpdate(progress);

        la.notifyDataSetChanged();
    }

    protected void onPostExecute(List<RSSItem> result) {
        super.onPostExecute(result);

        la.notifyDataSetChanged();
    }

    protected void onCancelled() {
        super.onCancelled();
    }
}

【问题讨论】:

    标签: android listview user-interface


    【解决方案1】:

    我不确定我是否理解您的问题,但我会做以下事情(如果我做对了):

    我想您有一个存储在 ListView 中的自定义对象,比如说 CustomItem。 我会将下载的 URL Image 放在该对象的构造函数中,并将 Drawable 存储为 CustomItem 的成员。在您创建了一个新的 CustomItem 并为其获取图像之后,publishProgress() 并在您的列表适配器上调用 notifyDataSetChanged()

    编辑:您应该将代码从 onPostExecute() 方法移到 doInBackground() 方法的末尾。

    试试这个:

    private class DownloadFilesTask extends AsyncTask<String, RSSItem, Void> {
        protected void onPreExecute() {
            super.onPreExecute();
            la.clear();
        }
        protected List<RSSItem> doInBackground(String... urls) {
            parse(urls[0]);
    
            if (feed == null) { return null; }
            rssList = feed.getAllItems();
            Iterator<RSSItem> iterator = rssList.iterator();
    
            while(iterator.hasNext()) {
                if (isCancelled()) return null; 
                RSSItem rss = iterator.next();
                //this happens fast no need to do this
                publishProgress(rss);
                //la.add(rss);
            }
            Drawable downloadedImage;
            for (int z = 0; z < rssList.size(); z++) {
                downloadedImage = downloadImage(rssList.get(z).getImageURL());
                ((RSSItem)rssList.get(z)).setImage(downloadedImage);
                publishProgress(null);
            }
            return rssList;
        }
        protected void onProgressUpdate(RSSItem... progress) {
            super.onProgressUpdate(progress);
            if progress!=null
               la.add((RSSItem)progress[0]);
            la.notifyDataSetChanged();
        }
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
    
        }
        protected void onCancelled() {
            super.onCancelled();
        }
    }
    

    【讨论】:

    • 好吧,你误解了我想做什么。首先我已经得到了你所说的这个并且它正在工作,但我不想下载图像并将其填充到 ListView 中。我只想填充文本,并且有一个默认的静态图像将代替原始图像出现。 doInBackground 完成后,它会向 onPostExecute 返回一个值,然后我将下载所有图像。您可以通过我分享的来源在上面看到它。
    • 好的。我现在明白了。 doBackground 中的代码将很快完成,问题是您在 postExecute() 中执行代码中耗时的部分,它将在 UIThread 上运行并阻塞您的 UI。检查我编辑的答案。
    • 你的意思是把这两行代码从onProgressUpdate(...)移到doInBackground(...)之前return陈述。如果是这样,它会生成一个异常。另外我不确定我是否可以从 doInBackground(...) 调用 notifyDataSetChanged(...),它们分别针对两种不同的威胁运行 doInBackground(...) - 关于背景威胁和 notifyDataSetChanged(...) 关于 UI 威胁
    • 仔细阅读我的编辑。 onPostExecute 中的代码也将它移到 doInBackground 中。再次尝试使用标志或其他信息调用 onProgressUpdate(),以了解您这次不需要添加 RssItem。
    • 对不起,我对onPostExecute(...)的理解有误,但是还是不行,这次不用la.add((RSSItem).....),里面什么都没有列表视图!你能证明你的想法吗?您可能还想看看我对 AsyncTask 类做了什么?请参阅@MODIFICATIONS >>
    【解决方案2】:

    您是否在doInBackground() 中填充列表适配器的基础数据集?那么,除了调用publishProgress()之外,你还需要在你的AsyncTaskonProgressUpdate()中调用adapter.notifyDataSetChanged()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 2022-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多