GL_BOOK_8

Chapter 9

AsyncTask<Params, Progress, Result>()
new AsyncTask<Void, Integer, Boolean>() {

            @Override
            protected Boolean doInBackground(Void... params) {
                Log.i("haha","doInBackground");
                publishProgress(50);
                return null;
            }
            @Override
            protected void onProgressUpdate(Integer... values) {
                Log.i("haha","onProgressUpdate");
                Log.i("haha", ""+values[0]);
                super.onProgressUpdate(values);
            }
            @Override
            protected void onPreExecute() {
                Log.i("haha","onPreExecute");
                super.onPreExecute();
            }
            @Override
            protected void onPostExecute(Boolean result) {
                super.onPostExecute(result);
                Log.i("haha","onPostExecute");
            }

        }.execute();

当后台任务中调用了 publishProgress 方法,onProgressUpdate 就会很快被调用

服务Service

onCreate onStartCommand
startService 时 服务未从创建过 第一次创建时调用 onCreate onStartCommand , 之后多次调用startService , 只有 onStartCommand 得以执行
context.stopService 或者 在service内部 调用 stopSelf方法

活动和服务的关联

public class LhyService extends Service {

    MyBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    class MyBinder extends Binder{
        public void startToDo(){
            Log.i("haha", "startToDo");
        };
        public void stopToDo(){
            Log.i("haha", "stopToDo");
        };
    }

}
ServiceConnection conn=  new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {

            Log.i("haha", "ComponentName : "+name);
            Log.i("haha", "onServiceDisconnected");

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LhyService.MyBinder myBinder = (MyBinder) service;
            myBinder.startToDo();
        }
    };
bindService(serviceIntent, conn, BIND_AUTO_CREATE);
unbindService(conn);

任何一个服务在应用程序范围内都是通用的 可以和多个活动 activity进行绑定 绑定完成后 都可以获得相同的Binder实例
每个服务只存在于一个实例 所以不管调用了多少次 startService 方法 ,只要调用一次 stopService 或 stopSelf 方法 服务就会停下来

通过调用 bindService 来获取一个服务的持久连接 会调用onBind方法 如果服务还没有被创建 onCreate 方法会先于onBind方法执行 然后再执行 onBind方法
只要调用方和服务之间的连接没有断开 服务就会一直保持运行状态

如果一个活动 既调用 startService 方法 又调用了 bindService 方法 如何destroy掉这个服务呢
根据Android系统的机制 一个服务只要被启动或者被绑定之后,就会一直处于运行状态,必须要让以上两种条件同时不满足 才可以销毁服务 ,也就是说要同时调用 stopService 和 unbindService 方法 ,onDestroy 方法才可以被执行

服务的系统优先级

基本后台运行
内存不足的时候有可能被回收
前台服务和普通服务最大区别在于 会一直有一个正在运行的图标在系统状态栏显示 下拉状态栏会看到更加详细的信息 , 非常类似通知的效果

创建前台服务

    public void onCreate() {
        super.onCreate();
        NotificationCompat.Builder mBuilder = new Builder(this);
        mBuilder.setSmallIcon(R.drawable.ic_launcher);
        mBuilder.setTicker("foreground service start");
        mBuilder.setContentTitle("foreground service title");
        mBuilder.setContentText("foreground service content");
        Intent intent = new Intent(this,MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pi);
        startForeground(1, mBuilder.build());

    }

就是把通知的 notify方法 换为 startForeground方法 在onCreate方法里

服务中的代码默认是在主线程中的 ANR 多线程

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                //TODO 

                stopSelf();
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

android 提供了一个 可以创建一个异步的、会自动停止的服务 IntentService 类
onHandleIntent方法是在子线程中的

public class YssService extends IntentService {

    public YssService(String name) {
        super(name);
    }
    public YssService() {
        super("YssService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("haha", "ThreadId : "+Thread.currentThread().getId());
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("haha", "onDestroy");
    }
}

后台执行的 定时任务
两种方法 一种是 Java 的 Timer 类
一种是 Android 的 Alarm 机制

Timer 有一个明显的短板 不太适用于 那些需要长期在后台运行的定时任务
因为 为了让电池耐用 android 手机的休眠策略是 长时间不操作的情况 自动让 CPU 自动进入睡眠状态 ,这就有可能导致 Timer 中的定时任务无法正常运行。而Alarm机制则不存在这种情况。Alarm具有唤醒CUP的功能

Alarm 机制的用法 :

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                //异步执行的逻辑功能
                Log.i("haha", "the service executed at "+new Date().toString());
            }
        }).start();

        AlarmManager manager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
        int halfMinute = 30*1000;
//      long triggerAtTime = SystemClock.elapsedRealtime()+halfMinute;
        long triggerAtTime = System.currentTimeMillis()+halfMinute;

        Intent i = new Intent(this,AlarmReceiver.class);
        PendingIntent pi  = PendingIntent.getBroadcast(this, 0, i, 0);

//      manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
        manager.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pi);
        //      manager.setExact(type, triggerAtMillis, operation);
        return super.onStartCommand(intent, flags, startId);
    }
public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, LongRunService.class));
    }

}

AlarmManager 通过 getSystemService(Context.ALARM_SERVICE)
manager.set(xx,xx,xx);
第一个xx 是 flag 和第二个 xx triggerAtTime是相对应的 trigger(触发)
flag 共有 四个参数可以选择

AlarmManager.ELAPSED_REALTIME_WAKEUP
表示让定时任务的触发时间从系统开机算起,并唤醒CPU
对应获取系统已开机运行的时间的方法 是 SystemClock.elapsedRealtime()
系统开机至今所经历的时间毫秒数

AlarmManager.ELAPSED_REALTIME
定时任务的触发时间从系统开机算起 但不会唤醒CPU
获取时间的方法同上

AlarmManager.RTC_WAKEUP
定时任务的触发时间 从 1970年1月1日0点开始算起 至今的时间加上要延时的时间 并唤醒CPU
获取时间的方法 System.currentTimeMillis()

AlarmManager.RTC
参照以上

第三个xx 是PendingIntent

需要注意的是 从android 4.4 版本开始 Alarm任务触发的时间 会变得不准确 有时候会延迟一段时间后任务才开始得到执行 系统在耗电性方面上进行了优化导致的 大幅度减少 CPU被唤醒的次数 有效延长电池的使用时间

如果要求 Alarm任务执行的时间必须准确无误 使用AlarmManager.setExact() 方法来替代 set

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值