Ясность на IntentService
У меня есть этот сервис, который расширяет IntentService.
public class RefreshService extends IntentService {
static final String TAG = "RefreshService";
public RefreshService() {
super(TAG);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreated");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroyed");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void onHandleIntent(Intent intent) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final String username = prefs.getString("username", "").trim();
final String password = prefs.getString("password", "").trim();
Log.d(TAG, "onDestroyeds");
if (TextUtils.isEmpty(username) || (TextUtils.isEmpty(password))){
Toast.makeText(this, "Please update your username and password", Toast.LENGTH_LONG ).show();
return;
}
// here code for fetching data and inserting into db.
}
}
Когда настройки отсутствуют, вместо показа всплывающего сообщения я получаю следующую ошибку.
07-12 18:28:33.125 2961-2961/com.example.krishna.yamba I/menu_item_selected﹕ [0,Refresh]
07-12 18:28:33.143 2961-2961/com.example.krishna.yamba D/RefreshService﹕ onCreated
07-12 18:28:33.147 2961-3637/com.example.krishna.yamba D/RefreshService﹕ onDestroyeds
07-12 18:28:33.147 2961-3637/com.example.krishna.yamba D/RefreshService﹕ onDestroyeds
07-12 18:28:33.181 2961-2961/com.example.krishna.yamba D/RefreshService﹕ onDestroyed
07-12 18:28:33.197 2961-3637/com.example.krishna.yamba W/MessageQueue﹕ Handler (android.view.ViewRootImpl$ViewRootHandler) {38f6505f} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.view.ViewRootImpl$ViewRootHandler) {38f6505f} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:325)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.post(Handler.java:326)
at android.view.ViewRootImpl.loadSystemProperties(ViewRootImpl.java:5413)
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:378)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:253)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.widget.Toast$TN.handleShow(Toast.java:414)
at android.widget.Toast$TN$1.run(Toast.java:322)
at android.os.Handler.handleCallback(Handler.java:738)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Я предполагаю, что следующее верно
- Код в методе onHandleIntent выполняется в другом потоке.
- Поэтому здесь хорошо выполнять интенсивные задачи. (в этом случае я просто загружаю и обновляю базу данных)
Когда настройки верны, все работает нормально. Тогда добавление всплывающего сообщения по сравнению со сборкой и обновлением не должно быть проблемой, верно?
Как поставить тостовое сообщение при пустых настройках?
2 ответа
IntentService
выполняет его onHandleIntent в отдельном потоке. С другой стороны, Toast
работает в основном потоке пользовательского интерфейса. Для того, чтобы показать Toast
в IntentService
, вам нужно сделать что-то вроде этого:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(RefreshService.this, "Toast msg here", Toast.LENGTH_LONG).show();
}
});
Код в методе onHandleIntent выполняется в другом потоке.
Правильный.
Поэтому здесь хорошо выполнять интенсивные задачи. (в этом случае я просто загружаю и обновляю базу данных)
Правильный.
Тогда добавление всплывающего сообщения по сравнению со сборкой и обновлением не должно быть проблемой, верно?
Нет, потому что вы не можете поднять Toast
из фоновой темы. Это, по сути, то, что ошибка говорит вам.
Как поставить тостовое сообщение при пустых настройках?
Правильный ответ - не использовать Toast
, Это второе худшее решение для сообщения пользователю о состоянии ошибки (самое худшее - просто не пытаться сообщить пользователю вообще). Нет никакой гарантии, что пользователь будет смотреть на экран в тот момент, когда Toast
читается, и поэтому пользователь может пропустить сообщение. Используйте гренки или что-то в этом роде.
В любом случае, вам нужно договориться, чтобы основной поток приложения как-то обновлял пользовательский интерфейс... если ваш пользовательский интерфейс находится на переднем плане. Современные решения для этого обычно включают в себя какую-то шину событий. В настоящее время существует три основных реализации шины событий:
LocalBroadcastManager
( пример приложения)- EventBus greenrobot ( пример приложения)
- Площадь Отто ( пример приложения)
Образцы приложений, на которые я ссылаюсь, демонстрируют пользовательский интерфейсNotification
шаблон, где мы обновляем пользовательский интерфейс, если мы оказались на переднем плане, или мы поднимаем Notification
сообщить пользователю о событии, если у нас нет нашего интерфейса на переднем плане.