Я использую обновленную версию этого ответа , чтобы связать (привязать) действие с услугой.
MyService.java
public class MyService extends Service {
private LocalBinder binder = new LocalBinder();
private Observable<Integer> responseObservable;
private ObservableEmitter<Integer> responseObserver;
public static boolean isRunning = false;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder()
.setLenient()
.create());
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Client client = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build())
.addConverterFactory(factory)
.build()
.create(Client.class);
for (//some loop) {
Response<Result> response = client.search(//some params here)
.execute();
responseObserver.onNext(response.code());
}
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
isRunning = false;
}
public Observable<Message> observeResponse() {
if (responseObservable == null) {
responseObservable = Observable.create(em -> responseObserver = em);
responseObservable = responseObservable.share();
}
return responseObservable;
}
public class LocalBinder extends Binder {
public DService getService() {
return MyService.this;
}
}
}
MainActivity.java
public class MainActivityextends AppCompatActivity {
private MyService service;
private Disposable disposable;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
service = ((MyService.LocalBinder) iBinder).getService();
disposable = service.observeResponse()
.observeOn(Schedulers.newThread())
.subscribe(responseCode -> updateUI()); //this must run on main thread
startService(new Intent(MainActivity.this, MyService.class));
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onDestroy() {
if (disposable != null)
disposable.dispose();
unbindService(serviceConnection);
super.onDestroy();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
//....
Button start = findViewById(R.id.start);
start.setOnClickListener(v -> {
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
});
//....
}
}
Если я использую observeOn(AndroidSchedulers.mainThread())
, я получаю NetworkOnMainThreadException
, а если я использую observeOn(Schedulers.newThread())
, я получаю OnErrorNotImplementedException: Only the original thread that created a view hierarchy can touch its views.
Я знаю, что означают обе ошибки, в обычных случаях я могу легко их устранить, но здесь я ничего не делаю.
Мне нужно, чтобы сетевые запросы в службе выполнялись синхронно, потому что она находится вцикл, и я обрабатываю каждый результат запроса по порядку, асинхронные вызовы не вариант для меня.
Я пытался runOnUiThread(() -> updateUI())
, но он выдает ту же ошибку.Я также пытался запустить службу в новом потоке, но все еще оставалась та же ошибка.