I have written the following code within the main class for an async worker
private class Renderer extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "works... ", Toast.LENGTH_LONG).show();
return null;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Long result) {
}
}
But calling this crashes the app
public void render(View v)
{
new Renderer().execute();
}
Can some one tell me what's going wrong?
You can't do a Toast in doInBackground, you will get Can't create handler inside thread that has not called Looper.prepare().
If it's just for testing at this stage (which your code seems to imply), consider instead just writing some log output for now.
Alternatively put your Toast either onPreExecute or onPostExecute
More info: How to raise a toast in AsyncTask, I am prompted to used the Looper
You are showing toast in doInbackground which is not possible. Do it in onPostExecute
protected void onPostExecute(Long result) {
Toast.makeText(getApplicationContext(), "works... ", Toast.LENGTH_LONG).show();
}
doInbackground is invoked on the background thread. You should update ui on the ui thread. You can alos display toast in onProgressUpdate.
More info at
http://developer.android.com/reference/android/os/AsyncTask.html
Check the topic under the section The 4 steps.
You can't access UI thread from background thread.
An AsyncTask is a helper around Threads and Handlers. It helps you to perform a background task and update the UI regularly.
Thus, the methods of AsyncTask run on different Threads:
doInBackground runs in a background Thread
onProgressUpdate and onPostExecute run on the UI Thread.
Now, you can only modify the UI in the UI Thread (=main Thread). This is why your code leads to a crash. Simply moving your Toast into onPostExecute will solve your problem.
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "works... ", Toast.LENGTH_LONG).show();
}
});`
Try to do all ui work on main thread.
Related
While reading the documentation, I found that The AsyncTask class must be loaded on the UI thread. But I am surprised that AsyncTask can also be executed from the worker thread.
So the question is:
If AsyncTask can also execute from the background thread, Why in the documentation they are saying just opposite to it.
How could it possible to have context on onPostExecute.?
new Thread(new Runnable() {
#Override
public void run() {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(getBaseContext(), "in AsyncTask...", Toast.LENGTH_SHORT).show();
}
}.execute();
}
}).start();
The AsyncTask Android class lets us sort of bind background tasks to the UI thread. So using this class, you can perform background operations and then publish the results to the UI thread that updates the UI components.
you can understand AsyncTask execution briefly : http://codetheory.in/android-asynctask/
There is two Threads Main Thread and Worker Thread. Asyntasck works on worker thread.Mostly Asynctask used for background Task.It works on worker thread and publish the result on Main thread.
If Main thread block for 5 sec or more than that Application not responding (ANR) dialogs comes so to avoid this scenario for background task Asynctask used
when I read document about asyntask, they say that: "should not" update UI thread in doInbackground because doInbackground work on different thread.
that means : this action will dangerous because UI Thread isn't thread-safe. I understand it. but when I try for test what happen when I update UI Thread in this function. I receive error: (but error doesn't not look like because aysnchonize, but because we CANNOT do it)
(TextView)((Activity)context).findViewById(R.id.text)).setText("StackOverFlow");
//context: reference of context object of UI Thread
Please explain for me. Does we shouldn't or mustn't .
thanks :)
what I have understand so far with android is...,
we can't update UI thread from background thread.
May be it is the case they have stopped us to update UI from background thread.
The reason for that is very clear... # OS level there will be so many thread will be running.
And also
different thread from different application, And in that case It will be chaos on the screen, if we can update UI from bg-thread
Inside the doInBackgroundyou will not get the UI access. If You Want to take UI access publishProgress from doInBackgroundyou will go to the onProgressUpdate from there do what you wan to show on UI.
Below is the Code you will check for your reference :
class DownloadAsyncTask extends AsyncTask
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(Login.this, "", "Please Wait ...");
}
#Override
protected Void doInBackground(String... arg0) {
int status1 = validationuser(username);
Log.i("MyLog", "Inside the doInBackground is came"+status1);
if(status1 == 1)
{
publishProgress(status1+ "Valid User Code","1",""+status1);
}
else
{
publishProgress(status1+ " Invalid Valid User Code","0",""+status1);
}
return null;
}
#Override
protected void onProgressUpdate(String...values){
super.onProgressUpdate(values);
int index = Integer.parseInt(values[2]);
if(index == 1)
{
USERIDLOGIN = edittextuserName.getText().toString();
Intent intent=new Intent(Login.this, CollectionModuleandDownload.class);
/*Toast.makeText(Login.this, "Valid User Password", Toast.LENGTH_SHORT).show();*/
startActivity(intent);
progressDialog.dismiss();
}
else
{
Toast.makeText(Login.this, "Invalid Username & Password", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
/*if(progressDialog != null)
{
progressDialog.dismiss();
}*/
}
}
so you have to update ui only on the OnPostExecute & OnPreExecute.
here's a good example of asynctask. give it a try
you call it by
new SaveProfile().execute();
then this...
private class SaveProfile extends AsyncTask<String, Void, Boolean>{
#Override
protected Boolean doInBackground(String... params) {
//---------- so your stuff here.... non ui related
Log.v("response from saving",response);
if(response.equals("1")){
return true;
}else{
return false;
}
}
protected void onPostExecute(Boolean result) {
if(result) {
//------ UPDATE UI HERE
Toast.makeText(ProfileCompanyActivity.this, "profile saved", 2500).show();
}else{
Toast.makeText(ProfileCompanyActivity.this, "an error occured", 2500).show();
}
}
}
When you create a Aysnc task the doInBackground method runs in the separate thread from UI thread. So you cannot update the UI from this method.
The OnPostExecute and onPreExecute method execute in the same thread as UI thread. For further reading go here
If only one thread is allowed to touch the user interface, Android can guarantee that nothing vital is changed while it’s measuring views and rendering them to the screen
It is because .. User Interface can be updated only on mainthread..all the user interface objects in your screen are maintained by this mainthread....now if you try to change the user interface from some other thread(do in background)in this case.. it causes error because..for example.. if you try to change the seekbar(some widget) value from other than main thread.. and the user is trying to put a different value...then it is ambiguous for android.. as to which thread it should listen... hope it clarifies your doubt..
So, it is like we should'nt try to.. and because of its security.. we cannot try also.. as it gives error.. =]
doInBackground is used to perform heavy calculations or any background work you want to perform in your activity.
when the operation in your doinbackground method finished the on postexecute methods upadates your ui..
in short doinbackground is not used to update ui.
I think the answer is that we mustn't
It just doesn't seem logical to me..
its like trying to change the radio station at another car driving beside you..
the architecture just doesn't work that way.. you can decide on a radio station before you set off to your road trip or when you stop driving and theoretically you can yell to him and ask him to change the station but you cannot do it yourself.
As doInBackground() runs on separate thread and onPostExecute runs on UIMain thread and as per constraint provided by Android you cannot update UIMain Thread from other thread.
Because of above mentioned reason you are getting mentioned message while you are running your application.
While I'm updating my database I want to display a progress dialog. My problem is that the ProgressDialog is getting late to appear,after 4-5 seconds, then appears and disappears very fast, it stays on screen few milliseconds almost you can't see it, then new data are shown in the list immediately. This makes me think that the ProgressDialog is waiting for database to be updated(it doesn't take much, about 4,5 seconds) and then it shows on the screen but is dismissing very fast. I would like the ProgressDialog appear immediately I press the 'Update' button and stay on the screen about 4-5 seconds.
class MyAsyncTask extends AsyncTask<Void, Void, Void>{
ProgressDialog myprogsdial;
#Override
protected void onPreExecute(){
myprogsdial = ProgressDialog.show(MyActivity.this, null, "Upgrade", true);
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
RefreshDataBase();
}
});
return null;
}
#Override
protected void onPostExecute(Void result){
myprogsdial.dismiss();
}
}
When I call it, new MyAsyncTask().execute();
Ok I think that this
runOnUiThread(new Runnable() {
is causing this behavior.
doInBackground() executes your code in a new thread to the main UI thread. You are then putting the code to execute in this thread back into the main one causing the progress dialog to be delayed at the end and then in postExecute() it gets closed immediately.
A good asyntask tutorial can be found here.
You must not use runOnUiThread. What you're basically did is:
Started new non-ui thread
From this new non-ui thread you posted a long running task to UI thread.
Exited from non-ui thread.
Your ui thread now executes long-running operation (RefreshDataBase) and blocks the UI.
You should call RefreshDataBase() directly. And if this method touches UI, you have to refactor it.
I have solved it, using this answer of Vladimir Ivanov.
I have separated the functionality by the appearance.
I have kept the functionality(downloading new data) in doInBackground() and in onPostExecute() I updated the list: get the new adapter,called setListAdaper() and notifyDataSetChanged.
Of course, I quit using runOnUiThread(). Thanks to all for hints.
I use AsyncTask to change text of TextView like this:
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
response += url;
}
return response;
}
#Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
Everything will fine if I call it in OnClick event:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = (TextView) findViewById(R.id.txt);
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new LongOperation().execute(new String[]{"Hello"});
}
});
}
But the problem when I called it in my thread, the program forced close
this.closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Thread t= new Thread(){
#Override
public void run(){
try{
//Do something
//Then call AsyncTask
new LongOperation().execute(new String[]{"Hello"});
}catch(Exception e){}
}
};
t.start();
}
});
Where am I wrong? I dont' understand how difference call AsyncTask in thread or not.
I recommend you consult the AsyncTask documentation and Processes and Threads for a better understanding of how it works. Essentially, you should create your AsyncTask subclass on the main thread.
When you call AsyncTask.execute(), your provided, AsyncTask.onPreExecute is called on the main thread, so you can do UI setup.
Next AsyncTask.doInBackground method is called, and runs in its own thread.
Finally, when your AsyncTask.doInBackground method completes, a call is made to AsyncTask.onPostExecute on the main thread, and you can do any UI cleanup.
If you need to update the UI from within your AsyncTask.doInBackground method, call AsyncTask.publishProgress, which will invoke onProgressUpdate in the main thread.
When you call it from the UI thread, the associated Context is the running Activity. When you call it from a regular thread, there is no valid Context associated with that thread. AsyncTask executes in its own thread, you shouldn't be creating its own thread. If that is actual code, then you have missunderstood the point of AsyncTask. Search for tutorials on how to use it.
Adding to what the others have said: I think you can use AsyncTask to launch off a task in another thread, even if you start the AsyncTask from a different thread than the UI already.
But in that case, the only way you'll only be able to modify the UI indirectly, for example: pass the handler of the current Activity somehow to this AsyncTask instance, and send messages to it (handler messages get processed on the UI thread). Or use broadcast intents that the Activity catches and updates the UI accordingly, etc. These solutions seem to be overkills though.
I have tasks completed by AsyncTask in background. At some point I need to issue a Toast that something is completed.
I've tried and I failed because
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
How can I do that?
onPostExecute - executes on UI thread
or
publishProgress(); in your doinbackground and
protected void onProgressUpdate(Integer... progress) {
}
http://developer.android.com/reference/android/os/AsyncTask.html
you can Toast inside doInBackground
add this code where you want to Toast appear
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(<your class name>.this, "Cool Ha?", Toast.LENGTH_SHORT).show();
}
});
You can also use runOnUiThread method to manipulate your UI from background threads.
If you want to use Toast
You should use this method : onProgressUpdate()
protected Integer doInBackground(Void...Params) {
int check_point = 1;
publishProgress(check_point);
return check_point;
}
protected void onProgressUpdate(Integer integers) {
if(integers == 1) {
Toast.makeText(classname.this, "Text", 0).show();
}
If you want to display the Toast from the background thread you'll have to call runOnUiThread from doInBackground. I don't believe there's another way.
Edit: I take that back. I think you can implement onProgressUpdate, which runs on the UI thread, to show the Toast and make calls to publishProgress from doInBackground.
If you want to display the Toast in doInBackground, you can use it in the OnPostExecute method of AsyncTask.
protected void onPostExecute(String file_url) {
Toast.makeText(getApplicationContext(),"Your Message", Toast.LENGTH_LONG).show();
pDialog.dismiss();//dismiss the progress dialouge
}