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);
        }
    }
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

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();
    }
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80

 
 
    從打印的日志也可以得到上述結論:

這里寫圖片描述
---------------------
作者:唐人小調
來源:CSDN
原文:https://blog.csdn.net/gengbaolong/article/details/78574225
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM