Activity is sometimes closed on ProgressDialog dismiss - android

I have an Activity with a tabbed UI in which I load 3 fragments through a ViewPagerAdapter.
1 fragment (called C) is a simple PreferenceFragment, 1 (B) is only a TextView the last one (A) extends Fragment and I use it to show a ListView containing all the installed packages on the devices.
When the user open the app, an AsyncTask in Fragment A loads the packages and it prepares the adapter to pass to the ListView. Moreover, I use a ProgressDialog in the AsyncTask to inform the users that the list is almost ready.
I leave you with some code:
Inner AsyncTask in fragment C:
private class AppListTask extends AsyncTask<Void, Integer, List<Map<String, Object>>> {
Context context;
public AppListTask(Activity context) {
this.context = context;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(context);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(true);
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialogInterface) {
AppListTask.this.cancel(true);
}
});
}
#Override
protected List<Map<String, Object>> doInBackground(Void... voids) {
// get list of apps
progressDialog.setMax(list.size());
int nApps = 1;
for(ResolveInfo info : list) {
//work on info
nApps++;
publishProgress(nApps);
}
//return
}
#Override
protected void onProgressUpdate(Integer... progress) {
progressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(List<Map<String, Object>> items) {
if (progressDialog != null && progressDialog.isShowing()) {
if (!((Activity) context).isFinishing() && !((Activity) context).isDestroyed()) {
progressDialog.dismiss();
progressDialog = null;
}
}
//set adapter on list view
}
}
and I execute it from onActivityReady in Fragment C
private ProgressDialog progressDialog;
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (listAdapter == null || listAdapter.isEmpty()) {
new AppListTask(getActivity()).execute();
}
}
#Override
public void onPause() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
super.onPause();
}
...
The problem is that on Note4 it works perfectly while on galaxy S5 happens something strange.
If I open the app the first time, as soon as the ProgressDialog is dismissed (in onPostExecute), the app is automatically closed without exceptions. At the second or third launch instead it works good.
If I do not use the ProgressDialog at all, it works good on first launch.
I also tried to use the ProgressDialog as setCancelable(false) but nothing changes.

Related

ListFragment with AsyncTask not showing ProgressDialog

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.

Android ProgressDialog takes time to appear on screen

I have attached on click listener to a text view, inside on click listener a function say f1 is called and inside f1 another function say f2 is called.
Inside f2 I have created a android ProgressDialog object using current activity context, and called show function on progressDialog object. ProgressDialog takes time to appear on screen around 5-6 sec.
I have analyzed my code, but not able to understand why it takes this much time ?
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ShowSyncDialog(); - f1
}
});
public void ShowSyncDialog()
{
fnSyncOfflineData(); - f2
}
public void fnSyncOfflineData()
{
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.show();
//other code
}
You should call your functions in an AsyncTask. Also ProgressDialog must be shown at the beginning of this works. Use something like this:
public class YourTask extends AsyncTask<String, Void, String> {
private Context mContext;
private ProgressDialog progressDialog;
public YourTask(Context context) {
super();
mContext = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Your Message");
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.show();
}
#Override
protected String doInBackground(String... values) {
// If you want to use 'values' string in here
String values = values[0];
String yourResult = yourFunction();
return yourResult;
}
#Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
// Your task has done
...
}
}
Then call this task with:
new YourTask(YourActivity.this).execute();
You can change return type of task doInBackground method. This is just an example, you can search about AsyncTask.
Good luck.

ProgressDialog during startActivity()

I have this code in my activity (LoadTask is an inner class):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
ProgressDialog loading = new ProgressDiaolg(this);
...
}
public class LoadTask extends AsyncTask<Context, Void, Integer> {
ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
#Override
protected void onPreExecute() {
loading.show();
}
#Override
protected Integer doInBackground(Context... params) {
EventLoader el = new EventLoader(params[0]);
list = el.getMylist();
return el.getError();
}
protected void onPostExecute(Integer result) {
if (result == EventLoader.NO_HTTP_CONN) {
getErrorDialog(R.string.errore_caricamento, true).show();
} else if (result == EventLoader.ERR_JSON) {
getErrorDialog(R.string.errore_json, true).show();
} else if (result == EventLoader.ERR_NULL) {
getErrorDialog(R.string.errore_evento_null, true).show();
} else {
mainList=list;
Intent intent = new Intent(MainActivity.this, EventActivity.class);
intent.putExtra(Const.Tags.FULL_LIST, mainList);
loading.dismiss();
startActivity(intent);
}
}
}
the dialog works fine during the loading of the list, but here's my problem:
dismissing the dialog before startActivity(intent) will result in 2-3 seconds of no progress indicator while the new activity is created (there's a listview to be populated with a custom adapter) and before it is actually resumed, which is not very user friendly.
dismissing the dialog after startActivity(intent) will result in a rough disposal of the dialog (first goes the dimmed background, then it freezes... and so on). actually it's like not calling loading.dismiss() at all and letting it be destroyed with the activity.
Is there a smooth way for the ProgressDialog to be persistent through both the loading of the data and the creation of the new activity and eventually be dismissed when the new activity UI is ready to be shown?
If you want a smoother transition I would recommend you use fragments instead. Or you can make it slightly smoother by not populating the list view until onStart and making sure it's done on the background thread.

Showing activity indicator in android

I am new to android.I need to show an activity indicator while synchronizing.On clicking a button,i am redirecting to a new activity.In this new activity i am synchronizing.I need to show an activity indicator on button click till it is synchronized.
Synchronizing is effectively a network task And you have to do this on Background ( Async Task) So you can call an AsyncTask in your new Activity
private class SyncOperation extends AsyncTask<String, Void, String> {
ProgressDialog progressDialog;
#Override
protected String doInBackground(String... params) {
// Synchronize code here
return null;
}
#Override
protected void onPostExecute(String result) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
#Override
protected void onPreExecute() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Synchronizing, please wait...");
progressDialog.show();
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
}
}
}
Now in OnCreate() of new Activity
SyncOperation syncTask=new SyncOperation();
syncTask.execute();
It will show a loader like

How to set adapter of spinner by using Async Task Class

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);
}
}

Categories

Resources