首页 > 代码库 > Service & Timer & Handler & leaked ServiceConnection

Service & Timer & Handler & leaked ServiceConnection

定义一个Service,每隔一秒钟,变量count增加1;

在Activity里bindService,然后利用new Timer() 和 Handler,每隔一秒利用IBinder实例mBinder的getNumber()方法读取count的最新值,并显示在TextView.

 

首次运行,报错。

Debug模式,发现MainActivity.class 79行的HandleMessage()方法在onServiceConnected()(MainActivity.class 第68行)之前就执行了,mBinder对象还未初始化(该对像是回调onServiceConnected()方法时初始化 ), 所以才会出现NullPointerException.

试着去解决问题:在83行增加判断语句

 83 if (mBinder != null) {   //**此处未加if判断语句就会出错,提示NullPointerException 84     // 获取Service中的实时Count值,并在UI中显示 85     mCount = mBinder.getNumber() + ""; 86     }
 87  88  // 在Toast中显示count 89  textView1.setText(mCount);

然后在程序可以运行,但是刚开始TextView显示“default”(mCount的初始值) , 一秒钟之后才开始显示累加的数字。

但是LogCat还是有抱错

 

问题1:为什么HandleMessage()方法在onServiceConnected()之前就执行了?

问题2:为什么有ServiceConnection 泄漏?

问题2的已解决:在MainActivity中,改写onDestroy()

1 @Override2     protected void onDestroy() {3         super.onDestroy();4         //在关闭Activity时取消与mService的绑定5         unbindService(conn);        6     }

 

 

*******************************************************************************************************************************

Service定义如下:

 1 package com.rocky.myfirstserviceapp.service; 2  3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.Binder; 6 import android.os.IBinder; 7  8 public class MyService extends Service { 9 10     private int count = 0;11     private boolean quit = false;12     private MyBinder binder = new MyBinder();13     14     public class MyBinder extends Binder{15         public int getNumber(){16             //获取即时数值17             return count;18         }19     }20     21     @Override22     public IBinder onBind(Intent intent) {23         System.out.println("Service is binded");24         return binder; //返回IBinder实例25     }26     27     @Override28     public void onCreate() {29         super.onCreate();30         System.out.println("Service is Created");31         32         //新建一 个线程,每隔1秒加133         new Thread(){34             public void run() {35                 while(!false){36                     try {37                         Thread.sleep(1000);38                     } catch (InterruptedException e) {39                         e.printStackTrace();40                     }41                     count++;42                 }43             };44         }.start();45     }46     47     @Override48     public boolean onUnbind(Intent intent) {49         System.out.print("Service is Unbinded");50         return true;51     }52     53     @Override54     public void onDestroy() {55         super.onDestroy();56         this.quit = true;57         System.out.print("Service is destroyed");58     }59 60 }

 

*******************************************************************************************************************************

 

Activity 定义如下:

  1 package com.rocky.myfirstserviceapp;  2   3 import java.util.Timer;  4 import java.util.TimerTask;  5   6 import com.rocky.myfirstserviceapp.service.MyService;  7 import com.rocky.myfirstserviceapp.service.MyService.MyBinder;  8   9 import android.app.Activity; 10 import android.app.ActionBar; 11 import android.app.Fragment; 12 import android.app.Service; 13 import android.content.ComponentName; 14 import android.content.Intent; 15 import android.content.ServiceConnection; 16 import android.os.Bundle; 17 import android.os.Handler; 18 import android.os.IBinder; 19 import android.os.Message; 20 import android.view.LayoutInflater; 21 import android.view.Menu; 22 import android.view.MenuItem; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.TextView; 26 import android.widget.Toast; 27 import android.os.Build; 28  29 /** 30  *  31  * @author LinXing 利后Service从1增加到100, 每秒加1。 多个Activity从Service中提取即时数值 32  */ 33  34 public class MainActivity extends Activity { 35  36     // 保存所启动的Service的IBinder对象 37     private MyService.MyBinder mBinder; 38     private TextView textView1; 39  40     private ServiceConnection conn; 41  42     // 接收信息后更新UI 43     private Handler mHandler; 44  45     private String mCount = "default"; 46  47     @Override 48     protected void onCreate(Bundle savedInstanceState) { 49         super.onCreate(savedInstanceState); 50         setContentView(R.layout.activity_main); 51  52         textView1 = (TextView) findViewById(R.id.textView1); 53  54         // 创建启动Service的Intent 55         Intent intent = new Intent(this, MyService.class); 56  57  58         // 定义一个ServiceConnection对象 59         conn = new ServiceConnection() { 60  61             @Override 62             public void onServiceDisconnected(ComponentName name) { 63                 System.out.print("Service is disconnected"); 64             } 65  66             @Override 67             public void onServiceConnected(ComponentName name, IBinder service) { 68                 mBinder = (MyService.MyBinder) service; 69                 System.out.print("Service is connected"); 70             } 71         }; 72  73         // 绑定service 74         bindService(intent, conn, Service.BIND_AUTO_CREATE); 75  76         // 实现Handler 77         mHandler = new Handler() { 78             @Override 79             public void handleMessage(Message msg) { 80                 super.handleMessage(msg); 81  82                 if (msg.what == 0x33) { 83                     if (mBinder != null) {   //**此处未加if判断语句就会出错,提示NullPointerException 84                         // 获取Service中的实时Count值,并在UI中显示 85                         mCount = mBinder.getNumber() + ""; 86                     } 87  88                     // 在Toast中显示count 89                     textView1.setText(mCount); 90                 } 91  92             } 93         }; 94  95         // 计时器,每隔一秒发送一个消息 96         new Timer().schedule(new TimerTask() { 97  98             @Override 99             public void run() {100                 Message msg = new Message();101                 msg.what = 0x33;102                 mHandler.sendMessage(msg);103             }104         }, 0, 1000);105 106     }107 108     @Override109     public boolean onCreateOptionsMenu(Menu menu) {110 111         // Inflate the menu; this adds items to the action bar if it is present.112         getMenuInflater().inflate(R.menu.main, menu);113         return true;114     }115 116     @Override117     public boolean onOptionsItemSelected(MenuItem item) {118         // Handle action bar item clicks here. The action bar will119         // automatically handle clicks on the Home/Up button, so long120         // as you specify a parent activity in AndroidManifest.xml.121         int id = item.getItemId();122         if (id == R.id.action_settings) {123             return true;124         }125         return super.onOptionsItemSelected(item);126     }127 128 }

 

*******************************************************************************************************************************