Showing Progresscircle in Asynctask - java

I want to show an progresscircle while a chat is loading. So I put some progressbar in, visibility set to invisible. Now I set in onPreExecute() the visibility to visible and in onPostExecute() to invisible.
The circle is shown, but just when the chat already did load AND it doesnt disappear. Can someone tell me my mistake? :o
#Override
public void onPreExecute() {
MainActivity.pbReadChat.setVisibility(ProgressBar.VISIBLE);
}
#Override
public Map<String, ArrayList<String>> doInBackground(String... strings) {
//...
return result;
}
public void onPostExecute(Map<String, ArrayList<String>> result) {
super.onPostExecute(result);
MainActivity.pbReadChat.setVisibility(ProgressBar.INVISIBLE);
}
Edit: Now it disappears but it gets just shown after chat already did load in doInBackground()
That are the important things of my Async class I think, hope someone can help me

Your onPostExecute() is not being called because doInBackground() does not return. It can happen because of one of the reasons below:
Infinite loop.
Infinite wait for an input.
Unchecked exception.
cancel() being called on AsyncTask. In this case, onCancelled() is called instead of onPostExecute()

Related

Progress Dialog not showing up in AsyncTask

I have an Android application with an AsyncTask which is responsible for downloading a file from the internet. This AsyncTask is executed when clicking on an item in a Listview. So I have a custom adapter and in the OnItemClickListener of the Listview, I start the download and execute the AsyncTask.
Now, my adapter contains the following code to start the AsyncTask named FileDownloader:
#Override
public void onClick(View view) {
try {
FileDownloader fd = new FileDownloader(activity);
// some irrelevant code here
String filepath = fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString()).get();
}
catch(Exception e) { e.printStackTrace(); }
}
Activity is a private field that is passed to the adapter in the constructor of the adapter:
public GameHistoryAdapter(Activity a, int selectedIndex) {
this.activity = a;
}
The FileDownloader class contains an OnPreExecute method where I want to show the progress dialog on the activity:
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(activity);
dialog.setMessage("Downloading...");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show();
}
But whatever I try, the dialog does not appear. When I create an alert dialog in the OnPostExecute method of the AsyncTask, the dialog will show.
#Override
protected void onPostExecute(String res)
{
super.onPostExecute(res);
dialog.hide();
new AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.save_pdf_title_text))
.setMessage(activity.getString(R.string.save_pdf_text) + PDFFileName)
.setPositiveButton(activity.getString(R.string.close_text), null)
.setIcon(android.R.drawable.ic_dialog_info)
.show();
}
Does anyone know why the dialog is not appearing on my activity?
Does anyone know why the dialog is not appearing on my activity?
Yes, the following line of code...
String filepath = fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString()).get();
Don't EVER use the get() method of AsyncTask. It will block the main / UI thread and makes the whole point of an AsyncTask redundant. In other words get() turns it into a synchronous process instead of an asynchronous one.
The fact you can show a dialog in onPostExecute(...) is simply because it will be called after the blocking call to get() has returned. This means the main / UI thread will no longer be frozen (blocked) and UI updates can be made once again.
Remove get() from your call to execute(...) and instead just use...
fd.execute("http://myurl.com/img.png", PDFFileName, GameHistoryAdapter.this.gameInfo.toString());
...then in your onPostExecute(...) method set you filepath variable to what it should be.
I don't know who added the get() method to AsyncTask but if I ever find them I'll have some serious words to say. It has little or no use and causes a lot of people a lot of confusion.

Updating an adapter from a background thread

A few of my users (maybe 50) are getting crashes with the following error:
java.lang.IllegalStateException: The content of the adapter has
changed but ListView did not receive a notification. Make sure the
content of your adapter is not modified from a background thread, but
only from the UI thread.
If I understand correctly, it's caused by calling adapter.clear(); and adapter.addAll(list); in an AsyncTask's doInBackground() method, and I need to move it in the onPostExecute().
The problem is I can't reproduce that error, so I can't be sure if it's fixed. Some similar questions on StackOverflow seem to indicate that simply moving the updating the adapter to the onPostExecute() method doesn't solve the problem.
Does anyone know how I can make this error happen every time on my device to make sure the fix worked? I don't get it why it would work in most cases but only sometimes cause a crash.
Simple answer: you are forgetting to call adapter.notifyDatasetChanged().
Notifies the attached observers that the underlying data has been
changed and any View reflecting the data set should refresh itself.
Get your data in background and update your adapter in onPostExecute() because you should never change a content of the adapter from background thread. Both onPreExecute() and onPostExecute() are executed on the UI thread.
To reproduce the issue, try sleeping after making changes to your adapter in doInBackground().
For example:
#Override
protected Void doInBackground(Void... params) {
adapter.clear();
try
{
Thread.sleep(5000);
}
catch(InterruptedException e){}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.notifyDatasetChanged();
}
You shouldn't call any UI things in doInBackground(..) method.
just call them in onPostExecute(..) as well as onPreExecute(..)
for example
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.clear();
}
According to the AsyncTask documentation, in the "The 4 steps" paragraph.
onPostExecute(Result), invoked on the UI thread after the background
computation finishes. The result of the background computation is
passed to this step as a parameter.
Try this..
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDatasetChanged();
}
});

