#android #sleep #toast
#Android #сон #toast
Вопрос:
У меня возникла любопытная проблема, когда я пытаюсь show();
мои тосты. Ниже вы увидите два тоста, разделенных try/catch and Thread.sleep();
В этом случае второй тост, toast2
, будет отображаться, но toast1
не будет.
Если я удалю try/catch
оба тоста, они будут отображаться без проблем.
Я видел в другом месте, что toast.show();
делает запрос в потоке пользовательского интерфейса, который может противоречить другим операциям. Мне интересно, является ли это той же проблемой, что и у меня здесь с Thread.sleep();
Как я могу решить эту проблему?
Спасибо
TestService.java
///Debug - Show a Toast
// Toast does NOT show up
Toast toast1 = Toast.makeText(context,"Service Started", Toast.LENGTH_SHORT);
toast1.show();
//Try to sleep for roughly 2 seconds
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Debug - Shows a Toast
Toast toast2 = Toast.makeText(context,"Sleep completed", Toast.LENGTH_SHORT);
toast2.show();
Комментарии:
1. Выполняется ли это в потоке пользовательского интерфейса?
2. что вы пытаетесь сделать?? вы хотите, чтобы поток пользовательского интерфейса ждал 2 секунды? или вы хотите, чтобы ваш поток управления ждал 2 секунды, что вам нужно??
3. Сначала изучите основы пользовательского интерфейса
Ответ №1:
В реальной жизни у вас, вероятно, будет какая-то логика вместо простого «сна», верно? Согласно вашему примеру, правильным способом запуска службы для Android было бы выполнение ее в рабочем потоке. Это гарантирует, что вы не получите ANR.
ваш мог бы выглядеть примерно так:
new AsyncTask<Void, Void, Void>() {
@Override
protected void onPostExecute(Void result) {
Toast toast2 = Toast.makeText(context, "Sleep completed",
Toast.LENGTH_SHORT);
toast2.show();
}
@Override
protected void onPreExecute() {
Toast toast1 = Toast.makeText(context, "Service Started",
Toast.LENGTH_SHORT);
toast1.show();
}
@Override
protected Void doInBackground(Void... params) {
// Try to sleep for roughly 2 seconds
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}.execute();
Ответ №2:
Поскольку вы приостанавливаете поток пользовательского интерфейса сразу после первого тоста, у него нет возможности отображаться. И к тому времени, как режим ожидания закончится, время для первого тоста прошло.
Это звучит как наиболее правдоподобное объяснение, но я могу ошибаться. Нужно действительно глубоко покопаться в коде Android, чтобы узнать наверняка.
Комментарии:
1. Я считаю, что вы правы. Я сократил время почти до нуля и
toast1
появился.
Ответ №3:
Я предполагаю, что вам нужно создать тост, который длится более 2 секунд (почему вы должны использовать Thread.Sleep(2000)
перед отправкой другого тоста?).
Итак, я только что нашел эту ссылку, которая предоставляет очень хороший пример.
Надеюсь, это поможет
Ответ №4:
Я столкнулся с той же проблемой, я попытаюсь решить с помощью AsyncTask, как предложено, но мой вариант использования следующий:
1) Я хочу отобразить всплывающее сообщение (начать широковещательное сообщение) 2) Если условие выполнено правильно, я передаю message1 клиентам. 3) Я сплю 2 секунды, чтобы разрешить трансляцию для завершения. 4) Я постоянно отправляю message2 клиентам. 5) Если это будет сделано, я бы поджарил другое сообщение (широковещательные сообщения завершены)
Я придумал следующий пример обходного пути (хотя последовательность всплывающих сообщений все еще отображалась в обратном порядке):
package com.toasttester;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import android.os.AsyncTask;
public class MainActivity extends ActionBarActivity {
Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PreSleepToast pst = new PreSleepToast();
pst.execute();
Toast t = Toast.makeText(getApplicationContext(), "Message1", Toast.LENGTH_SHORT);
t.show();
try {
Thread.sleep(2000);//to allow broadcasting to complete
} catch (Exception e) {
e.printStackTrace();
}
callToast1();
}
private Runnable r = new Runnable() {
@Override
public void run() {
Toast t = Toast.makeText(getApplicationContext(), "Message3", Toast.LENGTH_SHORT);
t.show();
}
};
public class PreSleepToast extends AsyncTask<Void, byte[], Void> {
/**
* The sender socket on which we send connections.
*/
public PreSleepToast() {
}
/**
* Polling loop for outgoing connections.
*/
@Override
protected Void doInBackground(Void... params) {
handler.post(r);
return null;
};
};
public void callToast1(){
Toast t = Toast.makeText(getApplicationContext(), "Message2", Toast.LENGTH_SHORT);
t.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Комментарии:
1. хм, мое решение работает только на marshmallow, не сработало на nougat….in кажется, что nougat заменяет «Message2» …. тогда как в marshmallow он отображается после него.
2. теперь я озадачен поведением nougat ….. даже если я использую ArrayList для постановки в очередь моих Message1 и Message2 по одному до сна и по одному после ….. и затем я запускаю asynctask, который публикует runnable, который в конечном итоге перебирает сообщения в ArrayList, чтобы поджарить их …… но все равно отображается только последнее сообщение……