class TestAsync extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
v.findViewById(R.id.loadinglayout).setVisibility(View.VISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.INVISIBLE);
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
callAPI();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
v.findViewById(R.id.loadinglayout).setVisibility(View.INVISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.VISIBLE);
}
}
public void callAPI ()
{
RequestInterface requestInterface = new RequestImplementation();
requestInterface.setUrl("https://api.myjson.com/bins/vl9pp");
ConnectionExecutor connectionExecutor = new
ConnectionImplementation();
ResponseInterface temp = null;
try {
temp = connectionExecutor.executeConnection(requestInterface);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
rangeText.setText(temp.getPayload());
}
Call API function will call a method of another class where HttpConnection is done.
If the function is directly called from onViewCreated() in fragment then it works. If I call it from another async task it returns nothing.
I am actually trying to show a progress bar when the callApi function is called.
It is not allowed to start an AsyncTask outside the UI thread. doInBackground is outside the UI thread.
From https://developer.android.com/reference/android/os/AsyncTask.html:
Threading rules
...
The AsyncTask class must be loaded on the UI thread.
call it on onPostExecute method
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
v.findViewById(R.id.loadinglayout).setVisibility(View.INVISIBLE);
v.findViewById(R.id.wholecontentlayout).setVisibility(View.VISIBLE);
callAPI();
}}
From this SO answer
only inside onProgressUpdate() or onPostExecute() since these methods
runs on the UI thread. Therefore, start the second AsyncTask on the UI
thread by choosing one of the two methods listed above.
Simply put, if you're in need of firing up AsyncTask within another AsyncTask, it must be called from either onProgressUpdate() or onPostExecute() since they resides in UI thread.
To show the ProgressBar to illumilate the task is running, you should show your progress bar in onPreExecute() and hide it in onPostExecute(Result).
AsyncTask<Void, Void, Void> yourTask = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
/**
* Show your progress bar:
*/
yourProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
/**
* Do your stuffs in background thread
*/
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
/**
* Hide your progress bar:
*/
yourProgressBar.setVisibility(View.GONE);
}
};
Run the task: yourTask.execute();
onPostExecute(Result) method will get called when the task completed.
Related
I'am trying to implement an AsyncTask in Android that will load all my data from the database. Therefore I used the onPreExecute method to start a ProgressDialog
public class DataLoader extends AsyncTask<Void, Void, Void> {
private LoginActivity activity;
private ProgressDialog nDialog;
public DataLoader (LoginActivity act){
this.activity = act;
nDialog = new ProgressDialog(activity);
}
protected void onPreExecute() {
System.out.print("Start AsyncTask");
nDialog.setMessage("Loading data..");
nDialog.setTitle("Starting the application");
nDialog.setIndeterminate(false);
nDialog.setCancelable(true);
nDialog.show();
}
#Override
protected Void doInBackground(Void ... params) {
System.out.println("Starting doInBackground");
loadDashboardData();
return null;
}
protected void onPostExecute() {
nDialog.dismiss();
Intent i = new Intent();
i.setClass(activity.getApplicationContext(), DashboardActivity.class);
activity.startActivity(i);
}
The I use the doInBackground method to load call a function to load the data. This method is called from an visible activity. The task is called with:
public class LoginActivity extends Activity {
public void onClick(View v) {
DataLoader dl = new DataLoader(this);
dl.execute();
}
}
And the code for the doInBackground is:
protected Void doInBackground(Void ... params) {
System.out.println("Starting doInBackground");
loadDashboardData();
return null;
}
Now the problem is that my doInBackground method will not finish. I tried to implement the loadDashboardData() call in the onPreExecute method. This will not show my dialog box but it will load the data correctly. In this case the UI Thread is not responding and will response after all the data has been loaded.
What can hinder the doInBackground method to execute correctly and load the data properly? The called method works (because I can call it and get the correct data). Also I'am not seeing the println in my run console.
In the frontend I can see the progressbar spinning, but in the backend I can see that no data is loaded.
Your problem is that you are overriding the wrong method name : )
It should be
#Override
protected void onPostExecute(Void result) {
// your code
}
as in your case the variable which doInBackground return is Void.
You can check the documentation about AsyncTask .
I have been writing AsyncTask's for short background operations in android for quite some time and had a very basic question. If I start an AsyncTask from a separate thread and not the main UI thread, would my onPreExecute()andonPostExecute methods be still called in the UI thread or the thread from which I started the AsyncTask. I am curious because I was unable to show a popup inside the onPreExecute() method when I started the it from some other thread.
EDIT 2
I tried writing this simple activity to try:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
#Override
public void run() {
final TestAsyncTask task = new TestAsyncTask();
task.execute();
}
}).start();
}
private class TestAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
}
}
}
This runs fine.
But when I run the application with the following code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
#Override
public void run() {
final TestAsyncTask task = new TestAsyncTask();
task.execute();
}
}).start();
}
private class TestAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "Yo!", Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... voids) {
return null;
}
}
}
It fails with the following error:
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
as one of the lines in the stack trace.
While docs say that these callbacks execute in main thread - it is not true. onPreExecute() runs synchronously from the executeOnExecutor() i.e. in the thread that starts AsyncTask.
onPostExecute() is always runs in main thread. (it is invoked from finish(), and this happens inside Handler that uses looper of main thread).
You should do UI updates and alert or pop up showing in AsyncTask's onPostExecute() method which runs on UI thread. The AsyncTask's doinBackground() method runs on another thread.
Quoting offical Docs:
onPostExecute
Added in API level 3
void onPostExecute (Result result)
Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).
onPreExecute
Added in API level 3
void onPreExecute ()
Runs on the UI thread before doInBackground(Params...).
you can find it here https://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)
Do in background runs on background thread while OnPreExecute and OnPostExecute run on main Ui thread.
I have an activity with a listview. When I call this activity the activity takes about 3-5 seconds to appear and display the listview. It looks as if the button has not been pressed to load the activity, i would like to display a progressdialog while this loads but can't figure it out.
ProgressDialog progress;
progress = ProgressDialog.show(this, "Loading maps!",
"Please wait...", true);
// sort out track array
getTracks();
progress.dismiss();
I did the above on the oncreate() of the activity with the listview but the dialog never shows?
What I would like is to show the progress dialog on Activity A when the button is pressed and then dismiss once Activity B is loaded and displayed?
Thanks
You need to implement AsyncTask or simple JAVA threading. Go with AsyncTask right now.
onPreExecute() - display dialog here
doInBackground() - call getTracks()
onPostExecute() - display tracks in ListView and dismiss dialog
For example:
private static class LoadTracksTask extends AsyncTask<Void, Void, Void> {
ProgressDialog progress;
#Override
protected void onPreExecute() {
progress = new ProgressDialog(yourActivity.this);
progress .setMessage("loading");
progress .show();
}
#Override
protected Void doInBackground(Void... params) {
// do tracks loading process here, don't update UI directly here because there is different mechanism for it
return null;
}
#Override
protected void onPostExecute(Void result) {
// write display tracks logic here
progress.dismiss(); // dismiss dialog
}
}
Once you are done with defining your AsyncTask class, just execute the task inside onCreate() by calling execute() method of your AsyncTask.
For example:
new LoadTracksTask().execute();
You can make progress Dialog like this :
onPreExecute(){
progressdialog = new ProgressDialog(MainActivity.this);
progressdialog.setMessage("Please wait while downloading application from the web.....");
progressdialog.setIndeterminate(false);
progressdialog.setMax(100);
progressdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressdialog.setCancelable(false);
progressdialog.show();
}
doInBackground(String... strings){
// here you code for downloading
}
onProgressUpdate(String... progress)
{
// here set progress update
progressdialog.setProgress(Integer.parseInt(progress[0]));
}
onPostExecute(String result)
{
progressdialog.dismiss();
}
Use something like this:
private static class MapLoader extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
progress.setVisibility(View.VISIBLE);
// make your element GONE
}
#Override
protected Void doInBackground(Void... params) {
// Load map processing
return null;
}
#Override
protected void onPostExecute(List<Document> result) {
progress.setVisibility(View.GONE);
adapter.setNewData(new_data);
adapter.notifyDataSetChanged();
}
}
In your onCreate() use:
listView.setAdapter(adapter);
new MapLoader.execute();
I am opening a progressdialog with AsyncTask in doInBackground method the question is loading from database and after question successfully loaded the progress dialog box will be closed
but my problem is some time I am getting following error
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRoot$W#44757528 is not valid; is your activity running?
by doing some googling I have found that there may be i am holding on to a reference to a Context (either explicitly, or by creating a Dialog or Toast or some other dependent item) that has been destroyed (typically because you are using the onCreateDialog or you passed the Activity to some other process that didn't get destroyed when the Activity was destroyed).
So I have put below code that dismiss progressdialog in-case if activity is destroyed before dialog box is dismissed
protected void onDestroy() {
if (pdForNewQuestion != null)
pdForNewQuestion.dismiss();
super.onDestroy();
}
but I still face the issue. I am not destroying any activity but still the error suddenly comes sometimes and sometimes it works properly
the async code is below
// Start new question in every 60 seconds :)
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
mProgressStatus++;
} catch (Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
txtCountingNum.setText((timer--) + "\nSec.");
if (timer < 0) {
questionLoadWithAsyncTask();
}
}
});
}
}
}).start();
public void questionLoadWithAsyncTask() {
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
pdForNewQuestion = new ProgressDialog(QuizActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... arg0) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result) {
if (pdForNewQuestion != null) {
pdForNewQuestion.dismiss();
}
}
}.execute();
}
Check whether the dialog is showing or not if dialog is showing then only dismiss like this..
#Override
protected void onDestroy() {
if (pdForNewQuestion != null) {
if (pdForNewQuestion.isShowing()) {
pdForNewQuestion.dismiss();
pdForNewQuestion = null;
}
}
super.onDestroy();
}
you are running infinite loop inside new Thread but not breaking the loop and stopping that Thread. It runs infinitely in the background even when activity goes background. try stopping the Thread once work is finished.
First of all why are you starting your AsyncTask inside a Thread? As i understand you are trying to start an AsyncTask every 60 seconds and populate a new question. There is a much better way to do this using only a Handler and AsyncTask.
Create a Handler and post Runnable which runs every seconds and depending on the result start your AsyncTask :
int mSeconds = 0;
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(mSeconds == 60){
new QuestionLoader().execute();
mSeconds = 0;
}
mHandler.postDelayed(this, 1000);
mSeconds++;
}
}, 1000);
and you can create your AsyncTask like this :
private class QuestionLoader extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
super.onPreExecute();
pdForNewQuestion = new ProgressDialog(MainActivity.this);
pdForNewQuestion.setTitle("Please wait...");
pdForNewQuestion.setMessage("Question is loading...");
pdForNewQuestion.setCancelable(false);
pdForNewQuestion.setIndeterminate(true);
pdForNewQuestion.show();
}
#Override
protected Void doInBackground(Void... params) {
wordsCursor = dbHelper.getRandomWords();
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
if(pdForNewQuestion != null && pdForNewQuestion.isShowing()){
pdForNewQuestion.dismiss();
}
}
}
This is usually caused by your app trying to display a dialog using a previously-finished Activity as a context. Then check that the activity is not closed by some other apps or other triggers before showing the dialog
if (!isFinishing()) {
//showdialog here
}
I'm working on downloading a html source from website and displaying it on TextView. It's being downloaded in another thread and I want to display it when it'll be finished. So. i have to pause main thread until it finish. Right now i do it like this:
MyAsyncTask task = new MyAsyncTask(this);
task.execute();
Thread.sleep(6000);
((TextView) findViewById(R.id.textView1)).setText(task.result);
But as you see it's not the best way to do this. I need something like "sleepUntil(boolean is MyTaskCompleated)". Is there something like this in Java. Or is there any better way to do it?
Having the UI thread sleep is no different than performing the actual work in the UI thread itself. Both cases will end up with a UI that is not responsive, and can cause an "Application Not Responding" message.
It seems like your goal is to not allow the user to perform any other actions while this work is being performed. One alternative approach to do this would be to block the UI with a progress dialog, and dismiss() the dialog in the onPostExecute() method of your AsyncTask subclass.
I use callbacks.
MyCallback.java
public interface MyCallback<T> {
public void onComplete(T result);
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
private MyCallback<Boolean> mCallback;
public MyAsyncTask(MyCallback<Boolean> callback) {
mCallback = callback;
}
#Override
protected void onProgressUpdate(Void... progress) {
super.onProgressUpdate(progress);
// ...
}
#Override
protected Boolean doInBackground(Void... params) {
// ...
}
#Override
protected void onPostExecute(Boolean result) {
if (mCallback != null) {
mCallback.onComplete(result); // will call onComplete() on MyActivity once the job is done
}
}
}
In this example, this callback will take nothing as argument and return a Boolean.
Now all you have to do is to let your calling class (MyActivity for example) implements MyCallback:
public class MyActivity extends Activity implements MyCallback<Boolean> {
// ...
xxx {
MyAsyncTask myAsyncTask = new MyAsyncTask(this); // the callback
myAsyncTask.execute();
}
// ...
#Override
protected void onComplete(Boolean result) {
// ...
}
}
This is what I do and it works very well.
I would suggest creating a class that extends Asynctask and then perform your work in the overload methods. This will give you the ability to run your task on another thread and have it execute code after the result is completed.
http://developer.android.com/reference/android/os/AsyncTask.html
Look at the example under Usage. The overloads for onPreExecute and onPostExecute run on the UI thread so you can do something like show a progress dialog onPreExecute and dismiss it onPostExecute.
doSomeWork();
new MyAsyncTask().execute(url);
The AsyncTask:
private class MyAsyncTask extends AsyncTask<URL, Void, Void> {
protected void doInBackground(URL... urls) {
downloadHtml(urls[0]);
}
protected void onPostExecute(Long result) {
continueWorkHere();
}
}