[英]How to display a Toast in Android AsyncTask?
我試圖在我用AsyncTask<URL, Integer, Long>
擴展的 initial_background 類中顯示 Toast。 我在 logcat 中收到此錯誤。
public class InitialBackgroundTask extends AsyncTask<URL, Integer, Long> {
@Override
protected Long doInBackground(URL... params) {
// TODO Auto-generated method stub
show a = new show();
a.loop();
return null;
}
public class show {
void loop()
{
for(int i=0; i<10; i++)
{
Toast.makeText(MainActivity.me, "test", Toast.LENGTH_LONG).show();
}
}
}
這是例外:
05-30 12:08:12.641: E/AndroidRuntime(30840): FATAL EXCEPTION: AsyncTask #1
05-30 12:08:12.641: E/AndroidRuntime(30840): java.lang.RuntimeException: An error occured while executing doInBackground()
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$3.done(AsyncTask.java:278)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.lang.Thread.run(Thread.java:856)
05-30 12:08:12.641: E/AndroidRuntime(30840): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.Handler.<init>(Handler.java:121)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast$TN.<init>(Toast.java:317)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast.<init>(Toast.java:91)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast.makeText(Toast.java:233)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.show.loop(show.java:11)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.java:13)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.java:1)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$2.call(AsyncTask.java:264)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-30 12:08:12.641: E/AndroidRuntime(30840): ... 5 more
上面的代碼展示了整個故事。 實際上,我想在 doInBackground 方法中顯示吐司
您無法在后台線程上更新 UI。 doInBackground()
在后台線程上調用。 您應該在 UI 線程上更新 UI。
runOnUiThread(new Runnable(){
@Override
public void run(){
//update ui here
// display toast here
}
});
onPreExecute()
和onPostExecute(Result)
在 UI 線程上調用。 所以你可以在這里展示吐司。
onProgressUpdate(Progress...)
,在調用publishProgress(Progress...)
后在 UI 線程上調用,可用於動畫進度條或在文本字段中顯示日志。
doInBackground()
計算的結果是onPostExecute(Result)
的參數,因此在doinBackground()
返回結果並在onPostExecute(Result)
顯示您的吐司
您還可以按照@Stine Pike 的建議使用處理程序
為清楚起見,請查看以下主題下的鏈接: 4 個步驟。
http://developer.android.com/reference/android/os/AsyncTask.html
創建一個處理程序對象並使用它執行所有 Toast 消息。
@Override
protected Void doInBackground(Void... params) {
Handler handler = new Handler(context.getMainLooper());
handler.post( new Runnable(){
public void run(){
Toast.makeText(context, "Created a server socket",Toast.LENGTH_LONG).show();
}
});
}
這是另一種這里沒有提到的方式,如下所示:
第 1 步:將Handler定義為全局
Handler handler;
第 2 步:在doInBackground()方法中初始化處理程序,如下所示:
@Override
protected Void doInBackground(Void... params) {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//your code
}
}
};
}
第 3 步:現在您可以通過調用在代碼中的任何位置調用該處理程序
if(handler != null){
handler.sendEmptyMessage(1);
}
您還可以做的是通過處理程序發送數據,如下所示:
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putInt("KEY", value);
message.setData(bundle);
handler.sendMessage(message);
並在您的處理程序中處理數據,如下所示
handler = new Handler(){
@Override
public void handleMessage(Message message) {
Bundle bundle = message.getData();
Integer value = bundle.getInt("KEY");
}
};
在 onPostExecute 或 onPreExecute 中顯示您的 Toast。 doInBackGround 在單獨的線程上運行,但其他兩個方法在 UI 線程上運行。
但是如果必須在 doInBackGround 中顯示 toast 則可以使用Handler.post或runonUiThread來執行 toast 顯示。
您不能在非 UI 線程中顯示 Toast(即在后台執行)。您可以嘗試標志概念。
public class HttpRequest extends AsyncTask<String[], Void, String> {
boolean flag=false;
....
...
....
@Override
protected String doInBackground(String[]... params) {
//set flag as true when you need to trigger the Toast
try{
//Some Network Calls
} catch (HttpHostConnectException e) {
flag=true;
//Triggered Flas when i got Exceptions
}
}
@Override
protected void onPostExecute(String result) {
if(flag){
Toast.makeText(activity, "HttpHostConnectException Occured ", Toast.LENGTH_SHORT).show();
}
}
快樂編碼..!!!在此處輸入代碼
您正試圖在非 ui 線程中顯示吐司,這就是出現此錯誤的原因。
如果要在 doInBackground 方法中顯示 Toast,則必須在 UI 線程中編寫 Toast 邏輯
看看下面的答案鏈接https://stackoverflow.com/a/11797945/582571
但是不建議在非ui線程下進行UI操作
我們可以通過向 AsyncTask 類傳遞一個接口並在onPostExecute方法中進行回調來做到這一點。
public interface IResult {
void onSuccess(String result);
void onError(String error);
}
public static class AsyncTaskClass extends AsyncTask<String, String, Boolean> {
IResult iResult;
AsyncTaskClass(IResult iResult){
this.iResult = iResult;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(String... params) {
boolean result;
try {
//doing BackGround Operation Here
result = true;
} catch (Exception e) {
Log.e(TAG,"Error: " + e.getMessage());
result = false;
}
return result;
}
@Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
Log.w(TAG, "On Post Execute: " + success);
if(success)
iResult.onSuccess("AsyncTask done successfully.");
else
iResult.onSuccess("Sorry! something went wrong.");
}
}
IResult iResult = new IResult() {
@Override
public void onSuccess(String result) {
Toast.makeText(PostActivity.this, result, Toast.LENGTH_LONG).show();
}
@Override
public void onError(String error) {
Toast.makeText(PostActivity.this, error, Toast.LENGTH_LONG).show();
}
};
String param1 = "some value 1";
String param2 = "some value 2";
new AsyncTaskClass(iResult).execute(param1, param2);`
使用 SDK 29
public class LoginControl extends AsyncTask<String, Void, String> {
private final Context context;
public LoginControl (Context context) {
this.context = context;
}
@Override
protected String doInBackground(String... strings) {
//do something
}
@Override
protected void onPostExecute(TokenBean tokenBean) {
Toast.makeText(context, "hello Toast", Toast.LENGTH_SHORT).show();
}
}
在 MainActivity.class 中
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url="something";
Context context = getApplicationContext();
new LoginControl(context).execute(url);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.