2014-09-15 2 views
2

Я использую RxJava для перемещения доступа к сети в отдельный поток на Android, но мой пользовательский интерфейс все еще блокируется.Блокировка пользовательского интерфейса происходит в Android, несмотря на RxJava

Я не использую неправильно наблюдаемые, как показано здесь: Android RxJava, Non Blocking?

В кодовых [A], [B] и [C] в поле ниже коде передаются в порядке [A] -> [C] - > [B], поэтому текущий поток обрабатывается штрафом, а RxJava вызывает [C], как только он получил результат. Это отлично.

Кроме того, блокировка намного лучше по сравнению с выполнением сетевого вызова в потоке пользовательского интерфейса, но у меня все еще есть небольшая блокировка. Пользовательский интерфейс остается свободным после вызова, но если сервер не отвечает за миллисекунды, он блокируется.

private search; // search is an instance variable in the same class 

    // [A] 

    Observable.just(search.find("something")) // search.find calls the REST endpoint 
      .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Action1<Search>() { 

       @Override public void call(Search search) { 
        // further processing // [B] 
       } 

      }, new Action1<Throwable>() { 

       @Override public void call(Throwable throwable) { 
        // error handler 
       } 

      }); 

    // [C] 

Может быть проблема, что поиск является переменным экземпляром в том же классе, где Наблюдаемые использует его, но вызов конечной точки выполняется из отдельной библиотеки? Это не имеет значения, не так ли?

Я делаю что-нибудь плохое, чего я не должен делать?

-

Поиск выглядит следующим образом (удалены обработки исключений для краткости):

public Search find(String searchtext) { 
    setSearchtext(searchtext); 
    SearchEndpoint.find(Session.getUser().getId(), searchtext); 
    return this; 
} 

SearchEndpoint как это:

public static Search find(final Long userId, final String searchtext) throws IOException { 
    return ApiService.api().searches().find(userId).setFind(searchtext).execute(); 
} 

и делает вызов сгенерированного Google облака конечной точки библиотека.

+0

Не могли бы вы разместить дополнительную информацию о методе search.find? Я полагаю, что его тип возврата - это поиск, и это простой синхронный вызов метода? В этом случае just() вызовет search.find(), блокирует до тех пор, пока не вернет значение, а затем обернет это значение в наблюдаемое, которое немедленно вызовет onNext, а затем onCompleted. Вместо этого: либо используйте RetroFit, либо посмотрите на Observable.create, чтобы правильно обернуть ваш вызов REST в Observable ...Спросите еще раз, если вам нужна дополнительная помощь! –

ответ

3

Попробуйте это:

Observable.create(new Observable.OnSubscribe<Search>() { 

    @Override 
    // method signature is from memory - I hope I am correct... 
    public void call(Subscriber<? super Search> subscriber) { 
     try { 
      Search search = search.find("something"); 
      subscriber.onNext(search); 
      subscriber.onCompleted(); 
     } catch (SomeException e) { 
      subscriber.onError(e); 
     } 
    } 
}) 
// and then continue with your .subscribeOn(...) 

Чтобы уточнить, может быть, это делает проблему с кодом более очевидным:

Observable.just(search.find("something")) 

явно эквивалентно

Search search = search.find("something"); 
Observable.just(search) 

И это делает его очевидно, что search.find выполняется до того, как мы когда-либо передадим управление rxjava, и он выполняется на любом нить, на которой вы сейчас находитесь, - тогда построение Наблюдаемого из предварительно вычисленного значения и доставка значения происходят в другой теме, но это не очень помогает ...

+0

Я начал использовать RxJava вчера и думал, что RxJava выполнит все, что стоит (просто), используя отражение. Если это не так, то ваше объяснение имеет смысл. Забавно, хотя это немного помогло. [Я не могу проверить прямо сейчас, но я сделаю это позже и дам вам обратную связь.] –

+0

есть причина, почему вы переопределяете поиск переменных? Поиск search = search.find («что-то»); -> IDE говорит мне, что «(поиск), возможно, не был определен». Если я пойду search = search.find («что-то»); код компилируется отлично. –

1

Я знаю, что это несколько месяцев назад - но вместо того, чтобы create ИНГ совершенно новый Наблюдаемые (который является относительно подверженной ошибкам), вы можете использовать оператор map для запуска поиска:

String search_input = "something"; // this is where you can specify other search terms 
Observable.just(search_input) 
     .map(s -> search.find(s)) // search.find calls the REST endpoint 
     .subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(// your subscriber goes here 

Если не использовать лямбды, что map функция должна выглядеть следующим образом:

.map(new Func1<String, Search>() { 
     @Override   
     public Search call(String s) { 
      return search.find(s) 
     } 
}) 
Смежные вопросы