Reputation: 2092
I am trying to display Toast in my initial_background class extended with AsyncTask<URL, Integer, Long>
. I am receiving this error in 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();
}
}
}
This is the exception:
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
The above code is showing the whole story. Actually, I want to show toast in doInBackground method
Upvotes: 19
Views: 42122
Reputation: 1570
You can't display Toast in non-UI thread (i.e Do in Background).You may try the flag concept.
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..!!!
Upvotes: 2
Reputation: 661
use 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();
}
}
in 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);
}
Upvotes: 0
Reputation: 3209
we can do this by passing an interface to the AsyncTask class and make a callback in onPostExecute method.
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);`
Upvotes: 0
Reputation: 133560
You cannot update UI on background thread. doInBackground()
is invoked on the background thread. You should update UI on the UI thread.
runOnUiThread(new Runnable(){
@Override
public void run(){
//update ui here
// display toast here
}
});
onPreExecute()
, onPostExecute(Result)
, are invoked on the UI thread. So you can display toast here.
onProgressUpdate(Progress...)
, invoked on the UI thread after a call to publishProgress(Progress...)
can be used to animate a progress bar or show logs in a text field.
The result of doInBackground()
computation is a parameter to onPostExecute(Result)
so return the result in doinBackground()
and show your toast in onPostExecute(Result)
You can also use a handler as suggested by @Stine Pike
For clarity, check the link below under the topic: The 4 steps.
http://developer.android.com/reference/android/os/AsyncTask.html
Upvotes: 30
Reputation: 8058
This is another way which is not mentioned here as follows:
Step 1: Define Handler as global
Handler handler;
Step 2: Initialise handler in doInBackground() method as follows:
@Override
protected Void doInBackground(Void... params) {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//your code
}
}
};
}
Step 3: And now you can call that handler by anywhere in code by calling
if(handler != null){
handler.sendEmptyMessage(1);
}
What more you can do is you can send data through handler as follows:
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putInt("KEY", value);
message.setData(bundle);
handler.sendMessage(message);
And handle data in you handler as below
handler = new Handler(){
@Override
public void handleMessage(Message message) {
Bundle bundle = message.getData();
Integer value = bundle.getInt("KEY");
}
};
Upvotes: 4
Reputation: 349
Create a handler object and execute all your Toast messages using that.
@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();
}
});
}
Upvotes: 22
Reputation: 5203
You are trying to display toast in non-ui thread that's why this error apear.
If you want to display toast in doInBackground method then you have to write your Toast logic inside UI thread
have a look in below answer link https://stackoverflow.com/a/11797945/582571
But it is not advisable to have a UI manipulation under non-ui thread
Upvotes: 0
Reputation: 54692
show your Toast in onPostExecute or onPreExecute. doInBackGround runs on a separate thread but the other two methods run on the UI thread.
But if it is must to show toast in doInBackGround then you can use Handler.post or runonUiThread to perform toast showing.
Upvotes: 2