• 【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析


    .先讲讲怎么使用bindService()绑定服务

        应用组件(客户端)可以调用bindService()绑定到一个serviceAndroid系统之后调用serviceonBind()方法,它返回一个用来与service交互的IBinder

      绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传

    bindService()ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder

    注:只有activities,services,contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service

    所以,从你的客户端绑定到一个service,你必须:

    • 1实现ServiceConnection.

      你的实现必须重写两个回调方法:

      • onServiceConnected()

        系统调用这个来传送在serviceonBind()中返回的IBinder

      • OnServiceDisconnected()

        Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.

    • 2调用bindService(),传给它ServiceConnection的实现.

    • 3当系统调用你的onServiceConnected()方法时,你就可以使用接口定义的方法们开始调用service了.

    • 4要与service断开连接,调用unbindService()

        当你的客户端被销毁,它将从service解除绑定,但是你必须总是在你完成与service的交互时或当你的activity暂停于是service在不被使用时可以关闭此两种情况下解

      除绑定.(下面会讨论更多在适当的时候绑定和解除绑定的问题.

      使用这个ServiceConnection,客户端可以绑定到一个service,通过把它传给bindService().例如:

      Intentintent = new Intent(this, LocalService.class);

      bindService(intent,mConnection, Context.BIND_AUTO_CREATE);

    • 第一个bindService()的参数是一个明确指定了要绑定的serviceIntent

    • 第二个参数是ServiceConnection对象.

    • 第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBINDBIND_NOT_FOREGROUND,不想指定时设为0即可.。

    补充事项

    下面是一些关于绑定到service的重要事项:

    • 你总是需要捕获DeadObjectException异常.它会在连接被打断时抛出.这是被远程方法抛出的唯一异常.

    • 对象引用计数是跨进程的作用的.

    • 你应该在客户端的生命期内使绑定和解除绑定配对进行,例如:

      • 如果你需要在你的activity可见时与service交互,你应该在onStart()绑定并在onStop()中解除绑定.

      • 如果你想让你的activity即使在它停止时也能接收回应,那么你可以在onCreate()中绑定并在onDestroy()中解除绑定.注意这意味着你的activity需要使用在自己整

        个运行期间使用service(即使位于后台),所以如果service在另一个进程中,那么你增加了这个进程的负担而使它变得更容易被系统杀掉.

        注:你一般不应该在你的activityonResume()onPause()中绑定和解除绑定到service,因为这些回调方法,出现在每个生命期变化中,并且你需要使发生在这

        些变化中的处理最小化.还有,如果你应用中的多个activity绑定到同一个service,并且有一个变化发生在其中两个activity之间,service可能在当前activity解除绑

        (pause)和下一个绑定前(rusume)被销毁又重建.

    2.管理(多个客户端)BoundService的生命期

      当一个service的所有客户端都解除绑定,Android系统就销毁它(除非它是从onStartCommand()启动).如果你的service是一个纯boundservice,你不需管理它的生命

    Android系统会为你管理它.。

      然而,如果你选择了实现onStartCommand()回调方法,那么你必须明确地停止service,因为service现在被认为是"开始的".在此情况下,service会一直运行,直

    service使用stopSelf()停止它自己或另外的组件调用了stopService()停止了它,不管是否有客户端绑定了它.

      另外,如果你的service已经启动并且接受绑定,那么当系统调用你的onUnbind()方法,你可以选择返回true表示你想在客户端下一次绑定到service时接受一个

    onRebind()的调用(而不是一个对onBind()的调用)onRebind()返回void,但是客户端依然会在它的onServiceConnected()回调中接收到IBinder.下图演示了这种生命其的

    逻辑:


    3。bindService和startService混合使用时

    1.如果先bindService,再startService:

    在bind的Activity退出的时候,Service会执行unBind方法而不执行onDestory方法,因为有startService方法调用过,所以Activity与Service解除绑定后会有一个与调用者没有关连的Service存在

    2.如果先bindService,再startService,再调用Context.stopService

    Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行onDestory,如果要立刻执行stopService,就得先解除绑定

     ---------------------------

    把上面的"如果先bindService,再startService"换成"如果先startService,再bindService",结果是一样的

    问题:

    如果在一个Activity的onCreate方法中,

    bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);

    再startService(serviceIntent);

    退出这个Activity时,会执行onUnBind

    但是再次进入这个Activity的时候,为什么不执行onBind方法了?只有在这个Service销毁后(执行onDestory),再进这个Activity才会执行onBind,还有就是当有两个客户端时,在第一个客户端startServie启动服务再bindService绑定服务,这时跳到第二个客户端里(启动时会调用onBind()),再客户端startServie启动服务再bindService绑定服务,启动时不会调用用onBind()了(因为之前客户端已经启动后没有onDestory()销毁Service,所以再客户端第二次绑定服务时,只会返回IBinder对象给onServiceConnected()),而且要注意的是当,当第一个服务启动并绑定一个服务时,再跳去第二个服务端启动并绑定这个服务时,第二个服务端再解绑时,不会调用onUnbind(),只有回到第一个客户端时,解绑这是才会调用onUnbind(),顺序反过来结果是一样的。得出一个结论是:当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()。

    package yy.android.service;


    import org.apache.http.conn.ClientConnectionManager;

    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.content.SharedPreferences.Editor;
    import android.os.Binder;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;

    public class ServiceActivity extends Activity {
    //    private final String TAG = "ServiceActivity";
        private Button unbind;
        public static IService iService=null;
        private Button mSkiptoClient;
        private Button mStart;
        public static EditText medit;
        private Button mBind;
        private Button mStop;
        public static ServiceConnection connection=new ServiceConnection() {
            public void onServiceDisconnected(ComponentName name) {
                Log.d("LOG","Activity ->Disconnected the LocalService");
            }
            public void onServiceConnected(ComponentName name, IBinder service) {
                // TODO Auto-generated method stub
                //获取连接的服务对象
                  //System.out.println("Connection!!!");
                  iService=(IService)service;
                  medit.setText(iService.getName());
                  Log.d("LOG","Activity ->Connected the Service");
            }
        };  
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            Log.d("LOG","Activity ->OnCreate");
            unbind = (Button)findViewById(R.id.unbind);
            mSkiptoClient = (Button)findViewById(R.id.skip);
            mStart = (Button)findViewById(R.id.start);
            mStop = (Button )findViewById(R.id.stop);
            medit = (EditText)findViewById(R.id.edit);
            mBind = (Button)findViewById(R.id.connection);
            mBind.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                     Intent intent=new Intent(ServiceActivity.this,LocalService.class);
                     bindService(intent,connection, BIND_AUTO_CREATE);    
                }
            });
            mStart.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Intent intent=new Intent(ServiceActivity.this,LocalService.class);    
                    startService(intent);
                }
            });
            mStop.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Intent intent=new Intent(ServiceActivity.this,LocalService.class);
                    stopService(intent);
                }
            });
            mSkiptoClient.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Intent intent = new Intent("android.intent.action.YClient");
                    startActivity(intent);
                }
            });
            unbind.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    unbindService(connection);
                }
            });
        }
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            super.onDestroy();
            Log.d("LOG","Activity ->OnDestory");
        }
        @Override
        protected void onPause() {
            // TODO Auto-generated method stub
    //        unbindService(connection);
            Log.d("LOG","Activity ->OnPause");
            super.onPause();
            
        }
        @Override
        protected void onRestart() {
            // TODO Auto-generated method stub
            super.onRestart();
            Log.d("LOG","Activity ->OnRestart");
        }
        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            Log.d("LOG","Activity ->OnResume");
    //         Intent intent=new Intent(ServiceActivity.this,LocalService.class);
    //         bindService(intent,connection, BIND_AUTO_CREATE);    
            super.onResume();
            
        }
        protected void onStart() {
            // TODO Auto-generated method stub
            super.onStart();
            Log.d("LOG","Activity ->OnSatrt");
        }
        @Override
        protected void onStop() {
            // TODO Auto-generated method stub
            super.onStop();
            Log.d("LOG","Activity ->OnStop");
        }
        

    }

    ////////////////////////////////////////////////////////////////////////////

    package yy.android.service;

    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;

    public class CLient extends Activity{
        private IService iService2=null;
        private Button unbind2;
        private Button mStart2;
        private EditText medit2;
        private Button mBind2;
        private Button mStop2;
        ServiceConnection connection2=new ServiceConnection() {
             public void onServiceDisconnected(ComponentName name) {
                Log.d("LOG","Client ->Disconnected the LocalService");
            }
            public void onServiceConnected(ComponentName name, IBinder service) {
                // TODO Auto-generated method stub
                 //获取连接的服务对象
                  //System.out.println("Connection!!!");
                  iService2=(IService)service;
                   medit2.setText(iService2.getName());
                   Log.d("LOG","Client ->Connected the Service");
            }
         };  
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.client);
            Log.d("LOG","Client ->OnCreate");
            unbind2 = (Button)findViewById(R.id.unbind2);
            mStart2 = (Button)findViewById(R.id.start2);
            mStop2 = (Button )findViewById(R.id.stop2);
            medit2 = (EditText)findViewById(R.id.edit2);
            mBind2 = (Button)findViewById(R.id.connection2);
            mBind2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                     Intent intent=new Intent(CLient.this,LocalService.class);
                     bindService(intent,connection2, BIND_AUTO_CREATE);    
                }    
            });    
            mStart2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {  
                    // TODO Auto-generated method stub
                    Intent intent=new Intent(CLient.this,LocalService.class);    
                    startService(intent);
                }
            });
            mStop2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Intent intent=new Intent(CLient.this,LocalService.class);
                    stopService(intent);
                }
            });
            unbind2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.e("LOG", "Unbind");
                    unbindService(connection2);
                    Log.e("LOG", "Unbind");
                }  
            });
        }     
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            //unbindService(connection2);
            Log.d("LOG","Client ->OnDestory");
            super.onDestroy();
            
        }
        @Override
        protected void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            Log.d("LOG","Client ->OnPause");
        }
        @Override
        protected void onRestart() {
            // TODO Auto-generated method stub
            super.onRestart();
            Log.d("LOG","Client ->OnRestart");
        }
        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
            Log.d("LOG","Client ->OnResume");
        }
        @Override
        protected void onStart() {
            // TODO Auto-generated method stub
            super.onStart();
            Log.d("LOG","Client ->OnSatrt");
        }
        @Override
        protected void onStop() {
            // TODO Auto-generated method stub
            super.onStop();
            Log.d("LOG","Client ->OnStop");
        }
        
    }
    ///////////////////////////////////////////////////////////////////

    package yy.android.service;
     
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;

    public class LocalService extends Service{
        private MyBind myBind=new MyBind();
        
        public IBinder onBind(Intent intent) {
                //System.out.println("Service onBind!!!");
                Log.d("LOG","LocalService ->onBind");
                return myBind;
            }
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            Log.d("LOG","LocalService ->onCreate");
            super.onCreate();
            
        }
         @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
             Log.d("LOG","LocalService ->onDestory");
            super.onDestroy();
            
        }
        @Override
        public void onStart(Intent intent, int startId) {
            // TODO Auto-generated method stub
            Log.d("LOG","LocalService ->onSatrt");
            super.onStart(intent, startId);
            
        }
        @Override  
        public boolean onUnbind(Intent intent) {
            // TODO Auto-generated method stub
            Log.d("LOG","LocalService ->onUnbind");
            return super.onUnbind(intent);
            //return true;
        }
        
        @Override
        public void onRebind(Intent intent) {
            // TODO Auto-generated method stub
            Log.d("LOG","LocalService ->onRebind");
            super.onRebind(intent);
            
        }
        
        

        public class MyBind extends Binder implements IService{

             public String getName() {
                 // TODO Auto-generated method stub
                 return "YUZHIBOYI";
             }
         }
    }
    /////////////////////////////////////////////////////////////////////////

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="yy.android.service"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk android:minSdkVersion="10" />

        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:name=".ServiceActivity"
                
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name=".CLient"
                
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.YClient" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
            <service android:name=".LocalService">
               <intent-filter>  
                   <action android:name="com.yy.yy"/>
                   <category android:name="android.intent.category.DEFAULT" />
               </intent-filter>  
            </service>   
        </application>
    </manifest>

    /////////////////////////////////////////////////////////

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
        <EditText
            android:id="@+id/edit2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
        ></EditText>     
        <Button  
            android:id = "@+id/connection2"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/Bind"  
            />  
            <Button  
            android:id = "@+id/start2"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/Start"  
            />  
            <Button  
            android:id = "@+id/stop2"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/StopService"  
            />  
              <Button  
            android:id = "@+id/unbind2"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/UnbindService"  
            />
    </LinearLayout>

    //////////////////////////////////////////////////////

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
       <EditText
            android:id="@+id/edit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
        ></EditText>     
        <Button  
            android:id = "@+id/connection"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/Bind"  
            />  
            <Button  
            android:id = "@+id/start"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/Start"  
            />  
            <Button  
            android:id = "@+id/stop"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/StopService"  
            />  
            <Button  
            android:id = "@+id/skip"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/Skip"  
            />  
            <Button  
            android:id = "@+id/unbind"  
            android:layout_width = "wrap_content"  
            android:layout_height = "wrap_content"  
            android:text = "@string/UnbindService"  
            /> 
    </LinearLayout>

    ////////////////////////////////////////////////////

    混合使用的时候总结的,欢迎大家来一起讨论!


    Le王冬冬 博客分享地址: http://www.cnblogs.com/dongdong230/ 每个人都应做一天攻城狮
  • 相关阅读:
    bzoj 3709: [PA2014]Bohater【贪心】
    bzoj 3714: [PA2014]Kuglarz【最小生成树】
    bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】
    bzoj 2087: [Poi2010]Sheep【凸包+极角排序+dp】
    bzoj 3830: [Poi2014]Freight【dp】
    bzoj 3930: [CQOI2015]选数【快速幂+容斥】
    bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式【后缀自动机】
    bzoj 1614: [Usaco2007 Jan]Telephone Lines架设电话线【二分+spfa】
    bzoj 1640||1692: [Usaco2007 Dec]队列变换【后缀数组】
    bzoj 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛【Floyd】
  • 原文地址:https://www.cnblogs.com/dongdong230/p/4183025.html
Copyright © 2020-2023  润新知