• 并行执行的Service,以媒体转码成新格式为例


    大家众所周知,IntentService内置的handler只有一个线程,而AsyncTask又只适合时间至多几秒的操作,所以我们关注使用ExecutorService建立并行执行。为了确保Service一直保持活跃状态,需要调用Service.startForeground()方法。由于Service.startForeground()和Service.stopForeground()并不会叠加,所以还需要维护一个内部计数器,用来记录活跃的任务。一旦计数器为0则调用Service.stopForeground();

    在这个例子中,主要介绍怎么利用Service执行并行的任务,并不是主要讲解多媒体格式文件转码的操作,所以转码操作都省略,主要实现并行执行。

    public class MediaTranscoder extends Service {
    private static final int NOTIFICATION_ID = 1001;//定义通知的标识ID
    public static final String ACTION_TRANSCODE_MEDIA = "com.liyaunjinglyj.services.TRANSCODE_MEDIA";
    public static final String EXTRA_OUTPUT_TYPE = "outputType";//转码的类型
    private ExecutorService mExecutorService;//定义线程池
    private int mRunningJobs = 0;//任务计数器
    private final Object mLock = new Object();//锁
    private boolean mIsForeground = false;//标志是否需要结束Service


    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }


    @Override
    public void onCreate() {
    super.onCreate();
    this.mExecutorService = Executors.newCachedThreadPool();//缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务,因此在一些面向连接的daemon型SERVER中用得不多。能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。 注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    String action = intent.getAction();
    if (ACTION_TRANSCODE_MEDIA.equals(action)) {
    String outputType = intent.getStringExtra(EXTRA_OUTPUT_TYPE);


    //启动新的作业增加计数器
    synchronized (mLock) {
    TranscodeRunnable transcodeRunnable = new TranscodeRunnable(
    intent.getData(), outputType);
    mExecutorService.execute(transcodeRunnable);//执行当前线程
    mRunningJobs++;//线程计数器加1
    startForegroundIfNeeded();//创建通知,并保持活跃
    }
    }
    return START_NOT_STICKY;//系统回收资源关闭了当前的Service并不会重新启动.适合执行一次性操作。
    }


    @Override
    public void onDestroy() {
    super.onDestroy();
    this.mExecutorService.shutdownNow();//shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务
    }


    private class TranscodeRunnable implements Runnable {
    private Uri mInData;
    private String mOutputType;


    private TranscodeRunnable(Uri inData, String outputType) {
    this.mInData = inData;
    this.mOutputType = outputType;
    }


    @Override
    public void run() {

    //在这里执行转码操作

    //转码完成后,计数器加1

    synchronized (mLock) {
    mRunningJobs--;
    stopForegroundIfAllDone();
    }
    }


    }


    private void stopForegroundIfAllDone() {
    if (mRunningJobs == 0 && mIsForeground) {
    stopForeground(true);
    this.mIsForeground = false;
    }
    }


    private void startForegroundIfNeeded() {
    if (!mIsForeground) {
    Notification notification = buildNotFication();
    startForeground(NOTIFICATION_ID, notification);
    this.mIsForeground = true;
    }
    }


    private Notification buildNotFication() {
    Notification notification = null;

    //在这里构建通知
    return notification;
    }


    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    在一页纸上打印8页PPT讲义的方法
    如何用XML数据绑定前台Repeater
    ASP.net中导出Excel的简单方法
    鼠标浮上JS自动弹窗
    通过拖动百度地图的添加覆盖物获取所在地的经纬度坐标
    void FillSolidRect(lpRect,clr)无效原因现象。
    WM_DRAWITEM与DrawItem()的讨论
    自绘控件 CSatic无法响应OnDrawItem
    【原创】CListCtrl和CImageList显示缩略图,图片自动排列。
    【转】VC改变对话框按钮字体颜色和背景的解决方案
  • 原文地址:https://www.cnblogs.com/liyuanjinglyj/p/4656580.html
Copyright © 2020-2023  润新知