How to return Arraylist from AsyncTask to UI thread

I need help with returning Arraylist of ArrayList OUT from AsyncTask or setting a webview within AsyncTask. I tried to set a webview from within AsyncTask and got an error that told me that I had to do this within a UI thread.
Then I tried to return a arralist of arraylist from AsyncTask to my UI thread which did not work that either.
This is the error I recieved:
java.lang.Throwable: Warning: A WebView method was called on thread 'AsyncTask #3'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.
Oncreate()
---->Call my AsyncTask and then start it with task.execute
The AsyncTask itself will execute onPostExecute() when it's ready and then it will return nothing because it is void.
Code block 1
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab2);
...
...
queriesAsync task = new queriesAsync();
task.execute(new String[] { DatabasePath });
...
Code block 2
private class queriesAsync extends AsyncTask<String, Void, ArrayList> {
#Override
protected ArrayList doInBackground(String... pathToDB) {
///Do something
return ArrayList;
}
#Override
protected void onPostExecute (ArrayList result){
// return?
}
}
I would bet that you are not using AsyncTask's onPostExecute(), which runs on the UI Thread after doInBackground() finishes. When doInBackground() finishes it returns the desired result to onPostExecute() which runs on the UI Thread. Here you can manipulate UI components as you please.

Android ListView freezes while loading data

i am using a custom listview with images in my app
and loading all data from a json url.
i have created a onscrollistener()
which automatically add data below the current data when user scrolls to the bottom of the listview.
But when my data is loading whole listview freezes for 2-3 sec.
I dont know whats wrong??
here is my code for AsyncTask
private class BackgroundLoadMore extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
// Showing progress dialog before sending http request
}
protected Void doInBackground(Void... unused) {
runOnUiThread(new Runnable() {
public void run() {
LoadData();
list.setOnScrollListener(new EndlessScrollListener());
}
});
return (null);
}
protected void onPostExecute(Void unused) {
// On completing background task
// closing progress dialog etc,.
}
You must be fetching the json data from url in main UI thread. This blocks the UI from being updated by system, and hence the freeze. Use AsyncTask to do such network tasks in background.
LoadData() should be called in a background thread, which is asynctask's doInBackground(). Your call runOnUIThread puts it back on the UI thread, and that you dont want. remove the runOnUIThread call from asynctask.
protected Void doInBackground(Void... unused) {
LoadData();
return (null);
}
protected void onPostExecute(Void unused) {
// On completing background task
// closing progress dialog etc,.
list.setOnScrollListener(new EndlessScrollListener());
}
Move LoadData(); out of
runOnUiThread(new Runnable() {
public void run() {}
};
doInBackground is performing in the worker thread, but in it you use runOnUiThread wich start a UI therad operations.
You have to load all the data from net in background thread and then in postExecute update your listview
You are probably loading your data inside the UI thread.
Since operations such as loading JSON data from the internet are slow (from 0.5-10 seconds is typical) then if you do that inside the main thread of your app, the user interface will stop responding for this time. You should use a Thread or AsyncTask to load the JSON data asynchronously and so keep the UI thread free to respond to user input (such as scrolling the list).
My suggestion is that you use an AsyncTask to load the data.
Here are some links:
AsyncTask documentation
AsyncTask example
See the accepted answer for this question to see an implementation
Edit
Put list.setOnScrollListener(new EndlessScrollListener()); and list.notifyDatasetChanged(); inside onPostExcecute();

How to make a callback after the view is completely rendered?

How to make a callback after the view is completely rendered ?
I am trying to call a method which takes a screen-shot of parent view.
If I write that code in onCreate() method, the app crashes due to null pointer (as no view is rendered).
for now the temporary solution I have implemented is to make a delay of 1 second before calling that method.
But, I am looking for a much more robust solution to this problem.
any suggestions and help appreciated.
thanks :)
Try this logic ... always called after the view has got focus or rendered or looses focus
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
doWhateverAfterScreenViewIsRendered();
}
I have got a better option now :)
this really gives a call-back after the layout is rendered
private class LoadActivity extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mainMethod();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
takeScreenShot(1);
}
#Override
protected String doInBackground(String... params) {
return null;
};
}
I created the above class and then called this method for execution in onCreate()
LoadActivity loadactivity= new LoadActivity();
loadactivity.execute();
You should use the onResume() callback on your Activity, which is
Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.

Categories

Resources