In my code I load a spinner adapter by using Async Task
In My case The ProgressDialog is Not dismissing
This is My code.
I want to show the item after adapter load and the progressDialog is to dismiss
Please Help me, Thanks
private class LoadMoreVehicals extends AsyncTask<Object, Integer, Object> {
#Override
protected void onPreExecute() {
progressBar = ProgressDialog.show(RegistrationScreen.this, "",
"Loading...");
progressBar.setIndeterminate(true);
progressBar.setIndeterminateDrawable(getResources().getDrawable(
R.anim.progressbar_handler));
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
String countryUrl = ConstantURL.COUNTRY_URL;
getCounty(countryUrl);
countrySpinner
.setAdapter(new MyCustomSpinnerAdapter(
RegistrationScreen.this,
R.layout.spinner_dropdown,
countyList));
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.getProgress();
}
#Override
protected void onPostExecute(Object result) {
progressBar.dismiss();
Log.e("Im in onPostExecute", "");
super.onPostExecute(result);
}
}
While programming in Android you should remember one thing that any task which draws something on the screen should be executed on the main thread. When you set the adapter then android calls the getView() method of the adapter and draws views on the screen. So you should set the adapter in the postExecute() method instead in doInBackground() method.
Here is a small sample to clear my point:
class MyTask extends AsyncTask<Void, Void, Void> {
ProgressDialog pd = new ProgressDialog(MainActivity.this);
#Override
protected void onPreExecute ( )
{
//starting the progress dialogue
pd.show();
}
#Override
protected Void doInBackground (Void... params)
{
//fetch data here
...
...
return null;
}
#Override
protected void onPostExecute (Void result)
{
//set adapter here
...
...
//dismissing the progress dialogue
pd.dismiss();
}
}
In my experience i have so many problems with async runs and UI so now always separate the stuff trying to place the "responsibilities" in each place. So i do something like this:
Create my Async class with the process i want to do and nothing that transform the UI in it
Create a function in UI thread that modify the UI when async task finish, something like OnAsyncTaskComplete(Object response)
Keep communicated the threads
public class MyActivity extends Activity {
private static MyAsyncClass backgroundTask;
private static ProgressDialog pleaseWaitDialog;
//......activity stuff.......
#Override
public void onPause()
{
super.onPause();
//Get rid of progress dialog in the event of a screen rotation or other state change. Prevents a crash.
if (pleaseWaitDialog != null)
pleaseWaitDialog.dismiss();
}
//Function to avoid lose the async thread if the app interrupts (phone rotation, incoming call, etc) RECOMENDED TO HANDLE THIS!!
//Sets the current state after app resume
#Override
public void onResume()
{
super.onResume();
//If there is a background task set it to the new activity
if ((backgroundTask != null) && (backgroundTask.getStatus() == Status.RUNNING))
{
if (pleaseWaitDialog != null)
pleaseWaitDialog.show();
backgroundTask.setActivity(this);
}
}
}
//Logic business after the web service complete here
//Do the thing that modify the UI in a function like this
private void onTaskCompleted(Object _response)
{
//For example _response can be a new adapter
MyList.setAdapter((BaseAdapter)_response);
//or can be a list to create the new adapter
MyList.setAdapter(new MyAdapter(this, (ArrayList<String>)_response));
//or can be anything you want, just try to make here the things that you need to change the UI
}
/**
* Class that handle the async task
*/
public class MyAsyncClass extends AsyncTask<Void, Void, Object>
{
//Maintain attached activity for states change propose
private MyActivity activity;
//Keep the response of the async task
private Object _response;
//Flag that keep async task completed status
private boolean completed;
//Constructor
private MyAsyncClass(MyActivity activity) {
this.activity = activity;
}
//Pre execution actions
#Override
protected void onPreExecute() {
//Start the splash screen dialog
if (pleaseWaitDialog == null)
pleaseWaitDialog= ProgressDialog.show(activity.this,
"PLEASE WAIT",
"Getting results...",
false);
}
//Execution of the async task
protected Object doInBackground(Object...params)
{
//return the thing you want or do want you want
return new ArrayList();
}
//Post execution actions
#Override
protected void onPostExecute(Object response)
{
//Set task completed and notify the activity
completed = true;
_response = response;
notifyActivityTaskCompleted();
//Close the splash screen
if (pleaseWaitDialog != null)
{
pleaseWaitDialog.dismiss();
pleaseWaitDialog = null;
}
}
//Notify activity of async task completion
private void notifyActivityTaskCompleted()
{
if ( null != activity ) {
activity.onTaskCompleted(_response);
}
}
//for maintain attached the async task to the activity in phone states changes
//Sets the current activity to the async task
public void setActivity(MyActivity activity)
{
this.activity = activity;
if ( completed ) {
notifyActivityTaskCompleted();
}
}
}
}
Hope its help you
First of all you cannot set the adapter in the doInBackground
follow this design:
private class LoadMoreVehicals extends AsyncTask<Object, Integer, Object>
{
private ArrayList<Country> countries;
#Override
protected void onPreExecute() {
progressBar = ProgressDialog.show(RegistrationScreen.this, "","Loading...");
progressBar.setIndeterminate(true);
progressBar.setIndeterminateDrawable(getResources().getDrawable(R.anim.progressbar_handler));
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
String countryUrl = ConstantURL.COUNTRY_URL;
countries = getCounty(countryUrl);
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.getProgress();
}
#Override
protected void onPostExecute(Object result) {
countrySpinner.setAdapter(new MyCustomSpinnerAdapter(RegistrationScreen.this,R.layout.spinner_dropdown,countries));
progressBar.dismiss();
Log.e("Im in onPostExecute", "");
super.onPostExecute(result);
}
}
Related
I have a progress dialog, I want it to show and dismiss when my method has finished executing. now, I have this:
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Downloading...");
progressDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try{
DownloadMethod(s);
progressDialog.dismiss();
}catch (Exception e){
Toast.makeText(prefs.this, "We can't reach the data...Try again", Toast.LENGTH_SHORT).show();
}
}
}).start();
My method DownloadMethod is executed but never shows the dialog.
Actually, It must be throwing an exception with progressDialog.dismiss(); call because you cannot update UI from a worker thread, instead use AsyncTask
e.g pass parameter to constructor
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
TypeOf_S s;
public DownloadFilesTask(TypeOf_S s){
this.s = s;
}
#Override
protected Void doInBackground(Void... obj) {
DownloadMethod(s);
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
and call it like new DownloadFilesTask(s).execute();
or with generic parameter
private class DownloadFilesTask extends AsyncTask<TypeOf_S, Void, Void> {
#Override
protected Void doInBackground(TypeOf_S... obj) {
DownloadMethod(obj[0]);
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
and call it like new DownloadFilesTask().execute(s);
progressDialog.dismiss();is throwing an exception so move your code inside runOnUiThread() method like this:
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.dismiss();
}
});
as suggested by Pavneet you can use async task as follows where AsyncTask<String, void, String> corresponds to the input type progress value and last is result value you are interested so give data types accordingly.
private class DownloadFilesTask extends AsyncTask<String, void, String> {
protected String doInBackground(String... urls) {
//here do the actual downloading instead of calling the DownloadMethod(s)
}
protected void onPreExecute() {
//here show the dialog
progressDialog.show();
}
protected void onPostExecute(String result) {
//here hide the dialog
progressDialog.dismiss();
}
}
and where you are calling the download function you just call this
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Downloading...");
new DownloadFilesTask().execute(s);
//here s is assumed to be string type you can give anything
I have a ListFragment which has an AsyncTask in it to write data to a remote store. I need to have a ProgressDialog show status while the data is being sent since this may take a considerable time depending on the number of files being stored remotely. I have done this successfully from an Activity, but I am having issues showing progress within the ListFragments AsyncTask.
This is complicated by the fact that I need to show updates within the doInBackground method of the task, since that is where the major of the work is being done. That said, the ProgressDialog is not showing up at all even in the non-UI bound onPreExecute() method. Looking at other posts for ProgressDialogs I am using passing getActivity() to the ProgressDialog. Also this mechanism is working with several other Activity classes I am using else where, just not here. I am probably just missing something obvious so any help is appreciated.
Here is a code example - forgive me if it does not compile or has a mistake - I had to remove boatloads of code to boil it down to the problem at hand:
public class MyFragment extends ListFragment {
private ProgressDialog mProgress;
private void hideProgress() {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
}
private void showProgress(String message) {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
mProgress = ProgressDialog.show(getActivity(), null, message, true, false);
}
protected void updateProgressMessage(String message) {
if (mProgress != null && mProgress.isShowing()) {
mProgress.setMessage(message);
}
}
public syncForms() {
new syncPendingFormsResultTask().execute();
}
private class syncTask extends AsyncTask<Object, String, Boolean> {
#Override
protected void onCancelled() {
hideProgress();
}
#Override
protected void onPreExecute() {
showProgress("Submitting Form...");
}
#Override
protected Boolean doInBackground(Object... params) {
onProgressUpdate("Uploading Form");
}
#Override
protected void onProgressUpdate(String... values) {
String message = values[0];
updateProgressMessage(message);
}
#Override
protected void onPostExecute(Boolean result) {
showProgress("Upload Complete...");
hideProgress();
}
}
}
}
The syncForms() is the method called to initiate the task.
I don't want to implement an interface directly in asynctask class like this:
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
swipeRefreshLayout.setRefreshing(true);
}
#Override
protected Void doInBackground(Void... params) {
retrofitCallBackUtil.getLastTenMessageCallBack(AppConfig.USER_ID, userId, offsetNumber, service, new RetrofitResponseCallBack() {
#Override
public void onSuccess(ArrayList<Message> messages) {
messageAdapter.insertToTheFirst(messages);
}
#Override
public void onFailure() {
}
});
offsetNumber += 5;
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
messageAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
}.execute();
I just to implement it by main class and put this into this parameter like this:
retrofitCallBackUtil.getLastTenMessageCallBack(AppConfig.USER_ID, userId, offsetNumber, service, this);
but I cannot do it inside asynctask method. So anyone can give me some solution?
I assume you have these code in MainActivity (or something similar).
Let's implement the interface you need to pass into getLastTenMessageCallBack in this Activity by implements RetrofitResponseCallBack {...}
Now, in your Asyntask doInBackground method, call
retrofitCallBackUtil.getLastTenMessageCallBack(AppConfig.USER_ID, userId, offsetNumber, service, MainActivity.this)
Voila, you don't have to create anonymous class inside your Asyntask anymore.
Note that, you have to move and place the fields/params properly, just the matter of being right place, no big deal :D
Create a class separately for AsyncTask like this. This AsyncTask will process the data and publish the data who implements the interface defined inside the AsyncTask . In this case interface defined is DataDownloadListener
public class GetFoldersAsync extends AsyncTask<Integer,Boolean,Boolean> {
Context context;
ProgressDialog dialog;
ArrayList mFolderDataLevel;
public GetFoldersAsync(Context context){
this.context=context;
}
public static interface DataDownloadListener {
public void dataDownloadedSuccessfully(ArrayList data);
public void dataDownloadFailed();
}
DataDownloadListener dataDownloadListener;
public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
this.dataDownloadListener = dataDownloadListener;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(context, "Please wait", "Processing.........");
}
#Override
protected Boolean doInBackground(Integer... params) {
Log.v(Constants.BLL_LOG, "ExplorerDBOperation doInBackground ");
mFolderDataLevel=new ArrayList();
// Process to populate mFolderDataLevel
return true;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if(dialog!=null && dialog.isShowing())
{dialog.dismiss();}
Log.v(Constants.BLL_LOG, "ExplorerDBOperation onPostExecute ");
if(mFolderDataLevel!=null && mFolderDataLevel.size()>0){
dataDownloadListener.dataDownloadedSuccessfully(mFolderDataLevel);
}else{
dataDownloadListener.dataDownloadFailed();
}
}
}
Now in the caller Activity, call this method when the AsyncTask needs to process and get back data to same activity.
public class HomeActivity extends AppCompatActivity {
//Other necessary methods goes here .....
//call this method for processing AsyncTask and to get back data
public void getFolderData(int parentID, int callerID){
Log.v(Constants.BLL_LOG,"parentID="+parentID+" , callerID="+callerID);
mCallerID=callerID;
GetFoldersAsync getFolders = new GetFoldersAsync(this);
getFolders.setDataDownloadListener(new GetFoldersAsync.DataDownloadListener()
{
#SuppressWarnings("unchecked")
#Override
public void dataDownloadedSuccessfully(ArrayList data) {
Log.v(Constants.BLL_LOG,"getFolderData dataProcessSuccessfully");
// Success data with populated ArrayList to process further
}
#Override
public void dataDownloadFailed() {
//Failure
Log.v(Constants.BLL_LOG,"getFolderData dataProcessFailed()");
}
});
getFolders.execute(callerID);
}
}
Hi I'm making Login page that access MySQL database. But my Activity always runs the code that check fail/success before it finishes the AsyncTask.
I tried using asynctask.get() method, but it just freeze my UI and doesn't work.
I tried this answer that said I should call the result-checker method inside onPostExecute().
But since I need to change the TextView to show success/failed, it results in NullPointerException because I instantiate the TextView inside onCreate().
I can't move the TextView instantiation into constructor because it will return NullPointerException unable to instantiate activity ComponentInfo.
Login.java
public class Login extends Activity{
//declare global Views here
protected void onCreate(Bundle bundle){
//Setup views
}
protected void onClick(View v){
//Setup necessary variables
AsyncClass async = new AsyncClass(this);
async.execute(username, password);
}
public void checkSuccess(boolean success){
if(success)
textView1.setText("Success");
else
textView1.setText("Failed");
}
}
AsyncClass.java
public class AsyncClass extends AsyncTask<String, String, JSONObject>{
protected JSONObject doInBackground(String... params){
//access database
}
protected void onPostExecute(JSONObject json){
//read the json result
Login login = new Login();
login.checkSuccess(true);
}
}
Any solution? Thanks
How about making AsyncTask as your inner class?
So your code should look something like below.
public class Login extends Activity {
//declare global Views here
protected void onCreate(Bundle bundle) {
//Setup views
}
protected void onClick(View v) {
new AsyncClass().execute(username, password);
}
public void checkSuccess(boolean success) {
if (success) textView1.setText("Success");
else textView1.setText("Failed");
}
class AsyncClass extends AsyncTask < String, String, JSONObject > {
protected JSONObject doInBackground(String...params) {
//access database
}
protected void onPostExecute(JSONObject json) {
checkSuccess(true / false);
}
}
}
try this
protected void onPostExecute(JSONObject json){
//read the json result
Login login = (Login)context; // object that you pass to task constructor
login.checkSuccess(true);
}
Also you can add progress dialog to your task to indicate some job execution
public class BaseTask<T> extends AsyncTask<Object, Void, T> {
public Context context;
public ProgressDialog dialog;
public BaseTask(Context context) {
this.context = context;
this.dialog = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
this.dialog.setMessage(context.getResources().getString(R.string.loading));
this.dialog.show();
}
#Override
protected T doInBackground(Object... objects) {
//....
return something;
}
#Override
protected void onPostExecute(T result) {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
// do something
}
}
You cannot edit the UI from the async task thread. In order to make updates to the UI thread, use the onProgressUpdate() method. This method is part of your AsyncTask class, is actually executed in the main UI Thread (I hope you use the async task as a nested class btw, since it is declared public I guess your not. You should change that). The onProgressUpdate() Method is called by the OS itself if you call publishProgress(...) inside your Async task.
A small sample:
protected JSONObject doInBackground(String... params){
publishProgress("test");
}
/**
* This method is part of the Async Task
*/
protected void onProgressUpdate(String... progress) {
login.checkSuccess(true);
}
I would use it this way, just override your onPostExecute where you need it or create a own interface
//create a object f your asyncclass and
//override the onPostExecute where you need it
mInfo = new ASYNCCLASS({
#Override
public void onPostExecute(Object result){
//doSomething something with your views!
}
}).execute();
Waiting is not the answer, because you do not know how long your Asynctask will take to end.
Code above is not tested, just pseudoce, but it should show what i mean.
Do not have my IDE round here, so if anybody would correct the brackets if neccessary would be great!
Greetz
I have a huge database (40MB) on an SDCard. I need fetch data, with LIKE in query, which is very slow.
DB request takes about 5 seconds. Therefore, I need to do it asynchronously and with ProgressDialog.
I tried it with AsyncTask, but problem is with ProgressDialog. It was implemented this way:
private class GetDataFromLangDB extends AsyncTask<String, String, String> {
private final ProgressDialog dialog = new ProgressDialog(TranslAndActivity.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
urDBCursor.close();
curDBCursor = null;
scaAdapter = null;
this.dialog.setMessage("Loading data...");
this.dialog.show();
}
#Override
protected String doInBackground(String... whatSearch) {
String result = "";
if (myDatabaseAdapter != null) {
curDBCursor = myDatabaseAdapter.fetchAll(whatSearch[0]);
}
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
prepareListView();
}
}
The problem is that ProgressDialog is not shown during the DB request.
After finished database query, it flash on screen for a short time. When user tries
to tap on screen during database request, UI is freezed, and after DB request
message about 'not responding' is shown.
I tried it with a thread this way:
public void startProgress(View view, final String aWhatSearch) {
final ProgressDialog dialog = new ProgressDialog(MyActivity.this);
if (curDBCursor != null){
curDBCursor.close();
curDBCursor = null;
}
dialog.setMessage("Loading data...");
dialog.show();
Runnable runnable = new Runnable() {
public void run() {
curDBCursor = myDatabaseAdapter.fetchAll(aWhatSearch);
// dirty trick
try {
Thread.sleep(250); // it must be here to show progress
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
public void run() {
if (dialog.isShowing()) {
dialog.dismiss();
}
prepareListView();
}
});
}
};
new Thread(runnable).start();
}
The result was the same, but when I used the trick with Thread.sleep(250);
ProgressDialog was shown during the database request. But it is not spinning,
it looks freezed during the DB request.
DB stuff is called this way (after tap on search button):
btnSearchAll.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// AsyncTask
new GetDataFromLangDB().execute(edtTextToSearch.getText().toString());
// or Thread
//startProgress(null, edtTextToSearch.getText().toString());
}
});
I found a lot of problems like this in SO, but nothing was useful for me.
Could it be that DB is on SD Card?
I put the definition of the dialog into the AsyncTask Class and it works fine for me.
Take a look at this exampel (You have to change NAMEOFCLASS in the name of your CLASS:
private class doInBackground extends AsyncTask<Integer, Integer, Void> {
final ProgressDialog dialog = new ProgressDialog(NAMEOFCLASS.this) {
#Override
protected void onPreExecute() {
dialog.setCancelable(false);
dialog.setTitle(getString(R.string.daten_wait_titel));
dialog.setIcon(R.drawable.icon);
dialog.setMessage(getString(R.string.dse_dialog_speichern));
dialog.show();
}
#Override
protected void onCancelled() {
dialog.cancel();
}
....
#Override
protected void onProgressUpdate(Integer... values) {
// DO YOUR UPDATE HERE
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
Maybe this SO answer could help you. It looks like similar problem. Try to use AsyncQueryHandler for querying your database
declare you Dialog box on Class (Activity) level like this
private ProgressDialog dialog = null;
show the progress dialog and call the AsyncTask class when you want to start you Busy work..like onButton click or any
dialog = ProgressDialog.show(this,"Sending Email to your account please! wait...", true);
SendingEmailTask task = new SendingEmailTask();
String s = "";
task.execute(s);
create your inner class like
private class SendingEmailTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
//do your work here..
// like fetching the Data from DB or any
return null;
}
#Override
protected void onPostExecute(String str) {
//hide progress dialog here
dialog.dismiss();
}
}
let me know if this help!!