您的位置:首页 > 移动开发 > Android开发

Android使用Rxjava异步递归读取内存卡中所有的视频文件

2016-06-11 20:38 1016 查看
Rxjava是一个异步调用库,可以很灵活地使用操作符来满足各种的异步操作需求。

RXjava入门引导文章请看:/article/11909868.html

我们都知道,android中可以使用HandlerThread做异步耗时操作,使用是可以使用,但是其步骤过于繁琐,看起来也不优雅。

使用HandlerThread读取文件夹中的视频文件:

package com.danxx.mdplayer.ui;

import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.transition.Explode;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.danxx.mdplayer.R;
import com.danxx.mdplayer.adapter.BaseRecyclerViewAdapter;
import com.danxx.mdplayer.adapter.BaseRecyclerViewHolder;
import com.danxx.mdplayer.model.VideoBean;
import com.danxx.mdplayer.utils.FileUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class VideoListActivity extends AppCompatActivity {
private String path;
private static final int MSG_READ_FINISH = 1;
private VideoListAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
private RecyclerView videoListView;
private File rootFile;
private TextView tvFilePath;

/**包含有视频文件夹集合**/
private List<VideoBean> videoBeans = new ArrayList<VideoBean>();
private List<VideoBean> videoBeans2 = new ArrayList<VideoBean>();
private HandlerThread handlerThread;
private Handler readTaskHandler;
private Handler mainHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if(msg.what == MSG_READ_FINISH){
if(videoBeans.size()>0){
mAdapter.setData(videoBeans);
mAdapter.notifyDataSetChanged();
}else{
Toast.makeText(VideoListActivity.this, "sorry,没有读取到视频文件!", Toast.LENGTH_LONG).show();
}
}
return false;
}
});

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set Explode enter transition animation for current activity
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode().setDuration(800));
getWindow().setExitTransition(null);

setContentView(R.layout.activity_video_list);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
path = intent.getStringExtra("path");
mAdapter = new VideoListAdapter();
tvFilePath = (TextView) findViewById(R.id.tvFilePath);
videoListView = (RecyclerView) findViewById(R.id.videoListView);
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setOrientation(OrientationHelper.VERTICAL);
videoListView.setLayoutManager(mLayoutManager);
videoListView.setAdapter(mAdapter);
if(path != null && !TextUtils.isEmpty(path)){
tvFilePath.setText(path);
initData();
}
}

private void initData(){
rootFile = new File(path);

handlerThread = new HandlerThread("ReadVideoFileTask");
handlerThread.start();
readTaskHandler = new Handler(handlerThread.getLooper());
ReadVideoFileTask readVideoFileTask = new ReadVideoFileTask(mainHandler);
readTaskHandler.post(readVideoFileTask);

mAdapter.setOnItemClickListener(new BaseRecyclerViewAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, Object data) {
VideoActivity.intentTo(VideoListActivity.this , ((VideoBean)data).path ,((VideoBean)data).name);
}
});
}

class ReadVideoFileTask implements Runnable{

Handler mainHandler;
public ReadVideoFileTask(Handler handler){
this.mainHandler = handler;
}
@Override
public void run() {
eachAllMedias(rootFile);
Log.d("danxx", "文件读取完成");
Message msg = mainHandler.obtainMessage(MSG_READ_FINISH);
msg.sendToTarget();
}

/** 遍历所有文件夹,查找出视频文件 */
private void eachAllMedias(File f) {
if (f != null && f.exists() && f.isDirectory()) {
File[] files = f.listFiles();
if (files != null) { //文件夹里面存在文件或者文件夹
for (File file : f.listFiles()) {
if (file.isDirectory()) {
eachAllMedias(file);
} else if (file.exists() && file.canRead() && FileUtils.isVideo(file)) {
String name = file.getName();
String size = FileUtils.showFileSize(file.length());
String path = file.getPath();
videoBeans.add(new VideoBean(name , path , size));
}
}
}
}else{
Log.d("danxx" ,"目录直接为空");
}
}
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == android.R.id.home)
{
finish();
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}

class VideoListAdapter extends BaseRecyclerViewAdapter<VideoBean>{

/**
* 创建item view
*
* @param parent
* @param viewType
* @return
*/
@Override
protected BaseRecyclerViewHolder createItem(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(VideoListActivity.this).inflate(R.layout.item_videos_layout, parent, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
}

/**
* 绑定数据
*
* @param holder
* @param position
*/
@Override
protected void bindData(BaseRecyclerViewHolder holder, int position) {
((MyViewHolder)holder).tvName.setText(getItemData(position).name);
((MyViewHolder)holder).tvSize.setText(getItemData(position).size);
}

class MyViewHolder extends BaseRecyclerViewHolder{
View mView;
ImageView ivPic;
TextView tvName,tvSize,tvlength;
public MyViewHolder(View itemView) {
super(itemView);
ivPic = (ImageView) itemView.findViewById(R.id.ivPic);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvSize = (TextView) itemView.findViewById(R.id.tvSize);
tvlength = (TextView) itemView.findViewById(R.id.tvlength);
mView = itemView;
}

@Override
protected View getView() {
return mView;
}
}
}
}


