在 GridView 中显示联机视频持续时间



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

我尝试在网格视图适配器之外使用此代码:

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()因为仅返回屏幕上可以看到的内容的计数,并且当用户由于回收而滚动时,此计数将重置。当用户在持续时间完全填充后滚动时,没有任何问题,但原因是这发生在后台,用户应该能够随时滚动,并且仍然在正确的视频上设置正确的持续时间,我该如何实现?我想过根本不使用回收,但我知道这对性能不利。希望我说得有道理。

适配器的 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传递给它,而不是子索引。

最新更新