1. Java / Говнокод #16112

    +68

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    public String getCurrentUrl() {
        if (webview == null) {
          throw new SelendroidException("No open web view.");
        }
        long end = System.currentTimeMillis() + UI_TIMEOUT;
        final String[] url = new String[1];
        done = false;
        Runnable r = new Runnable() {
          public void run() {
            url[0] = webview.getUrl();
            synchronized (this) {
              this.notify();
            }
          }
        };
        runSynchronously(r, UI_TIMEOUT);
        return url[0];
      }

    final String[] url = new String[1];
    url[0] = webview.getUrl();
    return url[0];

    Вы чо? Серьёзно?

    Запостил: kovel, 04 Июня 2014

    Комментарии (16) RSS

    • Замыкания как в JS без обновления языка. Эх.
      Ответить
    • Более чем. Просто анонимный класс не может обращаться к локальным переменным, только к константам. Вот переменную и обернули в массив. Просто чтобы вернуть значение. А вот в синхронизации и правда говно.
      Ответить
      • Не ну понятно, просто тут как бы Selendroid, ООП, Java... На хера эти процедурные workaround'ы?
        Ответить
        • Потому что переданный из метода объект (ну или созданный в методе поток - один чёрт) может существовать намного дольше, чем выполняется сам метод. Поэтому доступ к локальным переменным из анонимного класса - зло. Их на момент обращения вообще может не быть, ладно, константы можно тупо скопировать и забыть, как страшный сон, а с переменными не прокатит. Ну а что можно изменять содержимое константного объекта, уж извините, это не бага, а фича. Типичное ООП как раз, с мутабельными структурами данных.
          Ответить
          • Самоцитата: "Но там объект сессии есть. Можно было ещё что-нибудь под response завести :)" Ну или как верно подметил товарищ ниже: AtomicReference
            Ответить
    • Я не спец в андроидах, но возможно, этот метод шедулит запрос в UI тред, т.к. больше ниоткуда трогать webview нельзя, оттого и забавная синхронизация.
      Ну и массив можно заменить каким-нибудь AtomicReference, если нет человеческого Executor-а.
      Ответить
      • Верно. Но там объект сессии есть. Можно было ещё что-нибудь под response завести :)
        Ответить
      • > если нет человеческого Executor-а
        На ведре для таких задачек есть прекрасный класс AsyncTask.

        http://developer.android.com/reference/android/os/AsyncTask.html
        Ответить
        • > прекрасный
          Только я так и не смог прикрутить к нему приоритеты.
          Если поискать в интернете, можно найти "решения", в которых предлагается чуть ли не с нуля всё переписать.
          Ответить
          • > приоритеты
            Да там вроде бы ради криворуких индусов даже "тредпул" ограничили одним тредом ;( Т.е. два асинктаска параллельно все равно работать не будут.
            Ответить
            • никто не ограничивал) Executor'ы абсолютно полноценные.
              Ответить
              • Да, именно у AsyncTask'ов кастрированный пул:

                When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
                Ответить
                • > Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution

                  It's just so typical for Google.

                  Много потоков могут привести к ошибкам - нужно их запретить.
                  Исключения могут привести к ошибкам - нужно их запретить.
                  Код с бустом бывает сложным - нужно запретить использовать буст.
                  Ответить
                • public abstract class AsyncTask<Params, Progress, Result> {
                  private static final String LOG_TAG = "AsyncTask";

                  private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors ();
                  private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
                  private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
                  private static final int KEEP_ALIVE = 1;

                  Ну да, и в самом деле как-то странно.
                  Ответить
          • > прикрутить к нему приоритеты
            А если просто набивать task'и в priority queue и по завершению таска дергать из нее следующий и запускать?

            P.S. Хотя это и есть то самое "переписать руками" :)
            Ответить

    Добавить комментарий