gpt4 book ai didi

Android 从服务更新 Activity UI

转载 作者:IT老高 更新时间:2023-10-28 13:05:27 24 4
gpt4 key购买 nike

我有一项服务一直在检查新任务。如果有新任务,我想刷新 Activity UI 以显示该信息。我确实找到了 https://github.com/commonsguy/cw-andtutorials/tree/master/18-LocalService/这个例子。这是一个好方法吗?还有其他例子吗?

谢谢。

最佳答案

请参阅下面的原始答案 - 该模式运作良好,但最近我开始使用不同的服务/Activity 通信方法:

  • 使用 bound service这使 Activity 能够直接获得引用服务,从而允许直接调用它,而不是而不是使用 Intent。
  • 使用 RxJava 执行异步操作。

  • 如果服务需要继续后台操作,即使没有Activity 正在运行,同时从 Application 启动服务类,以便它在未绑定(bind)时不会停止。

与 startService()/LocalBroadcast 技术相比,我发现这种方法的优势是

  • 不需要数据对象来实现 Parcelable - 这对我来说尤其重要,因为我现在在 Android 和 iOS 之间共享代码(使用 RoboVM)
  • RxJava 提供固定(和跨平台)调度,以及轻松组合顺序异步操作。
  • 这应该比使用 LocalBroadcast 更有效,尽管使用 RxJava 的开销可能会超过它。

一些示例代码。首先是服务:

public class AndroidBmService extends Service implements BmService {

private static final int PRESSURE_RATE = 500000; // microseconds between pressure updates
private SensorManager sensorManager;
private SensorEventListener pressureListener;
private ObservableEmitter<Float> pressureObserver;
private Observable<Float> pressureObservable;

public class LocalBinder extends Binder {
public AndroidBmService getService() {
return AndroidBmService.this;
}
}

private IBinder binder = new LocalBinder();

@Nullable
@Override
public IBinder onBind(Intent intent) {
logMsg("Service bound");
return binder;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}

@Override
public void onCreate() {
super.onCreate();

sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor pressureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
if(pressureSensor != null)
sensorManager.registerListener(pressureListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if(pressureObserver != null) {
float lastPressure = event.values[0];
float lastPressureAltitude = (float)((1 - Math.pow(lastPressure / 1013.25, 0.190284)) * 145366.45);
pressureObserver.onNext(lastPressureAltitude);
}
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
}, pressureSensor, PRESSURE_RATE);
}

@Override
public Observable<Float> observePressure() {
if(pressureObservable == null) {
pressureObservable = Observable.create(emitter -> pressureObserver = emitter);
pressureObservable = pressureObservable.share();
}
return pressureObservable;
}

@Override
public void onDestroy() {
if(pressureListener != null)
sensorManager.unregisterListener(pressureListener);
}
}

还有一个绑定(bind)到服务并接收压力高度更新的Activity:

public class TestActivity extends AppCompatActivity {

private ContentTestBinding binding;
private ServiceConnection serviceConnection;
private AndroidBmService service;
private Disposable disposable;

@Override
protected void onDestroy() {
if(disposable != null)
disposable.dispose();
unbindService(serviceConnection);
super.onDestroy();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.content_test);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
logMsg("BlueMAX service bound");
service = ((AndroidBmService.LocalBinder)iBinder).getService();
disposable = service.observePressure()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(altitude ->
binding.altitude.setText(
String.format(Locale.US,
"Pressure Altitude %d feet",
altitude.intValue())));
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
logMsg("Service disconnected");
}
};
bindService(new Intent(
this, AndroidBmService.class),
serviceConnection, BIND_AUTO_CREATE);
}
}

这个Activity的布局是:

<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.controlj.mfgtest.TestActivity">

<TextView
tools:text="Pressure"
android:id="@+id/altitude"
android:gravity="center_horizontal"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>
</layout>

如果服务需要在没有绑定(bind) Activity 的情况下在后台运行,它也可以从 Application 类启动,也可以在 OnCreate() 中使用 Context#startService() .


我的原始答案(2013 年):

为您服务:(在下面的示例中使用 COPA 作为服务)。

使用 LocalBroadCastManager。在您的服务的 onCreate 中,设置广播器:

broadcaster = LocalBroadcastManager.getInstance(this);

当你想通知 UI 某事时:

static final public String COPA_RESULT = "com.controlj.copame.backend.COPAService.REQUEST_PROCESSED";

static final public String COPA_MESSAGE = "com.controlj.copame.backend.COPAService.COPA_MSG";

public void sendResult(String message) {
Intent intent = new Intent(COPA_RESULT);
if(message != null)
intent.putExtra(COPA_MESSAGE, message);
broadcaster.sendBroadcast(intent);
}

在您的 Activity 中:

在 onCreate 上创建一个监听器:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.copa);
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String s = intent.getStringExtra(COPAService.COPA_MESSAGE);
// do something here.
}
};
}

并在 onStart 中注册:

@Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((receiver),
new IntentFilter(COPAService.COPA_RESULT)
);
}

@Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
super.onStop();
}

关于Android 从服务更新 Activity UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14695537/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com