2016-11-28 10 views
0

urlからビデオのサムネイルをグリッドビューに読み込もうとしています。すべてがうまくいきますが、私はこのメッセージを受け取ります "/振付師:46フレームをスキップしました!アプリケーションはメインスレッドであまりにも多くの作業をしている可能性があります。Android:メインスレッドでアプリケーションが動作している可能性があります。

メインスレッドのサムネイルの読み込みと関係があることは知っていますが、これを修正する方法を見つけることができませんでした。

私もデバイスを使ってテストしています。

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

「mediaMetadataRetriever」の呼び出しの1つは、時間がかかります。この操作をワーカースレッドに移動することを検討してください。 – Egor

+0

https://developer.android.com/reference/android/os/AsyncTask.htmlでretrieveVideFrameFromVideo全体をラップすることができます。AsyncTaskの実装方法を見てください – X3Btel

答えて

1

問題は、アダプタの各セルのデータを要求して処理していることです。

try { 
     holder.video_thum.setImageBitmap(retriveVideoFrameFromVideo(getItem(position).getURL())); 
    } catch (Throwable throwable) { 
     throwable.printStackTrace(); 
    } 

これは原因です。メインスレッド(UIを管理するスレッド)の中で、高価で非グラフィカルな作業をしています。最適化するには、そのような操作をスレッドを分離するために移動し、メインスレッド内で実行されるクラスにUIを更新できるように結果を通知する必要があります。これを行うにはいくつかの方法があります:Asynctasks、Observers、Event buses。簡単にするために、asynctaskを使ってみましょう。

を例としてこれを取る:

public class BitMapTask extends AsyncTask<Void, Void, Bitmap> { 

public interface OnBitmapLoaded{ 
    void loadBitmap(Bitmap bitmap); 
} 

private OnBitmapLoaded bitmapLoaded; 
private String url; 

public BitMapTask(String url){ 
    this.url = url; 
} 

public BitMapTask setBitMapLoaded(OnBitmapLoaded bitMapLoaded){ 
    this.bitmapLoaded = bitMapLoaded; 
    return this; 
} 

@Override 
protected Bitmap doInBackground(Void... params) { 
    return retriveVideoFrameFromVideo(url); 
} 

@Override 
protected void onPostExecute(Bitmap result){ 
    if(bitmapLoaded != null) bitmapLoaded.loadBitmap(result); 
} 
} 

を、その後、代わりのtry-catchで、あなたはこのような何かをする必要があります

BitMapTask task = new BitMapTask(getItem(position).getURL()) 
       .setBitMapLoaded(new OnBitmapLoaded() { 
      @Override 
      public void loadBitmap(Bitmap bitmap) { 
       if(bitmap != null){ 
        setImageBitmap(bitmap); 
       } 
      } 
     }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 

覚えておいて、この種の操作は無視されますメインスレッドの状態。つまり、アプリケーションが休止状態であっても、別のスレッドは実行されて実行され続けます。したがって、アプリケーションがフォアグラウンドに移動する場合は、リスナー/サブスクリプションの受信者を無効にする必要があります。ハッピーコーディング。

関連する問題