英文:
how is the UI being able to be updated from the service?
问题
关于这篇帖子,基本上我将我的MainActivity
注册到了我的服务中(我只是将正在运行的活动的引用传递给了服务),并从那里更新我的用户界面。但我困惑的是,如果Service
是一个独立的线程(不是UI线程),而我却从Service
线程调用UI更新,为什么它能正常工作呢?据我所知,只有UI线程才能调用UI更新,对吗?
供参考,我只是重新贴出了与相关帖子中的代码,展示了我如何从service
中更新UI:
public class MainActivity extends AppCompatActivity{
... onCreate(...){
//服务已连接
service.register(MainActivity.this);
}
}
public class Service extends Service(){
private MainActivity mActivity = null;
public void register(MainActivity activity){
mActivity = activity;
}
public void updateUI(){
mActivity.getUI_Component().doSomething().update();
}
}
英文:
With regard to this post, basically I register my MainActivity
to my service( I just pass a reference of my running activity to the service) and update my UI from there. But my confusion is that, if Service
is a separate thread(not the UI thread) and I'm calling UI updates from the Service
thread, why is it working? AFAIK , only the UI thread is supposed to be able to call the UI updates, right?
For, reference, I'm just reposting the code from the related post, on how I am updating the UI from the service
:
public class MainActivity extends AppCompatActivity{
... onCreate(...){
//service already connected
service.register(MainActivity.this);
}
}
public class service extends Service(){
private MainActivity mActivity = null;
public void register(MainActivity activity){
mActivity = activity;
}
public void updateUI(){
mActivity.getUI_Component().doSomething().update();
}
}
答案1
得分: 2
以下是您要求的翻译部分:
默认情况下,服务在主线程上运行,这并不是问题的关键。而且你认为只需要简单地传递引用的方式并不是一个好的做法。你可以这样做,先绑定到服务,然后获取服务实例,然后再传递活动实例。
在服务内部,通过 onBind
方法返回服务实例,使用 LocalBinder
,然后在活动中使用 ServiceConnection
来连接它。
protected ServiceConnection mServerConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext 在代码上面有定义,我认为没有必要解释是什么
mContext.bindService(intent, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(intent);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
在您的服务内部,类似这样:
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
onServiceConnected
方法会返回绑定实例。使用 binder.getService()
并将您的工作代码放在那里。
英文:
Service by default runs on the main thread , that is not at all the issue. And the way you presuming that you simply pass the reference is not a good practice. What you can do is bind to the service and get the service instance prior passing the activity instance.
inside service onBind
return the service using LocalBinder
and in the activity use ServiceConnection
to connect to it
protected ServiceConnection mServerConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext is defined upper in code, I think it is not necessary to explain what is it
mContext.bindService(intent, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(intent);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
Inside your service something like this
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
onServiceConnected
will return binder instance . use binder.getService()
and put your working code there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论