2015-03-27 4 views
0

Я уже несколько месяцев пишу приложения для Android, и я нахожусь в точке, где я создаю необходимое приложение.Как правильно использовать Workerthread?

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

Он основан на приложении приложения Android Studio Drawer.

В Main.onCreate Я получил свой operator=new Operator(), который расширяет Thread.

Теперь, при загрузке нового фрагмента, он иногда называет MainActivity.operator.someMethod() (я сделал оператор статическим, так что я могу использовать его в любом месте), и через некоторое время я понял, что только задачи на самом деле работает в фоновом режиме, являются те, в операторах run() метод и Asynctask мой логин Фрагмент работает. Все остальное пользовательский интерфейс ждет завершения и, следовательно, будет выполняться потоком пользовательского интерфейса.

Так что я подумал: никаких проблем! Мой operator получает handler, который построен в run(), и я изменить эти задачи:

public void run() { 
    Looper.prepare(); //Android crashed and said I had to call this 
    OpHandler = new Handler(); 
    LoadLoginData(); 
    [...Load up some Arrays with hardcoded stuff and compute for later use...] 
} 

public void LoadLoginData() { 
    OpHandler.post(LoadLoginDataRunnable); 
} 
private Runnable LoadLoginDataRunnable = new Runnable() { 
    @Override 
    public void run() { 
     if(sharedPreferences==null) 
      sharedPreferences= PreferenceManager.getDefaultSharedPreferences(context); 
     sessionID=sharedPreferences.getString("sessionID", null); 
     if(sessionID!=null) { 
      postenID = sharedPreferences.getString("postenID", PID_STANDARD); 
      postenName = sharedPreferences.getString("postenName", PID_STANDARD); 
      context.QuickToast(sessionID, postenName, postenID); 
     } 
    } 
}; 

контекст моего MainActivity, я дал оператору ссылку, чтобы я мог отправить Тосты для отладки.

Но теперь Runnables, кажется, не запускаются и не завершаются, любые файлы Log.e или Log.d не поступают в консоль.

После некоторых googeling и stackoverflowing каждый всегда объясняет, какая разница между обработчиками, Asynctask и Threads. И многозадачные примеры всегда показывают только что-то вроде new Thread(new Runnable{run(task1)}).start раз 3 с разными задачами.

И так стал моим большим вопросом:

Как правильно, в течение длительного времени (~ жизненный цикл MainActivity), с различными задачами, использовать фоновый поток?

Редактировать: уточнить, мне также хотелось бы прямое решение моей особой проблемы.

Редактировать 2: после прочтения комментария nikis (спасибо), простой ответ кажется «использовать HandlerThread вместо потока». Попробуй, как только я вернусь домой.

Попытка HandlerThread сейчас. Кажется, мой OpHandler, инициализированный в run(), уничтожается или что-то после того, как run() закончил, не уверен, что здесь (это еще одна загадка, на которую я надеялся получить ответ здесь). Я получаю исключение NullpointerException, как только я пытаюсь использовать его после завершения run().

+0

Рекомендую прочитать [этот учебник] (http://tutorials.jenkov.com/java-concurrency/index.html) и пересмотреть код. «AsyncTask» может быть не таким, каким вы хотите. Предпочитаемый способ Android для очереди задач был бы «IntentService». – 323go

+0

не думаю, что это реклама, но http: //blog.nikitaog.me/2014/10/11/android-looper-handler-handlerthread-i/ – nikis

+0

Вам нужно выполнить Looper # loop последним в вашем методе # запуска оператора. Другой вариант - использовать [HandlerThread] (https://developer.android.com/reference/android/os/HandlerThread.html). Не забудьте выйти из потока, когда закончите. – davidpetter

ответ

-2

Сделайте свой рабочий поток собственной задачей задач. В методе run() просто введите задачу из очереди и выполните ее. Если очередь пуста, дождитесь ее заполнения.

class Operator extends Thread 
{ 
    private Deque<Runnable> tasks; 
    private boolean hasToStop=false; 

    void run() 
    { 
      boolean stop=false; 
      while(!stop) 
      { 
       sychronized(this) 
       { 
        stop=hasToStop; 
       } 
       Runnable task=null; 
       synchronized(tasks) 
       { 
        if(!tasks.isEmpty()) 
         task=tasks.poll(); 
       } 
       if(task!=null) 
        task.run(); 
      } 
    } 

    void addTask(Runnable task) 
    { 
      synchronized(tasks) 
      { 
       tasks.add(task); 
      } 
    } 

    public synchronized void stop() 
    { 
      hasToStop=true; 
    } 
} 
+0

Хотелось бы узнать причину понижения, чтобы я мог обновить ответ (или, по крайней мере, узнать что-то, чего я не знаю). – lodo

+0

Не мой нисходящий сигнал, может быть, он не подходит к моему особому примеру или к вопросу, почему обработчик не работает. @topic: так что мой поток должен работать все время? Я надеялся, что смогу позволить моему потоку работать «по требованию», чтобы он не нуждался в мощности процессора, а не потому, что он, как уже упоминалось, иногда получает задание, когда я переключаю фрагмент или логин/выход из системы или какой-то другой материал. – Squirrelkiller

+0

@Marlon Regenhardt Если вы ожидаете, что поток будет оставаться без дела большую часть времени, просто дайте ему немного поспать на каждой итерации, чтобы проверки очереди были менее частыми. Это должно сделать издержки потока ничтожными. – lodo

Смежные вопросы