10.1 服务是什么
服务(service)是实现程序后台运行的解决方案,适合执行那些不需要和用户交互而且还要求长期运行的任务
注意1:它依赖于创建服务时所在的应用程序进程. 应用程序被杀死,服务结束。
注意2:它不会在应用程序切换时,关闭掉
10.2 Android 多线程编程
10.2.1 线程的基本用法
方法一:
class MyThread extends Thread{
@Override
public void run(){
}
}
//启动方法
new MyThread().start()
方法二:
class MyThread implements Runnable{
@Overried
public void run(){
}
}
//启动方法
MyThread myThread = new MyThread();
new thread(myThread).start();
方法三:
new Thread(new Runnable(){
@Override
public void run(){
}
});
10.2.2 在子线程中更新UI
android 更新应用程序的UI元素,必须在主线程中更新。
为了解决这个问题:google提供了Hander, 这个Handler,是在主线程运行的,
通过子线程发送更新UI数据,handler再通过数据更新UI。
类似队列,子线程发送数据进队列,handler取队列数据处理
public static final int UPDATE_TEXT = 1
private Hander handler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case UPDATE_Text:
//UI 操作
}
}
}
new Thread(new Runnable){
@Override
public void run(){
Message message = new Message();
message.what = UPDE_TEXT;
handler.sendMessage(message);
}
}
10.2.3 解析异步消息处理机制
android 的异步消息处理主要由4个部分组成:Message, handler, MessageQueue 和 Looper
a, Message, 是用于不同线程之间交换少量数据。
b, Handler, 用于发送消息(handler.sendMessage)和处理消息(handler中的handlerMessage)的,
c, MessageQueue, 消息队列,主要存放Handler发送的消息。每个线程只会有一个MessageQueue队列
d, Looper, 是每个线程中的MessageQueue的管家,调用了Looper的loop()方法后,就会进入到无限循环,
每当发现MessageQueue存在一条消息,则将它取出,并传递到Handler的MandleMessage中
每个线程也只会有一个Looper对象
10.2.4 使用AsyncTask
AsyncTask也是基于异步消息处理机制
AsyncTask有三个参数,
params, 执行Aysnc时,需要传入的参数,可用于后台操作
Progress, 后台任务执行时,如果要在界面上显示当前的进度,则使用指定的泛型作为进度单件
Result, 当任务执行完毕后,如果需要对结果进行返回,则使用指定的泛型作为返回值类型
public class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
@Override
protected void onPreExecute() {
progressDialog.show(); //显示进度对话框
}
@Override
protected Boolean doInBackground(Void... voids) {
while(true){
int downloadPercent = doDownLoad(); //虚构的下载方法
publishProgress(downloadPercent);
if(downloadPercent >= 100){
break;
}
}
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setMessage("Downloaded" + values[0] + "%");
}
@Override
protected void onPostExecute(Boolean result) {
progressDialog.dismiss(); //关闭进度对话框
if(result){
Toast.makeText(context, "Download succeeded", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(context, "Download failed", Toast.LENGTH_LONG).show();
}
}
}
//启动这个任务
new DownloadTask().execute();
10.3 服务的基本用法
10.3.1 定义一个服务
new->Service->Service
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
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中注册
10.3.2 启动和停止服务
//启动
Intent startIntent = new Intent( this, MyService.class );
startService(startIntent);
//关闭
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
10.3.3 活动和服务进行通信
第一步,在MyService中创建一个类,继承Binder, 改相关代码,如下
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload(){
Log.d("MyService", "startDownload executed");
}
public int getProcess(){
Log.d("Myservice", "getProgredd executed");
return 0;
}
}
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d("MyService", "onDestroy executed");
super.onDestroy();
}
}
第二步:在MainActivity中创建一个MainActivity中的类中类,再创建一个ServiceConnection的匿名类.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyService.DownloadBinder downloadBinder;
private Button start_service;
private Button stop_service;
private Button bind_service;
private Button unbind_service;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProcess();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start_service = (Button) findViewById(R.id.start_service);
stop_service = (Button) findViewById(R.id.stop_service);
start_service.setOnClickListener(this);
stop_service.setOnClickListener(this);
bind_service = (Button) findViewById(R.id.bind_service);
unbind_service = (Button) findViewById(R.id.unbind_service);
bind_service.setOnClickListener(this);
unbind_service.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.start_service:
Intent startIntent = new Intent(MainActivity.this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
Intent stopIntent = new Intent(MainActivity.this, MyService.class);
stopService(stopIntent);
break;
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
default:
break;
}
}
}
第三步:开启服务,看打印日记,那些方法运行,关闭服务,那些方法被调用,还有绑定服务,和解绑服务
注意,绑定服务,再解绑服务,就好,不然,会报错, 因为要绑定,才能解绑
10.4 服务的生命周期
第一点:服务只会存在一个实例,
第二点:调用了context中StartCommand方法,则会启动onStartCommand()方法,如果没有创建启动过,则先会调用OnCreate;
结束时,一定要调用unbindService,和stopService;
第三点:如果,开启服务,以绑定服务,要依次,停止服务和解绑服务
10.5 服务的更多技巧
10.5.1 使用前台服务
前台服务的后台服务最大的区别是,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息
这里不列出代码了,有问题,看这个https://blog.csdn.net/julicliy/article/details/104313756
10.5.2 使用IntentService
服务的代码都默认是在主线程运行了,很容易出现ANR( Application Not Responding )
onStartCommand中加入
new Thread(new Runnable){
@Override
public void run(){
//处理具体事物
stopSelf(); //停止服务
}
}
intentService类为了创建一个异步的,会自动停止的服务。
public class MyIntentService extends IntentService {
public MyIntentService(){
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d("MyIntentService", "SubThread id is " + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
在Mainfest.xml中注册 <application><service android:name=".MyIntentService"/></application>
启动该服务
Intent intentService = new Intent(MainActivity.this, MyIntentService.class);
startService(intentService);