3

사용자가 TextureView를 사용하여 목록보기를 통해 비디오를 볼 수 있도록 일부 행에 비디오를 표시하는 Listview가 있습니다. 지금까지 동영상은 올바르게로드되고 재생되지만 스크롤하는 동안 잘못된 순서로 표시됩니다. 이것은 어댑터 재활용보기로 인해 생각하지만,이 문제를 해결하는 방법을 잘 모르겠습니다.ListView에서 TextureView를 사용할 때 비디오가 잘못된 순서로 표시됩니다.

여기에 뷰를 렌더링 한 다음 AsyncTask를 각보기의 설정에의 getView하여 MediaPlayer를 시작했다가 처리하는의 getView가 내 구현

입니다. onSurfaceTextureAvailable에서 만든 AsyncTask 인스턴스가 순차적으로 완료되지 않을 수 있습니다 당신이 스크롤 할 때, 새로운 view 위해 만든 스레드 (그래서 이전 데이터가로드) 재활용 view의 스레드 전에 완료 할 수 있기 때문에

@Override 
public View getView(int position, View view, ViewGroup parent) { 
    final ViewHolder holder; 

    final VoucherItem vItem = items.get(position); 

    if (view == null) { 
     view = inflater.inflate(R.layout.voucher_row, parent, false); 
     holder = new ViewHolder(); 

     holder.list_img = (ImageView) view.findViewById(R.id.list_img);   
     holder.vid_play = (ImageView) view.findViewById(R.id.vid_play); 
     holder.video = (TextureView) view.findViewById(R.id.texture_video); 

     view.setTag(holder); 
    } else { 
     holder = (ViewHolder) view.getTag(); 
    } 



     if (!vItem.photo.equals("")) 
      Picasso.with(context).load(vItem.photo).fit().centerCrop() 
        .into(holder.list_img); 
     else 
      Picasso.with(context).load(R.drawable.default_spuare).fit() 
        .centerCrop().into(holder.list_img); 


     if (!vItem.photo.equals("")){ 
      holder.vid_play.setVisibility(View.GONE); 
      holder.video.setVisibility(View.GONE); 
      holder.list_img.setVisibility(View.VISIBLE); 
     } else {     
      holder.video.setVisibility(View.VISIBLE); 
      holder.list_img.setVisibility(View.GONE); 

      holder.video.setSurfaceTextureListener(new SurfaceTextureListener() { 

       @Override 
       public void onSurfaceTextureUpdated(SurfaceTexture arg0) { 

       } 

       @Override 
       public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1, 
         int arg2) {      
       } 

       @Override 
       public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) { 
        return false; 
       } 

       @Override 
       public void onSurfaceTextureAvailable(SurfaceTexture surface, int arg1, int arg2) { 
        final MediaPlayer mediaPlayer = new MediaPlayer(); 
        holder.vid_play.setTag(mediaPlayer); 
        new SetVideotask().execute(surface, vItem, mediaPlayer, holder.vid_play);      
       } 
      }); 
     } 
    } 

    return view; 
} 

class SetVideotask extends AsyncTask<Object, Integer, String>{ 

    @Override 
    protected String doInBackground(Object... o) { 
     // TODO Auto-generated method stub 
     final SurfaceTexture s = (SurfaceTexture) o[0]; 
     final VoucherItem item = (VoucherItem) o[1]; 
     final MediaPlayer mediaPlayer = (MediaPlayer) o[2]; 
     final View v = (View) o[3]; 


     mediaPlayer.setSurface(new Surface(s)); 
     try { 

      mediaPlayer.setDataSource(item.video); 
      mediaPlayer.prepare(); 
      mediaPlayer.start(); 
      //I do this so there is a frame in the video to act as a preview 
      Thread.sleep(100); 
      mediaPlayer.pause();  
      mediaPlayer.setOnErrorListener(VoucherAdapter.this);     
     } catch (Exception e) { 
      e.printStackTrace(); 
     }   

     return null; 
    }  
} 



static class ViewHolder { 
    ImageView list_img; 
    ImageView vid_play; 
    TextureView video; 
} 


@Override 
public boolean onError(MediaPlayer arg0, int arg1, int arg2) { 
    return true; 
} 

답변

1

입니다 .

스크롤하는 동안 종료되는 단일 스레드 풀을 생성하여이 문제를 해결할 수있었습니다.

또한 thisListView로드에 대한 궁극적 인 질문입니다.

+0

AsyncTasks를 사용하면 인스턴스를 다시 사용할 수 없다고 생각합니다. 새 인스턴스를 만들어야합니다. ViewHolder 클래스에 인스턴스를 추가하는 것이 더 좋을까요? 내 사례와 관련해서 좀 더 자세하게 설명해 주시겠습니까? 아마도 의사 코드 일 수도 있습니다. – Amanni

+0

새 변수를 시작하기 전에 SetVideotask에 전역 변수를 사용하고 취소하려고했지만 작동하지 않습니다. – Amanni

+0

단서 주셔서 감사합니다. – Amanni