使用Rxjava读取文件夹中的视频文件:

package com.danxx.mdplayer.ui;

import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.transition.Explode;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.danxx.mdplayer.R;
import com.danxx.mdplayer.adapter.BaseRecyclerViewAdapter;
import com.danxx.mdplayer.adapter.BaseRecyclerViewHolder;
import com.danxx.mdplayer.model.VideoBean;
import com.danxx.mdplayer.utils.FileUtils;
import com.danxx.mdplayer.utils.RxUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

public class VideoListActivity extends AppCompatActivity {
private String path;
private static final int MSG_READ_FINISH = 1;
private VideoListAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
private RecyclerView videoListView;
private File rootFile;
private TextView tvFilePath;

/**
* 包含有视频文件夹集合
**/
private List<VideoBean> videoBeans = new ArrayList<VideoBean>();

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set Explode enter transition animation for current activity
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode().setDuration(800));
getWindow().setExitTransition(null);

setContentView(R.layout.activity_video_list);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
path = intent.getStringExtra("path");
mAdapter = new VideoListAdapter();
tvFilePath = (TextView) findViewById(R.id.tvFilePath);
videoListView = (RecyclerView) findViewById(R.id.videoListView);
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setOrientation(OrientationHelper.VERTICAL);
videoListView.setLayoutManager(mLayoutManager);
videoListView.setAdapter(mAdapter);
if (path != null && !TextUtils.isEmpty(path)) {
tvFilePath.setText(path);
initData();
}
}

private void initData() {
rootFile = new File(path);
ReadVideoFileByRxjava();
}

/**
* 参考:http://blog.csdn.net/job_hesc/article/details/46242117
*/
private void ReadVideoFileByRxjava() {
Observable.just(rootFile)
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return RxUtil.listFiles(file);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Subscriber<File>() {
@Override
public void onCompleted() {
Log.d("danxx", "onCompleted");
if (videoBeans.size() > 0) {
mAdapter.setData(videoBeans);
mAdapter.notifyDataSetChanged();
} else {
Toast.makeText(VideoListActivity.this, "sorry,没有读取到视频文件!", Toast.LENGTH_LONG).show();
}
}

@Override
public void onError(Throwable e) {
}

@Override
public void onNext(File file) {
String name = file.getName();
String size = FileUtils.showFileSize(file.length());
String path = file.getPath();
videoBeans.add(new VideoBean(name, path, size));
Log.d("danxx", "name--->" + name);
}
}
);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}

class VideoListAdapter extends BaseRecyclerViewAdapter<VideoBean> {

/**
* 创建item view
*
* @param parent
* @param viewType
* @return
*/
@Override
protected BaseRecyclerViewHolder createItem(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(VideoListActivity.this).inflate(R.layout.item_videos_layout, parent, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
}

/**
* 绑定数据
*
* @param holder
* @param position
*/
@Override
protected void bindData(BaseRecyclerViewHolder holder, int position) {
((MyViewHolder) holder).tvName.setText(getItemData(position).name);
((MyViewHolder) holder).tvSize.setText(getItemData(position).size);
}

class MyViewHolder extends BaseRecyclerViewHolder {
View mView;
ImageView ivPic;
TextView tvName, tvSize, tvlength;

public MyViewHolder(View itemView) {
super(itemView);
ivPic = (ImageView) itemView.findViewById(R.id.ivPic);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvSize = (TextView) itemView.findViewById(R.id.tvSize);
tvlength = (TextView) itemView.findViewById(R.id.tvlength);
mView = itemView;
}

@Override
protected View getView() {
return mView;
}
}
}
}


上面用到的工具类RxUtil .java:

package com.danxx.mdplayer.utils;

import java.io.File;
import java.util.concurrent.Callable;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

/**
* Created by danxingxi
* Observable创建工具类
*/
public class RxUtil {

/**
* rxjava递归查询内存中的视频文件
* @param f
* @return
*/
public static Observable<File> listFiles(final File f){
if(f.isDirectory()){
return Observable.from(f.listFiles()).flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
/**如果是文件夹就递归**/
return listFiles(file);
}
});
} else {
/**filter操作符过滤视频文件,是视频文件就通知观察者**/
return Observable.just(f).filter(new Func1<File, Boolean>() {
@Override
public Boolean call(File file) {
return f.exists() && f.canRead() && FileUtils.isVideo(f);
}
});
}
}

}


使用Rxjava是不是优雅简洁很多?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: