参考书 : 《疯狂Android讲义》


目录

1,问题描述,service线程与UI主线程是同一个线程

2,解决思路,service启动的时候,启动一个线程来处理耗时操作。

3,通过IntentService去启动多线程【Intent服务】

4,前台服务

5,远程服务


《疯狂Android讲义》第10章 Service与BroadcastReceiver 讲的挺好的。建议参考。讲的粗了点,但容易上手。作为初步学习很合适。

 

1,问题描述,service线程与UI主线程是同一个线程

我们可以通过打印进程ID和线程ID 看到,service 线程与UI主线程是同一个线程。所以service的响应耗时,也会造成UI页面的卡顿。

String.valueOf(android.os.Process.myPid());            // 打印当前的进程ID。
String.valueOf(Thread.currentThread().getId());        //打印线程ID。

 

2,解决思路,service启动的时候,启动一个线程来处理耗时操作。

在Service服务代码的onstartConmmand启动函数中创建一个继承了Thread的实例对象,并使用start()启动线程

Activity代码:

package com.example.service02;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView.FindListener;
import android.widget.Button;
 
public class Main extends Activity {
	
	private Button ButtonNormalService;
	private Button ButtonIntentService;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_service02);
		
		 ButtonNormalService = (Button)findViewById(R.id.button1);
		 ButtonIntentService = (Button)findViewById(R.id.button2);
		 ButtonNormalService.setOnClickListener(listener);
		 ButtonIntentService.setOnClickListener(listener);
		
		 
	}
	
	
	private OnClickListener  listener = new OnClickListener() {
		
		@Override
		public void onClick(View arg0) {
			// 第一种方法:  继承Thread类,标准Java的多线程启动方式。
			Intent intent = new Intent(Main.this,Serviceapp.class);
			
			switch (arg0.getId()) {
			case R.id.button1:
				System.out.println("当前线程为:"+Thread.currentThread().getId());
				startService(intent);
				break;
			case R.id.button2:
				stopService(intent);
				break;
			default:
				break;
			}
		}
		
	}; 
}

Service服务代码:

package com.example.service02;
 
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
 
public class Serviceapp extends Service {
 
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}
	
	
	// 第一种方法在onstartConmmand启动函数中创建一个继承了Thread的实例对象,并使用start()启动线程
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {  // 使用一个多线程来处理Service信息 第一种方法
 
		MyThread mythread = new MyThread();
		mythread.start();
		return super.onStartCommand(intent, flags, startId);
	}
	private class MyThread extends Thread{  // 在线程的run()中进行处理
 
		@Override
		public void run() {
			System.out.println("service "+Thread.currentThread().getId());
			
			try {
				Thread.sleep(30000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
 
}

 

 

3,通过IntentService去启动多线程【Intent服务】

 IntentService是Service类的一个子类,用来处理异步请求,客户端使用IntentService(Intent)方法传递请求给IntentService,IntentService通过work Thread处理每个Intent对象,执行完所有的工作之后,自动停止Service。

Activity代码:

package com.example.service02;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView.FindListener;
import android.widget.Button;
 
public class Main extends Activity {
	
	private Button ButtonNormalService;
	private Button ButtonIntentService;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_service02);
		
		 ButtonNormalService = (Button)findViewById(R.id.button1);
		 ButtonIntentService = (Button)findViewById(R.id.button2);
		 ButtonNormalService.setOnClickListener(listener);
		 ButtonIntentService.setOnClickListener(listener);
		
		 
	}
	
	
	private OnClickListener  listener = new OnClickListener() {
		
		@Override
		public void onClick(View arg0) {
			
			// 第二种方法: 第二种方式使用intentService
			Intent intent = new Intent(Main.this,ExampleIntentService.class);
			switch (arg0.getId()) {
			case R.id.button1:
				System.out.println("当前线程为:"+Thread.currentThread().getId());
				startService(intent);
				break;
			case R.id.button2:
				stopService(intent);
				break;
			default:
				break;
			}
		}
		
	}; 
}

使用Intent

使用IntentService需要两个步骤:

1 必须创造一个无参数的构造方法:将继承的子类名传入到IntentService类中。

2 复写onHandleIntent()方法(处理多线程任务),这个方法是在另外一个线程中的,因此不会阻塞UI,而且这种服务会自动关闭。

package com.example.service02;
 
import android.app.IntentService;
import android.content.Intent;
 
public class ExampleIntentService extends IntentService {
	
	public ExampleIntentService() {
		super("ExampleIntentService");
		// TODO Auto-generated constructor stub
	}
 
	@Override
	protected void onHandleIntent(Intent arg0) {
		
		System.out.println("service 2222 "+Thread.currentThread().getId());
		try 
		{
			Thread.sleep(3000);
		} 
		catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 
	}
 
}

4,前台服务

服务默认会和UI处于同一个线程,而且不会自动关闭的,除非你调用stopself. 那么如果要执行一个耗时操作,而且希望任务结束的时候服务也自动关闭,

那么你可以尝试IntentService.

 

5,远程服务

Android服务在默认情况下和它的使用者在同一个应用程序中,更确切的说是在同一个进程中。实际开发中有一种服务,当你想使用的时候会发现它根本

不在当前进程内。例如百度地图就提供一个服务 com.baidu.location.f

远程服务:使用者和服务不在同一个进程。

使用AIDL 实现。