Ваш сбой происходит, потому что вы выполняете операции отображения, такие как onDraw()
из фонового потока. Все операции с вашими поверхностями и представлениями должны выполняться из основного потока пользовательского интерфейса.
Это означает, что вы должны предоставить какой-то механизм, чтобы фоновые потоки могли сообщить основному потоку, когда и что рисовать. Один из способов сделать это - использовать класс Android Handler
, который позволяет вам общаться между потоками. Вы можете использовать Handler
, например, для отправки объекта Runnable
в основной поток пользовательского интерфейса, который затем выполняет его вместе с другими асинхронными событиями.
Другой способ - использовать класс Android ASyncTask
, который оборачивает фоновую задачу и предоставляет методы onProgressUpdate()
и onPostExecute()
, которые можно переопределить. Оба метода всегда вызываются в основном потоке пользовательского интерфейса.
РЕДАКТИРОВАТЬ: Есть еще два способа заставить обновления пользовательского интерфейса в основном потоке:
1) В Activity есть вызов API runOnUiThread()
, который можно вызвать из фонового потока. Runnable, который вы передаете ему, будет вызываться в основном потоке:
BillingActivity.this.runOnUiThread(new Runnable() {
public void run() {
BillingActivity.this.finish();
}
});
2) Представление имеет метод post()
, который аналогичным образом ставит в очередь Runnable для запуска в потоке пользовательского интерфейса в ближайшем будущем:
mView.post( new Runnable() {
public void run() {
mView.doSomethingOrOther();
}
});
Независимо от того, как вы это делаете, все манипуляции с представлениями должны выполняться в главном потоке.