Android 在GridView中显示在线视频持续时间

Android 在GridView中显示在线视频持续时间,android,Android,我使用FTP客户端从服务器获取视频并在gridview上显示它们。我还想显示每个gridview项目(视频)的持续时间 我尝试在gridview适配器之外使用以下代码: for (FTPFile file : files) { if (file.isFile()) { //GetDuration try{

我使用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();
无论如何,这一切都很好,直到用户在arrListStr_持续时间完全填充之前开始滚动,然后持续时间将设置在错误的视频上,因为视图被回收

现在,在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)
                {
                    //
                }
            }
...
@覆盖
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
//TODO自动生成的方法存根
保持架=新保持架();
if(convertView==null)
{
convertView=充气机。充气(R.layout.activity\u video\u gridview\u single\u复选框,空);
}
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())
{
//完成填充的持续时间
holder.tvDuration.setText(stringArr_Duration[位置]);
}
其他的
{
//持续时间仍在填充时用户滚动
试一试{
对于(int i=0;i

这也会混淆持续时间和视频,因为
gv.getChildCount()
仅返回屏幕上可看到的内容的计数,当用户因循环使用而滚动时,此计数会重置。当用户在持续时间完全填充后滚动时,则不会出现问题,但这是在后台发生的,用户应该能够随时滚动,并且仍然具有正确的持续时间在正确的视频上,我如何才能做到这一点?我想过根本不使用回收,但我知道这对性能有害。希望我讲得通。

适配器的getView()文档

当用户在持续时间完全填充后滚动时,则不存在任何问题。>

这是因为在本例中,您正确地使用了
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.
}
私有字符串getVideoDuration(int索引){

如果(索引stringArr_Duration.length在从getView()调用时为null)-FFmpegMediaMetadataRetriever提取持续时间需要一些时间这就是为什么,您建议的方法在可以从服务器获取视频持续时间之前运行确定,因此我修改了您的代码并创建了一个全局int变量来保持位置,以便在返回NullPointerException或ArrayIndexOut时可以再次调用该方法对于BoundsException,现在它可以正常工作,除非我离开活动转到另一个活动(我完成了活动)然后返回到它的持续时间再次混淆,但当从开始启动应用程序时,一切正常,我不明白,因为当我返回到它时,活动被破坏,那么当我启动活动时,它的行为应该像我从开始启动应用程序一样?我有意义吗?总结上述内容,当我启动应用程序并单击我的VideoActivity您修改的代码运行良好,当我单击OtherActivity并返回VideoActivity时,某些视频的持续时间变得混乱。当我关闭应用程序并从头开始运行并单击VideoActivity时,一切正常,直到我选择任何其他活动,然后返回VideoActivity。@param position不应保存在全局范围内,如果stringArr_Duration为null,则我认为这意味着视频的持续时间还不可用,那么显示其持续时间没有意义,因此您可以安全地从我的方法返回空字符串。TURBO BOOST的原因:只要GridView需要显示项,就会调用适配器的getView()(初始加载以及每次用户滚动时)。参数位置被传递并故意保留为“最终”以从基础数据集中识别相应的视图。幕后GridView将获取此视图并在@param位置显示给您。因此,这不是进行不必要处理的地方,绝对不是进行异常处理的地方。
* @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);
 private String getVideoDuration(int index){
    if(index <= stringArr_Duration.length)
        return stringArr_Duration[index];
    return null; // can return empty string also here.
}