定义
- 服务(Service)
- Android中实现程序后台运行的解决方案
- 通常用于不需要和用户交互,但是又要长期运行的程序
- 服务的运行不依赖于用户界面
- 服务不是运行在一个独立的进程中的,而是依赖于创建服务时所在的程序的进程,当它所属的程序的进程被终止,这个服务也就停止了
- 服务不会自动开启线程,所有的代码默认运行在主线程中,为了避免线程阻塞,执行具体任务的子线程需要手动创建
Android中的多线程
基本用法
-
例子
-
使用继承的方法来创建线程和启动线程
// 新建一个类,继承Thread类来定义线程 class MyThread extends Thread{ @Override public void run(){ } } // 启动线程 MyThread myThread = new MyThread(); myThread.start();
-
使用实现接口的方法来创建线程和启动线程
// 新建一个类,实现Runnable接口来定义线程 class MyThread implements Runnable{ @Override public void run(){ } } // 启动线程 MyThread myThread = new MyThread(); new Thread(myThread).start();
-
使用匿名类实现
new Thread(new Runnable(){ @Override public void run(){ } }).start();
-
异步消息处理机制
- Android的UI也是线程不安全的,如果需要更新程序汇总的UI元素,必须在主线程中进行,否则程序会崩溃
- 子线程中通常会执行一些耗时任务,Android提供了一套异步消息处理机制,从而可以在子线程中进行UI操作
- Android中的异步消息处理主要由4个部分组成
- Message
- 在线程之间传递消息,可以在内部携带少量的信息
- message.what:用户自定义的消息代码
- message.arg1:传递的int类型的值1
- message.arg2:传递的int类型的值2
- message.obj:传递一个object对象
- Handler
- 用于发送和处理消息
- 调用Handler中的sendMessage()方法发送消息
- 消息经过处理之后传递到Handler的handleMessage()方法中
- MessageQueue
- 每个线程中只有一个MessageQueue对象
- 消息队列,用于存放所有通过Handler发送的消息
- 这些消息会一直存放在队列中,直到被处理
- Looper
- 每个线程中只有一个Looper对象
- 管理MessageQueue
- Looper的loop()方法会让程序进行循环中
- 然后每当MessageQueue中存在一条消息,就将消息取出来
- 将消息传递给handleMessage()方法
- Message
- 异步消息处理流程
- 在主线程中创建Handler对象,并重写handleMessage()方法
- 当子线程中需要进行某些操作的时候(比如修改UI),创建一个Message对象,通过Handler将这个消息发出去
- 这个消息会被添加到MessageQueue队列中等待处理,同时Looper会一直尝试从MessageQueue中取出等待处理的消息
- 消息被处理之后会发还到Handler中的handleMessage()方法。注意,因为Handler在主线程中创建,所以handleMessage()方法在主线程中运行
AsyncTask
AsyncTask的原理也是异步消息处理机制,但是Android对它进行了封装
-
AsyncTask是一个抽象类,需要创建一个子类去继承它,可以指定三个泛型参数
Params:执行AsyncTask时传入的参数,用于在后台任务中使用
Progress:后台执行任务的时候,如果需要在界面上显示当前的进度,就使用它来作为进度单位
Result:当任务执行完毕之后,如果需要对结果进行返回,就使用它作为返回值的类型
-
例子
class MyTask extends AsyncTask<Void,Integer,Boolean>{}
- 第一个泛型参数指定为Viod,表示不需要传入参数给后台任务
- 第二个泛型参数指定为Integer,表示使用整型数据作为进度显示的单位
- 第三个泛型参数指定为Boolean,表示使用布尔型数据来反馈执行结果
-
继承AsyncTask之后需要重写的方法
-
onPreExecute()
- 在后台任务开始执行之前调用
- 用于执行一些界面上的初始化操作
-
doInBackground(Params)
- 这个方法所有的代码都在子线程中运行,在这里处理耗时的任务,任务完成之后通过return语句将任务执行的结果返回
- 如果AsyncTask第三个泛型参数指定为Void,就不需要返回任务执行结果
-
onProgressUpdate(Progress)
- 在这个方法中可以对UI进行操作,利用参数中的数值可以对界面元素进行相应的更新
- 参数是后台任务中传递过来的
-
onPostExecute(Result)
- 后台任务执行完毕,且通过return语句进行返回时,调用这个方法
- 返回的数据会作为参数传递到这个方法中,可以利用返回的数据进行UI操作
-
例子
public class MyTask extends AsyncTask<Void,Integer,Boolean> { @Override protected void onPreExecute(){ progressDialog.show(); } @Override protected Boolean doInBackground(Void...params){ // 在这里执行具体的下载任务,这个方法中的代码都在子线程中运行 try{ while (true){ // doDownload()用于计算当前的下载进度并返回 int downloadPercent = doDownload(); // 调用publishProgress()方法并将当前的下载进度传进来 publishProgress(downloadPercent); if (downloadPercent >= 100){ break; } } } catch (Exception e){ e.printStackTrace(); } return true; } @Override protected void onProgressUpdate(Integer...values){ progressDialog.setMessage("下载进度+"+values[0]+"%"); } @Override protected void onPostExecute(Boolean result){ progressDialog.dismiss();// 关闭对话框 if (result){ Toast.makeText(context, "下载完成", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show(); } } } // 启动任务 new MyTask().execute();
-
-
总结
- 在doInBackground()方法中执行具体的耗时的任务(比如下载)
- 在onProgressUpdate()方法中进行UI操作
- 在onPostExecute()方法中执行收尾工作
服务的基本用法
定义一个服务
-
例子
public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override // 在服务创建的时候调用 public void onCreate(){ super.onCreate(); } @Override // 在每次服务启动的时候调用 public int onStartCommand(Intent intent,int flags,int startId){ return super.onStartCommand(intent,flags,startId); } @Override // 在服务销毁的时候调用 public void onDestroy(){ super.onDestroy(); } }
-
需要在AndroidManifest.xml中注册
<service android:name=".MyService" android:enabled="true" android:exported="true"> </service>
启动服务与停止服务
借助Intent来启动和停止服务
-
例子
-
设置两个Button按钮来启动服务和停止服务
public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button startService = (Button) findViewById(R.id.start_service); Button stopService = (Button) findViewById(R.id.stop_service); startService.setOnClickListener(this); stopService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_service: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; default: break; } } }
-
自定义MyService
public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate(){ super.onCreate(); Log.d("MyService","onCreate方法执行了"); } @Override public int onStartCommand(Intent intent,int flags,int startId){ Log.d("MyService","onStartCommand方法执行了"); return super.onStartCommand(intent,flags,startId); } @Override public void onDestroy(){ super.onDestroy(); Log.d("MyService","onDestroy方法执行了"); } }
-
活动和服务进行通信
-
例子
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder{ public void startDownload(){ Log.d("MyService","开始下载"); } public int getProgress(){ Log.d("MyService","获取进度的方法执行了"); return 0; } } @Override public IBinder onBind(Intent intent) { return mBinder; } public MyService() { } }
- 新建了一个DownloadBinder类,这个类继承Binder
- 这个类实现了两个方法,开始下载和查看下载进度
- 最后在onBind()方法中返回这个实例
-
当一个活动和服务绑定了之后,就可以使用这个服务中Binder提供的方法了
-
例子
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private MyService.DownloadBinder downloadBinder; // 创建ServiceConnection的匿名类,重写了两个方法 private ServiceConnection connection = new ServiceConnection() { @Override // 在活动与服务绑定的时候调用 public void onServiceConnected(ComponentName name, IBinder service) { // 向下转型得到DownloadBinder的实例 downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } @Override // 在活动与服务解绑的时候调用 public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button bindService = (Button) findViewById(R.id.bind_service); Button unbindService = (Button) findViewById(R.id.unbind_service); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bind_service: Intent bindIntent = new Intent(this,MyService.class); // 使用bindService()方法将MainActivity和Myservice绑定 // 参数1:Intent对象, // 参数2:ServiceConnection的实例 // 参数3:标志位,这里的BIND_AUTO_CREATE表示活动和服务绑定后自动创建服务 bindService(bindIntent,connection,BIND_AUTO_CREATE); break; case R.id.unbind_service: // 解除绑定 unbindService(connection); default: break; } } }
-