您的位置:首页 > 其它

Activity中通过bindService启动Service

2017-11-19 14:24 281 查看
在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();
}
}


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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Service 启动Service
相关文章推荐