Activity中通过bindService启动Service

    在Activity中,启动Service有两种方式:startService方式,bindService方式。

    如果想要调用Service中的方法,只能使用bindService方式。因为这种方式可以拿到Service的Binder对象,从而可以调用Service中的方法。

    这里,我们不说怎么调用,只是来验证一个问题:ServiceConnection接口中的onServiceConnected方法执行在哪个线程(另一种问法是:在onServiceConnected方法中是否可以直接更新UI)。

    结论:执行在主线程,也就是说,在这个方法中可以直接进行UI更新。

    下面,用一个例子来证明上面的结论。

    自定义Service类

public class SevenService extends Service {


    private int progress = 0;

    private OnProgressListener mOnProgressListener;

    public interface OnProgressListener{
        void onProgress(int progress);
    }

    public void setOnProgressListener(OnProgressListener listener){
        mOnProgressListener = listener;
    }

    public class SevenBinder extends Binder {

        public SevenService getService(){
            return SevenService.this;
        }
    }


    public int getProgress(){
        return progress;
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new SevenBinder();
    }


    //模拟下载
    public void startDownload(){
        new Thread(new Runnable() {
            @Override
            public void run() {

                Log.e("startDownload()","Thread: " + Thread.currentThread().getName());//Thread: Thread-9945

                while (progress < 100){

                    progress += 10;

                    //通知调用方
                    if(null!= mOnProgressListener){
                        mOnProgressListener.onProgress(progress);
                    }

                    try{
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }


    public void startSetText(){
        progress = 19;

        if(null!= mOnProgressListener){
            mOnProgressListener.onProgress(progress);
        }
    }
}

Service是四大组件之一,记得在清单文件中注册。

Activity类

public class ServiceActivity extends AppCompatActivity {

    private SevenService mSevenService;

    private int progress;
    private TextView service_text;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service);

        service_text = (TextView) findViewById(R.id.service_text);
        Log.e("ServiceActivity","Thread: " + Thread.currentThread().getName());//Thread: main
        //
        Intent intent = new Intent(this, SevenService.class);
        // 标志位BIND_AUTO_CREATE使得服务中onCreate得到执行,onStartCommand不会执行
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    //点击按钮
    public void bt_download(View view){
//        mSevenService.startDownload();//这个方法内部开启了子线程

        mSevenService.startSetText();

    }



    /***
     * 通过一系列验证,终于确定了:ServiceConnection的onServiceConnected方法是运行在主线程的,可以直接更新UI,
     */
    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定成功,回调这个方法
            mSevenService = ((SevenService.SevenBinder)service).getService();

            Log.e("onServiceConnected","Thread: " + Thread.currentThread().getName());//Thread: main

            mSevenService.setOnProgressListener(new SevenService.OnProgressListener() {
                @Override
                public void onProgress(final int progress) {

                    Log.e("setOnProgressListener","Thread: " + Thread.currentThread().getName());//Thread: Thread-9894
                    //如果点击按钮调用的是startSetText()方法,这里就可以在回调中直接更新UI。
                    service_text.setText(""+progress);

                    //这里不能直接更新UI的原因是:在SevenService中,startDownload()方法开启了子线程,所以mOnProgressListener.onProgress(progress);是在子线程中执行的

                    //android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

//                    runOnUiThread(new Runnable() {
//                        @Override
//                        public void run() {
//                            service_text.setText(""+progress);
//                        }
//                    });

                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //如果Service中途挂掉,client端也能通过onServiceDisconnected感知到(通过Binder的linkToDeath实现)
        }
    };


    @Override
    protected void onDestroy() {

        unbindService(conn);//解绑

        super.onDestroy();
    }
}

 
 
    从打印的日志也可以得到上述结论:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值