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が提案するハンドラーを使用することもできます
明確にするために、トピックの下のリンクを確認してください:The 4 steps。
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;
ステップ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でトーストを表示します。 doInBackGroundは別のスレッドで実行されますが、他の2つのメソッドはUIスレッドで実行されます。
ただし、doInBackGroundでトーストを表示する必要がある場合は、 Handler.post または runonUiThread を使用してトースト表示を実行できます。
非UIスレッドでトーストを表示することはできません(つまり、バックグラウンドで実行します)。フラグの概念を試すことができます。
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();
}
}
Happy Coding .. !!!ここにコードを入力してください
これを行うには、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);`
非UIスレッドでトーストを表示しようとしているため、このエラーが表示されます。
DoInBackgroundメソッドでトーストを表示する場合は、UIスレッド内にトーストロジックを記述する必要があります。
以下の回答リンクをご覧ください https://stackoverflow.com/a/11797945/582571
しかし、非UIスレッドの下でUI操作を行うことはお勧めできません