如何更新 GridView / ListView 的每个元素上的 ProgressBar 状态?

发布于 2024-12-15 02:32:43 字数 410 浏览 0 评论 0原文

目前我有一个 GridView,每个元素都应该有一个单独的 ProgressBar。这些元素代表单独的下载,我想使用这些进度条显示下载的状态。

但我应该如何更新它们呢?我的问题是,根据文档(以及我在 Google IO 视频中听到的内容),更新 AdapterViews 中元素的唯一方法是更新分配的适配器,并在每次更新后调用 .notifyDatasetChanged() 。

当然,这在这种情况下也确实有效,但更新非常频繁(5-10 秒更新)。以此频率调用 .notifyDatasetChanged 会中断与 GridView 的任何交互。例如,用户尝试长按网格中的某个项目,但单击事件停止,因为调用了 .notifyDatasetChanged 来更新下载进度。

还有其他方法可以做到这一点吗?我应该放弃 AdapterViews 并使用其他东西吗?

Currently I have a GridView, and every element should have a separate ProgressBar. The elements represent separate downloads, and I'd like to show the state of the downloads using these ProgressBars.

But how should I update them? My problem is, that according to the docs (and what I've heard on the Google IO videos), the only way to update elements in AdapterViews is to update the assigned adapter, and call .notifyDatasetChanged() after every update.

Of course this does actually work in this case too, but the updates are quite frequent (5-10 updates sec). And calling .notifyDatasetChanged in this frequency breaks any interaction with the GridView. E.g. the user tries to long-click on an item in the Grid, but the clicking event stops, because a .notifyDatasetChanged was called to update the progress of a download.

Is there any other way to do this? Should I ditch AdapterViews and use something else?

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

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

发布评论

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

评论(2

仙气飘飘 2024-12-22 02:32:43

对于像您这样频繁更新(每秒多次)的情况,notifyDatasetChanged 不是正确的方法 - 您需要直接更新各个视图。

如果没有看到您的代码以及文件下载和 GridView 中的条目之间的关系,很难准确说出您需要什么调用,但是:

-GridView 有一个“getChildAt”,您可以使用它来获取特定索引处的视图.
- 如果视图甚至不可见,则更新视图是没有意义的。如果它不在 getFirstVisiblePosition() 和 getLastVisiblePosition() 之间,请忽略它,每当重绘时都会使用更新的数据进行绘制。

For situations like yours with many frequent updates (many times a second), notifyDatasetChanged isn't the right way to go - You need to update the individual views directly.

Without seeing your code and the relationship between a file download and an entry in the GridView, it's hard to say exactly what calls you'll need, but:

-GridView has a "getChildAt" you can use to grab a view at a specific index.
-There's no point in updating the view if it's not even visible. If it's not between getFirstVisiblePosition() and getLastVisiblePosition(), ignore it, it'll get drawn with updated data whenever it gets redrawn.

暖阳 2024-12-22 02:32:43

我在一个项目中做到了这一点。如果您使用 Asysctask 而不使用 .notifyDatasetChanged(),则可以更新 UI。例如,我的实用程序中有一个下载方法。类

public static String downloadFile(DownloadItem downItem, AsynBackGroundFileLoader asynBackGroundFileLoader, String fileName,
            String fileURL) {
                // Spiking my code 
            while (bufferLength = inputStream.read(buffer) > 0 ) {
                    fileOutput.write(buffer, 0, bufferLength);
                // add up the size so we know how much is downloaded
                downloadedSize += bufferLength;

                // this is where you would do something to report the progress,
                int pro = ((int) (downloadedSize * 100 / totalSize));

                asynBackGroundFileLoader.updateProgress(pro);

            }
    }

并且在我的 AsyncTask 中,

public class AsynBackGroundFileLoader extends AsyncTask < Void , Integer , String > {



public AsynBackGroundFileLoader (DownloadItem dItem , TableLayout progressBarHodler , UpgradeActivity listener ) {
        try {
            mDownloadingProgressBarHolder = progressBarHodler ;
            this.mDownloadingProgressBarHolder.setVisibility ( View.VISIBLE ) ;

            mDownloadingProgressBar = ( ProgressBar ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_bar ) ;
            downloadCancelButton = ( ImageButton ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_cancel_btn ) ;
            downloadCancelButton.setImageResource ( R.drawable.btn_cancel );

    @ Override
    protected void onPreExecute ( ) {

    }

    @ Override
    protected String doInBackground ( Void ... params ) {

            boolean loadSuccess = Utils.downloadFile ( downItem , this , mFileName , downItem.getLink ( ) ) ;
        return ""+loadSuccess ;
    }

    @ Override
    protected void onPostExecute ( String result ) {

    }

    public void updateProgress ( int progressPercentage ) {
        try {
            if ( progressPercentage < 0 ) {
                progressPercentage = 0 ;
            } else if ( progressPercentage > 100 ) {
                progressPercentage = 100 ;
            }

//Here I am updating my UI without making list to notifyDataChanged()
                currentCompletedProgress = progressPercentage ;
                // This is my progressbar in UI that update , I got this progressbar by passing UI item view in constructor 
                mDownloadingProgressBar.setProgress ( progressPercentage ) ;
                downItem.setTotalProgress ( currentCompletedProgress ) ;
            } catch ( Exception e ) {
                Log.e ( TAG , "Exception = " + e.toString ( ) ) ;
                e.printStackTrace ( ) ;
            }

        }

    public ProgressBar getmDownloadinProgressBar ( ) {
        return mDownloadingProgressBar ;
    }
}

当用户点击列表行时我开始下载

public void onItemClick(AdapterView<?> tempadapter, View view, int position, long arg3) {
    TableLayout table = ((TableLayout) view.findViewById(R.id.downloading_progress_holder));
    DownloadItem temp = adapter.items.get(position);

        AsynBackGroundFileLoader bgdownloader = new AsynBackGroundFileLoader(temp, table, UpgradeActivity.this);
        bgdownloader.execute();
    }

    table.setVisibility(View.VISIBLE);
}

I have done this in one project. You can update the UI if you are using Asysctask without .notifyDatasetChanged(). E.g I have a downloading method in my Utils. class

public static String downloadFile(DownloadItem downItem, AsynBackGroundFileLoader asynBackGroundFileLoader, String fileName,
            String fileURL) {
                // Spiking my code 
            while (bufferLength = inputStream.read(buffer) > 0 ) {
                    fileOutput.write(buffer, 0, bufferLength);
                // add up the size so we know how much is downloaded
                downloadedSize += bufferLength;

                // this is where you would do something to report the progress,
                int pro = ((int) (downloadedSize * 100 / totalSize));

                asynBackGroundFileLoader.updateProgress(pro);

            }
    }

And in my AsyncTask

public class AsynBackGroundFileLoader extends AsyncTask < Void , Integer , String > {



public AsynBackGroundFileLoader (DownloadItem dItem , TableLayout progressBarHodler , UpgradeActivity listener ) {
        try {
            mDownloadingProgressBarHolder = progressBarHodler ;
            this.mDownloadingProgressBarHolder.setVisibility ( View.VISIBLE ) ;

            mDownloadingProgressBar = ( ProgressBar ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_bar ) ;
            downloadCancelButton = ( ImageButton ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_cancel_btn ) ;
            downloadCancelButton.setImageResource ( R.drawable.btn_cancel );

    @ Override
    protected void onPreExecute ( ) {

    }

    @ Override
    protected String doInBackground ( Void ... params ) {

            boolean loadSuccess = Utils.downloadFile ( downItem , this , mFileName , downItem.getLink ( ) ) ;
        return ""+loadSuccess ;
    }

    @ Override
    protected void onPostExecute ( String result ) {

    }

    public void updateProgress ( int progressPercentage ) {
        try {
            if ( progressPercentage < 0 ) {
                progressPercentage = 0 ;
            } else if ( progressPercentage > 100 ) {
                progressPercentage = 100 ;
            }

//Here I am updating my UI without making list to notifyDataChanged()
                currentCompletedProgress = progressPercentage ;
                // This is my progressbar in UI that update , I got this progressbar by passing UI item view in constructor 
                mDownloadingProgressBar.setProgress ( progressPercentage ) ;
                downItem.setTotalProgress ( currentCompletedProgress ) ;
            } catch ( Exception e ) {
                Log.e ( TAG , "Exception = " + e.toString ( ) ) ;
                e.printStackTrace ( ) ;
            }

        }

    public ProgressBar getmDownloadinProgressBar ( ) {
        return mDownloadingProgressBar ;
    }
}

I start downloading when user lick on list row

public void onItemClick(AdapterView<?> tempadapter, View view, int position, long arg3) {
    TableLayout table = ((TableLayout) view.findViewById(R.id.downloading_progress_holder));
    DownloadItem temp = adapter.items.get(position);

        AsynBackGroundFileLoader bgdownloader = new AsynBackGroundFileLoader(temp, table, UpgradeActivity.this);
        bgdownloader.execute();
    }

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