我正在尝试将网址中的视频缩略图加载到网格视图中 . 一切正常,但我收到这条消息“/编舞:跳过46帧!应用程序可能在其主线程上做了太多工作 . ”
我知道它与主线程中的缩略图加载有关,但我无法找到如何解决这个问题 .
我也在使用设备进行测试 .
public class ThumbAdapter extends ArrayAdapter<Videos> {
Context context;
int ressource;
ThumbAdapter_Holder holder=new ThumbAdapter_Holder();
public ThumbAdapter(Context context, int resource, ArrayList<Videos> videoList) {
super(context, resource, videoList);
this.context=context;
this.ressource=resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view=convertView;
if (view==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(ressource,parent,false);
holder.video_thum = (ImageView) view.findViewById(R.id.video_thum);
view.setTag(holder);
}
else {
holder=(ThumbAdapter_Holder) view.getTag();
}
try {
holder.video_thum.setImageBitmap(retriveVideoFrameFromVideo(getItem(position).getURL()));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return view;
}
class ThumbAdapter_Holder{
ImageView video_thum ;
}
public static Bitmap retriveVideoFrameFromVideo(String videoPath) throws Throwable {
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try
{
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
// mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
}
catch (Exception e)
{
e.printStackTrace();
throw new Throwable(
"Exception in retriveVideoFrameFromVideo(String videoPath)"
+ e.getMessage());
} finally {
if (mediaMetadataRetriever != null) {
mediaMetadataRetriever.release();
}
}
return bitmap;
}
}
1 回答
问题是,您正在请求和处理适配器的每个单元格中的数据 .
那是罪魁祸首 . 您正在主线程(管理UI)中执行昂贵的非图形化任务 . 为了优化,您需要将这种操作移动到单独的线程,并通知在主线程内执行的类结果,以便它可以更新UI . 有几种方法可以做到这一点:Asynctasks,Observers,Event bus . 为了简单起见,让我们使用asynctask .
以此为例:
然后,你应该做这样的事情,而不是try-catch .
请记住,这种操作会忽略主线程状态;这意味着,即使应用程序处于休眠状态,单独的线程也会继续运行并执行,因此,如果应用程序转到前台,您需要使侦听器/取消订阅接收器无效 . 快乐的编码 .