20

つるやInstagramアプリなどの動画でリストを実装しようとしています。リスト アイテムが表示されているか完全に表示されているときにビデオが再生され、リスト アイテムが非表示になるとビデオが一時停止します。メディア プレーヤーで textureview を使用して URL からビデオを再生し、recyclerview のリスト項目として追加しました。以下は私のコードです。

VideosAdapter クラス:

public class VideosAdapter extends RecyclerView.Adapter<VideosAdapter.ViewHolder> {

Context context;
private ArrayList<String> urls;

public static class ViewHolder extends RecyclerView.ViewHolder {

    public LinearLayout layout;
    public TextView textView;

    public ViewHolder(View v) {
        super(v);
        layout = (LinearLayout) v.findViewById(R.id.linearLayout);
        textView = (TextView) v.findViewById(R.id.textView);
    }
}

public VideosAdapter(Context context, ArrayList<String> urls) {
    this.context = context;
    this.urls = urls;
}

// Create new views (invoked by the layout manager)
@Override
public VideosAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_main, parent, false);
    ViewHolder viewHolder = new ViewHolder(v);
    return viewHolder;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    String url = urls.get(position);
    holder.textView.setText(url);
    playVideo(holder, url);
}

@Override
public int getItemCount() {
    return urls.size();
}

private void playVideo(ViewHolder holder, String url)
{
    final CustomVideoPlayer vid = new CustomVideoPlayer(String.valueOf(url), context);
    holder.layout.addView(vid);
    holder.layout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            vid.changePlayState();
        }
    });
}
}

CustomVideoPlayer クラス:

public class CustomVideoPlayer extends  TextureView implements TextureView.SurfaceTextureListener
{

Context context;
String url;
MediaPlayer mp;
Surface surface;
SurfaceTexture s;

public CustomVideoPlayer(Context context, AttributeSet attrs)
{
    super(context, attrs);
    this.context = context;
}

public CustomVideoPlayer(String ur, Context context)
{
    super(context);
    this.setSurfaceTextureListener(this);
    this.url = ur;
    this.context = context;

}

@Override
public void onSurfaceTextureAvailable(final SurfaceTexture surface, int arg1, int arg2) {

    this.s = surface;
    Log.d("url", this.url);
    startVideo(surface);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {

    return true;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,int arg2) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
}

public void setVideo(String url)
{
    this.url = url;
}

public void startVideo(SurfaceTexture t)
{
    this.surface = new Surface(t);
    this.mp = new MediaPlayer();
    this.mp.setSurface(this.surface);
    try {
        Uri uri = Uri.parse(this.url);
        this.mp.setDataSource(url);
        this.mp.prepareAsync();

        this.mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            public void onPrepared(MediaPlayer mp) {

                mp.setLooping(true);
                mp.start();

            }
        });
    } catch (IllegalArgumentException e1) {
        e1.printStackTrace();
    } catch (SecurityException e1) {
        e1.printStackTrace();
    } catch (IllegalStateException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    try {

    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }
    try {

    } catch (IllegalStateException e) {
        e.printStackTrace();
    }


}

public void changePlayState()
{
    if(this.mp.isPlaying())
        this.mp.pause();
    else
        this.mp.start();
}
}

このコードを実行すると、複数の問題が発生します。

1) 最初の 2 つのアイテム/動画がバッファリングされ、正常に再生されます。しかし、スクロールすると3番目のビデオがロードされず、最初のビデオもリストから削除されます。

2) スクロール ビデオ/リスト アイテムでは、既にバッファリングされたアイテムのバッファリングが再び開始されます。

3) 高速スクロール リストではラグが発生し、スタックしてクラッシュします。

リストのスクロールとビデオの再生中に取得したlogcatの画像が添付されています。

ここに画像の説明を入力

誰でもこれを案内できますか?つるアプリのようなリストを作成する正しい方法は何ですか?

4

3 に答える 3

4

ビデオのキャッシュをバックエンドでダウンロードしてローカルに維持し、ローカル メモリから一度に 1 つのビデオを再生して、リストのスクロールをスムーズに保つ必要があります。

于 2015-06-23T06:29:39.100 に答える
4

レイアウト ファイル「view_main」自体にカスタム ビデオ ビューを追加してみませんか。ビデオ ビューの可視性を確認し、ビューが表示されている場合にのみ再生します。

public static boolean isViewVisible(View subView, View parentView) {
    Rect scrollBounds = new Rect();
    parentView.getHitRect(scrollBounds);
    if (subView.getLocalVisibleRect(scrollBounds)) {
        return true;
    }
    return false;
}

可視性をチェックするためのコード。スクロール状態がアイドル状態のときに、スクロール状態が変更されたリスナーでこれを呼び出します。

また、ビデオをダウンロードするために AsyncTask を使用する必要がありますが、一度に 1 つのビデオのみをダウンロードするか、メモリ不足エラーが発生する可能性があります。

于 2015-06-22T12:16:19.610 に答える