1 class MyThread extends Thread{
2 public void run( ){
3 //执行耗时操作
4 }
5 }
6 new MyThread( ).start( );
(2)实现Runnable接口:
1 class MyRunnable implements Runnable{
2 public void run( ){
3 //执行耗时操作
4 }
5 }
6 new Thread(new MyRunnable).start( );
(3)使用匿名类:
1 new Thread(new Runnable( ){
2 public void run( ){
3 //执行耗时操作
4 }
5 }).start( );
2、Android不允许在子线程中更新UI,只能在主线程中更新。
1 private Handler handler = new Handler( ){
2 public void handleMessage(Message msg){
3 switch(msg.what){ //msg的what字段是一个标志字段,整型
4 case xxx:
5 //在这里可以进行UI操作
6 textView.setText("Change text succeed!") //改变textView的字符
7 break;
8 default:
9 break;
10 }
11 }
12 }
(2)在子线程中需要进行UI操作时(如按钮点击事件中),创建一个Message对象,并通过Handler对象的sendMessage方法将该消息发送出去,比如:
1 public static final int UPDATE_TEXT = 1; //修改UI的标志值
2 ......
3 @Override
4 public void onClick(View v){
5 switch(v.getId( )){
6 case R.id.chage_text_btn:
7 new Thread(new Runnable( ){
8 @Override
9 public void run( ){
10 Message msg = new Message( );
11 msg.what = UPDATE_TEXT ;
12 handler.sendMessage(msg);
13 }
14 }).start( );
15 break;
16
17 default:
18 break;
19 }
20 }
1 class MyAsyncTask extends AsyncTask<Params, Progress, Result>
(五)Service
1、定义Service:
1 public class MyService extends Service {
2 @Override
3 public IBinder onBind(Intent intent) {
4 return null;
5 }
6
7 @Override
8 public void onCreate() {
9 super.onCreate();
10 Log.d("MyService", "onCreate executed");
11 }
12
13 @Override
14 public int onStartCommand(Intent intent, int flags, int startId) {
15 Log.d("MyService", "onStartCommand executed");
16 return super.onStartCommand(intent, flags, startId);
17 }
18
19 @Override
20 public void onDestroy() {
21 super.onDestroy();
22 Log.d("MyService", "onDestroy executed");
23 }
24 }
2、Service类中有一个抽象方法onBind,还有三个常用方法:
1 <application
2 ... >
3 <service android:name=".MyService" >
4 </service>
5 ...
6 </application>
1 Intent startIntent = new Intent(this, MyService.class);
2 startService(startIntent);
(2)停止:
1 Intent stopIntent = new Intent(this, MyService.class);
2 stopService(stopIntent);
5、Activity和Service通信:
(1)在Service中安插内线Binder,并在onBind方法中发送这个内线:
1 public class MyService extends Service {
2
3 private DownloadBinder mBinder = new DownloadBinder();
4
5 class DownloadBinder extends Binder { //自定义Binder,模拟下载功能
6 public void startDownload() {
7 Log.d("MyService", "startDownload executed");
8 }
9
10 public int getProgress() {
11 Log.d("MyService", "getProgress executed");
12 return 0;
13 }
14 }
15
16 @Override
17 public IBinder onBind(Intent intent) {
18 return mBinder;
19 }
20 ... //其他方法
21 }
(2)在Activity中创建内线及ServiceConnection,其中的onServiceConnected方法即可接收内线IBinder并通过向下转型获取Binder:
1 ...
2 private MyService.DownloadBinder downloadBinder;
3 private ServiceConnection connection = new ServiceConnection() {
4 @Override
5 public void onServiceConnected(ComponentName name, IBinder service) {
6 downloadBinder = (MyService.DownloadBinder) service;
7 downloadBinder.startDownload();
8 downloadBinder.getProgress();
9 }
10
11 @Override
12 public void onServiceDisconnected(ComponentName name) {
13
14 };
15 };
16 ...
(3)在合适的时候(如按钮的点击事件等)绑定Activity与Service:
1 Intent bindIntent = new Intent(this, MyService.class);
2 bindService(bindIntent, connection, BIND_AUTO_CREATE); //BIND_AUTO_CREATE指当绑定后,自动创建Service
(4)解除绑定:
1 if(connection != null){
2 unbindService(connection);
3 }
1 startService( )
2 onCreate( )
3 onStartCommand( )
4 onDestory( )
5 bindService( )
6 unbindService( )
7 stopService( )
8 stopSelf( ) //在Service中任何地方都可以用这个方法结束服务本身
9 onBind( )
(3)如果startService( )和bindService( )都调用了,那么必须同时满足unbindService( )和stopService( )都被调用才会执行onDestory( )方法。
7、前台Service:在系统状态栏中一直显示的可见Service,只需在Service的onCreate方法中添加如下代码即可(其实是通知的用法):
1 @Override
2 public void onCreate() {
3 super.onCreate();
4 ...
5 Notification notification = new Notification(R.drawable.ic_launcher,
6 "Notification comes", System.currentTimeMillis());
7 Intent notificationIntent = new Intent(this, MainActivity.class);
8 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
9 notificationIntent, 0);
10 notification.setLatestEventInfo(this, "This is title",
11 "This is content", pendingIntent);
12 startForeground(1, notification);
13 }
8、IntentService:
服务的代码默认都是在主线程中的,如果直接在服务里去处理一些耗时逻辑,就很容易出现ANR(Application Not Responding)的情况。这时就可以方便的使用已经把多线程封装好的IntentService类:
1 public class MyIntentService extends IntentService {
2
3 public MyIntentService() { //需要一个无参的构造方法,调用父类的有参构造方法
4 super("MyIntentService");
5 }
6
7 @Override
8 protected void onHandleIntent(Intent intent) { //这个方法默认在子线程中运行
9 // 打印当前线程ID
10 Log.d("MyIntentService", "Thread id is "
11 + Thread.currentThread().getId());
12
13 // 在这里已经是在子线程中运行了,可以执行一些耗时操作,但不能执行UI操作
14 try {
15 Thread.sleep(1000);
16 } catch (Exception e) {
17 e.printStackTrace();
18 }
19 }
20
21 @Override
22 public void onDestroy() {
23 super.onDestroy();
24 Log.d("MyIntentService", "onDestroy executed");
25 }
26 }
IntentService在任务处理完后,会自动调用onDestory方法,不用再去人工调用unbindService或stopService方法。其他用法和普通Service一样。
(六)Service最佳实践:后台定时任务
1 import java.util.Date;
2
3 import android.app.AlarmManager;
4 import android.app.PendingIntent;
5 import android.app.Service;
6 import android.content.Intent;
7 import android.os.IBinder;
8 import android.os.SystemClock;
9 import android.util.Log;
10
11 public class LongRunningService extends Service {
12
13 @Override
14 public IBinder onBind(Intent intent) {
15 return null;
16 }
17
18 @Override
19 public int onStartCommand(Intent intent, int flags, int startId) {
20 //创建子线程打印当前时间,模拟定时任务
21 new Thread(new Runnable() {
22 @Override
23 public void run() {
24 Log.d("LongRunningService",
25 "executed at " + new Date().toString());
26 }
27 }).start();
28 //1.创建AlarmManager
29 AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
30 int aMinute = 60 * 1000; // 一分钟的毫秒数
31 long triggerAtTime = SystemClock.elapsedRealtime() + aMinute;
32 //2.创建跳到广播接收器的Intent
33 Intent i = new Intent(this, AlarmReceiver.class);
34 //3.创建PendingIntent
35 PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
36 //4.使用AlarmManager的set方法
37 //第一个参数:指定工作类型,有四种:ELAPSED_REALTIME_WAKEUP表示定时任务触发时间从
38 //系统开机算起,会唤醒CPU;ELAPSED_REALTIME,同ELAPSED_REALTIME_WAKEUP,但不会唤醒CPU;
39 //RTC表示从1970-1-1 00:00算起,不会唤醒CPU,RTC_WAKEUP同RTC,但会唤醒CPU。
40 //注:唤醒CPU和唤醒屏幕是不同的概念。
41 manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
42
43 return super.onStartCommand(intent, flags, startId);
44 }
45 }
3、创建AlarmReceiver类:
1 import android.content.BroadcastReceiver;
2 import android.content.Context;
3 import android.content.Intent;
4
5 public class AlarmReceiver extends BroadcastReceiver {
6
7 @Override
8 public void onReceive(Context context, Intent intent) {
9 Intent i = new Intent(context, LongRunningService.class);
10 context.startService(i); //反过来再启动服务,交替循环进行下去
11 }
12 }
4、在活动中启动服务:
1 import android.app.Activity;
2 import android.content.Intent;
3 import android.os.Bundle;
4
5 public class MainActivity extends Activity {
6
7 @Override
8 protected void onCreate(Bundle savedInstanceState) {
9 super.onCreate(savedInstanceState);
10 setContentView(R.layout.activity_main);
11
12 Intent i = new Intent(this, LongRunningService.class);
13 startService(i);
14 }
15 }
5、在AndroidManifest.xml中注册服务和广播接收器。
【本章结束】