第一行代码笔记 service基本用法

服务简介:

作为四大组件之一的服务可以运行在后台,但是服务并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀死时,所有依赖于该进程的服务也会停止运行。另外服务并不会自动开启线程,所有的代码都是默认运行在主线程当中。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务。否则就有可能出现主线程被阻塞住的情况。


插曲android多线程

一般通过匿名内部类

new Thread(new Runnable() {
    @Override
    public void run() {
      
    }
}).start();

定义一个单独的类的时候,一般实现Runnable接口。而不继承thread 继承的方式耦合较高。

注意子线程里不要做更新UI的操作,如果要更新,可以通过handle的异步消息处理。或者通过回调接口。或者AsyncTask。或者

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        showDatas.setText(msg);
    }
});

AsyncTask的简单说明

/**
 * AsyncTask三个参数
 * 参数1:在执行AsyncTask时需要传入的参数。可用于后台任务中
 * 参数2.后台任务执行时,如需显示进度,则使用这里指定的泛型作为进度单位
 * 参数3.但任务执行完毕后,如果需要返回结果,则这里指定的泛型作为返回值类型
 */
public class AsyncTaskDemo extends AsyncTask<Void, Integer, Boolean> {

    /**
     * 在后台任务执行之前调用,用于进行界面上的初始化操作,比如显示一个进度对话框
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 在这里处理所有的耗时任务,任务一旦完成通过return返回
     * 这里不能对UI进行操作,因为此处代码都运行在子线程中。
     *
     * @param params
     * @return
     */
    @Override
    protected Boolean doInBackground(Void... params) {
//        如果要更新进度条,调用publishProgress来完成
//        publishProgress();
        return null;
    }

    /**
     * 这里可以更新UI了
     *
     * @param values
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

    }

    /**
     * 但后台任务完成后return后这个方法马上会执行
     * 并且rentur的值可以在参数中获得。这里做收尾工作
     *
     * @param aBoolean
     */
    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
    }

    /**
     * 这里执行这个异步任务
     */
    private void start() {
        new AsyncTaskDemo().execute();
    }
}

回归服务基本用法

一 最基础示例:

第一步:通过new service创建一个service,好处是自动去清单文件中注册了这service

 <service
        android:name=".day05.service.MyService"
        android:enabled="true"
        android:exported="true" />

    <activity android:name=".day05.service.MyServiceActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

/**
 * 注意服务使用也是要去清单文件注册的。
 * 除了通过activity中 stopService(stopIntent);停止服务
 * 也可以在此类中调用 stopSelf();来停止服务
 *
 * 注意有时候我们既通过startService来开启了服务,又调用了bindService
 * 这时候要服务停止,必须调用stopService和unBindService
 */
public class MyService extends Service {
    public MyService() {
    }

    /**
     * 在服务创建的时候调用一次
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService:onCreate", "onCreate");
    }

    /**
     * 在服务启动的时候每次都会调用,希望服务一启动就执行的动作,逻辑写在这。
     * 但是注意每调用一次startService(intent)这个方法就会被执行一次。
     * 但是每个服务都只有一个实例,所以不管调用了多少次的startService只需要调用
     * 一次stopService活stopSelf方法,服务就会停下来
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 在服务销毁的时候调用,回收那些不在使用的资源
     */
    @Override
    public void onDestroy() {
        Log.i("MyService:onDestroy", "onDestroy");
        super.onDestroy();
    }

    /**
     * 通过bind来进行activity和服务之间的通信
     *
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.i("MyService:onBind", "onBind");
//        throw new UnsupportedOperationException("Not yet implemented");
        return mBinder;
    }

    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {
        public void startBownload() {
            Log.i("DownloadBinder", "startBownload");
        }

        public int getProgress() {
            Log.i("DownloadBinder", "getProgress");
            return 0;
        }


    }
}

第二步:创建activity来开启这个服务

public class MyServiceActivity extends AppCompatActivity implements View.OnClickListener {

//   通过binder的方式可以更好的控制service启动去执行的任务
    private MyService.DownloadBinder downLoadBinder;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downLoadBinder = (MyService.DownloadBinder) service;
            downLoadBinder.startBownload();
            downLoadBinder.getProgress();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_service);

        initView();
    }

    private void initView() {
        findViewById(R.id.startService).setOnClickListener(this);
        findViewById(R.id.stopService).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.startService:
//                启动方式一
//                Intent intent = new Intent(this,MyService.class);
//                startService(intent);

//                启动方式二
                Intent intent = new Intent(this,MyService.class);
                bindService(intent,connection,BIND_AUTO_CREATE);

                break;
            case R.id.stopService:
//                停止方式一
//                Intent stopIntent = new Intent(this,MyService.class);
//                stopService(stopIntent);

//                停止方式二
                unbindService(connection);
                break;
        }
    }
}

二 使用前台服务

服务几乎都是后台运行的。在后台运行时,他的系统优先级比较低,当系统出现内存不足时,就坑呢个会被回收掉。如果不想由于系统内存不足被回收,就提高它的优先级,使用前台服务。他和普通服务的最大区别在于,他会在系统的状态栏下一直显示一个正在运行的图标。

示例:只要在创建的MyService的onCreate方法添加一个通知,如下

@Override
public void onCreate() {
    super.onCreate();
    Log.i("MyService:onCreate", "onCreate");
    Intent intent = new Intent(this, MyServiceActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    Notification build = new NotificationCompat.Builder(this)
            .setContentTitle("前台服务")
            .setContentText("我的前台服务创建")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .build();
    startForeground(1,build);
}

三    IntentService的使用

因为服务也是运行在主线程的,所以如果要做耗时操作时,要自己开一个子线程进行,否则容易出现程序没有响应(ANR),另外有时候粗心,不记得unbindService 或者stopService 来停止服务,这时候就又一个IntentService,它能自己开线程执行相应的操作,并且执行完毕后,自动关闭服务。使用方式和之前一样,创建一个类继承IntentService 在清单文件注册这个service 然后在activity中通过intent    startSerive()来开启这个服务。

public class MyIntentService extends IntentService {
    public MyIntentService() {
//        调用父类的有参构造函数
        super("MyIntentService");
    }

    public MyIntentService(String name) {
        super(name);
    }

    /**
     * 在这里执行要做的动作,并且已经是开了子线程,不用自己再开线程了,等待这里执行完,
     * 会自动注销这个service
     * @param intent
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("MyIntentService", "onHandleIntent  sleep before");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i("MyIntentService", "onHandleIntent  sleep after");
        Log.i("MyIntentService", "onHandleIntent");
        Log.i("MyIntentService", "onHandleIntent  id: "+Thread.currentThread().getId());
    }

    @Override
    public void onDestroy() {
        Log.i("MyIntentService", "onDestroy");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值