首页 > 解决方案 > 在 GridView 中显示在线视频时长

问题描述

我正在使用 FTP 客户端从服务器获取视频并在 gridview 上显示它们。我也想显示每个 gridview 项目(视频)的持续时间。

我尝试在 gridview 适配器之外使用此代码:

            for (FTPFile file : files) {

                if (file.isFile())
                {
                    //GetDuration
                    try{
                        //NOTE: must not use https
                        mmr = new FFmpegMediaMetadataRetriever();
                        mmr.setDataSource(myDomain+skyVideos+"/"+username+"/"+file.getName());
                        long duration =Long.parseLong(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
                        duration=duration/1000;
                        long minute=duration/(60);
                        long second=duration-(minute*60);
                        mmr.release();

                        strDuration = String.format("%02d:%02d" , minute, second);

                        //ALL VIEWS
                        for (int j = 0; j < gv.getChildCount(); j++) {
                            View child = gv.getChildAt(j);
                            holder.tvDuration = child.findViewById(R.id.tvDuration);                    

                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {

                                    holder.tvDuration.setText(strDuration);
                                }
                            });
                        }


                        arrListStr_Duration.add(strDuration);
                        stringArr_Duration = new String[arrListStr_Duration.size()];
                        stringArr_Duration = arrListStr_Duration.toArray(stringArr_Duration);

                    } catch (IllegalStateException e) {
                      //
                    }catch (IllegalArgumentException e)
                    {
                        //
                    }
                }

                //SORT BY TIMESTAMP
                Arrays.sort(files, Comparator.comparing((FTPFile remoteFile) -> remoteFile.getTimestamp()).reversed());

            }
            client.disconnect();

这工作正常,即使它holder.tvDuration.setText(strDuration);一个接一个地设置视频的持续时间()而不是同时设置(因为 for 循环如何工作?)即使我在后台运行此方法:不过有这个)

        new Thread(new Runnable() {
            @Override
            public void run() {
                //code in background here
                getFTP_Duration();

                getFTP_SizeArray();
            }
        }).start();

无论如何,这一切都很好,直到用户在 arrListStr_Duration 完全填充之前开始滚动,然后持续时间将设置在错误的视频上,因为视图被回收。

现在在 GridView 适配器中,我尝试了以下View getView方法:

@Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub

            holder = new Holder();

            if (convertView == null)
            {
                convertView = inflater.inflate(R.layout.activity_video_gridview_single_checkbox, null);
            }

            holder.ivImage = convertView.findViewById(R.id.ivImage);
            holder.tvInvisibleDate = convertView.findViewById(R.id.tvInvisibleDate);
            holder.ivCheckbox = convertView.findViewById(R.id.ivCheckbox);
            holder.tvDuration = convertView.findViewById(R.id.tvDuration);
            holder.ibDots = convertView.findViewById(R.id.ibDots);
            holder.mypopupWindow = null;

            if (arrListStr_File.size() == arrListStr_Duration.size())
            {
                //Duration finished populating
                holder.tvDuration.setText(stringArr_Duration[position]);
            }
            else
            {
                //user scrolling while duration is still being populated
                try {
                    for (int i = 0; i < gv.getChildCount(); i++) {

                        if (arrListStr_Duration.size() != 0)
                        {

                            View child = gv.getChildAt(i);
                            holder.tvDuration = child.findViewById(R.id.tvDuration);

                            try {
                                holder.tvDuration.setText(stringArr_Duration[i]);
                            }catch (IndexOutOfBoundsException e)
                            {
                                //
                            }
                        }
                    }
                }catch (NullPointerException e)
                {
                    //
                }
            }
...

这也会混淆持续时间和视频,因为gv.getChildCount()只返回可以在屏幕上看到的内容的计数,并且当用户滚动时,由于回收,这个计数会被重置。当用户在持续时间完全填充后滚动时,没有问题,但由于这种情况发生在后台,用户应该能够随时滚动并且仍然在正确的视频上设置正确的持续时间,我该怎么做实现这个?我想过根本不使用回收,但我知道这对性能不利。希望我说得通。

标签: android

解决方案


适配器的 getView() 文档

* @param position The position of the item within the adapter's data set of the item whose view we want.

* @return A View corresponding to the data at the specified position.

View getView(int position, View convertView, ViewGroup parent);

当用户在持续时间完全填充后滚动时,就没有问题了。>

这是因为您position在这种情况下正确使用,而在其他情况下您正在使用子索引,这GridView就是混合视频的原因。

getView()您可以通过创建一种获取视频持续时间的方法来简化您的整个过程。

 private String getVideoDuration(int index){
    if(index <= stringArr_Duration.length)
        return stringArr_Duration[index];
    return null; // can return empty string also here.
}

然后调用它getView()并传递@param : position给它,而不是子索引。


推荐阅读