Как правильно использовать Workerthread?
Я пишу приложения для Android уже несколько месяцев, и я нахожусь в точке, где я создаю действительно необходимое приложение.
Поскольку я хочу, чтобы это работало хорошо и быстро, я создал 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 не появляется в консоли.
После некоторого гуглинга и переполнения стека все просто объясняют, в чем разница между обработчиками, Asynctask и потоками. И примеры многозадачности всегда показывают только что-то вроде new Thread(new Runnable{run(task1)}).start
раза 3 с разными задачами.
И так стал мой большой вопрос:
Как правильно, в течение более длительного времени (~ жизненный цикл MainActivity), с разными задачами использовать фоновый поток?
Изменить: чтобы уточнить, я также хотел бы прямого решения моей специальной проблемы.
Изменить 2: после прочтения комментария никис (спасибо), простой ответ, кажется, "использовать HandlerThread вместо потока". Постараюсь, как только я вернусь домой.
Попробуем HandlerThread сейчас. Похоже, мой OpHandler, инициализированный в run()
, разрушается или что-то после run()
закончил, не уверен, что здесь (это, кстати, еще одна загадка, на которую я надеялся получить ответ здесь). Я получаю NullpointerException, как только я пытаюсь использовать его после run()
закончил
1 ответ
Сделайте ваш рабочий поток владельцем очереди задач. в 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;
}
}