I am executing an AsyncTask from inside a DialogFragment but the progress bar is not shown during doInBackground. Here is the code:
public class GetCustomerSoapAsync extends AsyncTask<Void, Void, String>
{
ProgressDialog prg;
ActionBarActivity activity;
GetResponseFromGetCustomer listener;
public GetCustomerSoapAsync(ActionBarActivity activity, GetResponseFromGetCustomer listener)
{
this.activity = activity;
this.listener = listener;
prg = new ProgressDialog(activity);
prg.setMessage("Lütfen Bekleyin");
Log.i("ED","Progress will be shown");
prg.show();
}
#Override protected String doInBackground(Void... params)
{
//some stuff
}
#Override protected void onPostExecute(String s)
{
listener.getResponseFromGetCustomer(s);
if (prg.isShowing())
{
prg.dismiss();
}
}
and where I call it:
public class B1_PhoneNumberFragment extends android.support.v4.app.Fragment
{
...
buttonLogin.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
...
PhoneNumberVerified dialog = new PhoneNumberVerified();
dialog.show(getFragmentManager(), "NumberVerifiedByUser");
}
...
}
....
public class PhoneNumberVerified extends DialogFragment
{
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Format of this dialog will be changed
builder.setMessage("Numaranız doğru mu?\n" + "0" + number)
.setPositiveButton(R.string.yes,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,
int id)
{
GlobalApplication.getUser().setPhone(
(excludeParanthesis
(number)));
//AsyncTask is not working properly,
// progress dialog is not shown and code flows before
// response is set to s
GetCustomerSoapAsync getCustomerSoapAsync =
new GetCustomerSoapAsync(
(ActionBarActivity) getActivity(),
new GetResponseFromGetCustomer()
{
#Override
public void getResponseFromGetCustomer
(String s)
{
response = s;
}
});
getCustomerSoapAsync.execute();
Log.i("ED", "Response after GetCustomerSoapAsync callback: " +
response);
}
And finally, maybe because of the flawed flow of the tasks or maybe something else, the callback can't do its job, and response is not set to return value of the AsyncTask.
Thanks for any help!
You should use onPreExecute :
class Task1 extends AsyncTask<Object, Void, String []> {
/** The Progress dialog. */
private final ProgressDialog dialog = new ProgressDialog(YourActivity.this);
/**
* Set the Progress dialog.
*/
protected void onPreExecute()
{
super.onPreExecute();
this.dialog.setMessage("Loading...");
this.dialog.show();
dialog.setCanceledOnTouchOutside(false);
}
protected String[] doInBackground(Object... params) {
///
}
protected void onPostExecute(String [] result)
{
super.onPostExecute(result);
this.dialog.dismiss();
}
}
To call it you should:
Task1 myTask = new Task1();
myTask.execute(stopArrey, start, end);
Hope it helped! :)
You need to operate on the ProgressDialog only on the UI Thread.
The constructor on the asynctask gives great flexibility enough to put the task in it's own class. Note: It's important that any field that is initialized in the Constructor on your custom AsyncTask takes advantage of the java final keyword so the field variables get automatic null for garbage collection.
Solution ProgressDialog code needs to be invoked in onPreExecute() where the task is still on the UI thread.
public class GetCustomerSoapAsync extends AsyncTask<Void, Void, String>
{
ProgressDialog prg;
// use final for fields initialized in a constructor.
final ActionBarActivity activity;
final GetResponseFromGetCustomer listener;
//The example below passes in the ProgressDialog from the caller where it's already shown. Pass it in to have access in the async tasks publish Progress method. Dismiss the ProgressDialog in the listener method; You didn't show your listener so this is just a technique
public GetCustomerSoapAsync(ActionBarActivity activity, GetResponseFromGetCustomer listener, ProgressDialog prg)
{
this.activity = activity;
this.listener = listener;
this.prg = prg;
// or move this code to onPreExecute() where it runs on the UI thread.
// move this code to onPreExecute()
//prg = new ProgressDialog(activity);
//prg.setMessage("Lütfen Bekleyin");
//Log.i("ED","Progress will be shown");
//prg.show();
}
Ok the issue I believe is you have to declare the PD in the layout visible to the user before the Aysnch task is executing.
For example:
//Declare the pd here. Pd private to class.
private ProgressDialog pd;
builder.setMessage("Numaranız doğru mu?\n" + "0" + number)
.setPositiveButton(R.string.yes,
new DialogInterface.OnClickListener()
{
....
pd = ProgressDialog.show(getActivity(), "",
"Your Message Here!!!", false);
// Now using a modified constructor call your execute function
//Previous parametes + pd
GetCustomerSoapAsync gCSA = new GetCustomerSoapAsync(...,...,pd);
getCustomerSoapAsync.execute();
}
Then in your Asynch class:
public class GetCustomerSoapAsync extends AsyncTask<Void, Void, String>
{
ProgressDialog prg;
ActionBarActivity activity;
GetResponseFromGetCustomer listener;
public GetCustomerSoapAsync(ActionBarActivity activity, GetResponseFromGetCustomer listener,ProgressDialog pd)
ProgressDialog prg;
{
this.activity = activity;
this.listener = listener;
this.prg = pd;
}
#Override protected String doInBackground(Void... params)
{
//some stuff
}
#Override protected void onPostExecute(String s)
{
listener.getResponseFromGetCustomer(s);
if (prg.isShowing())
{
prg.dismiss();
}
}
Ps: I don't know if you are using fragments as a implementation but if you are you must refer to the same pd you called in the onclick function in the fragment via rootview else you might be calling functions on a progresss dialog that never showed in the first place.
Related
In an Android application, by clicking a button, in a fragment, I want to show an AlertDialog using AsynTask() method. I have put, in onPreExecute(), the function which called the AlertDialog. In doInBackground(), there is a task running, and in onPostExecute(), I dismiss the AlertDialog.
The crash occurs just when I click the button. And it refers to line code in the LoadingDialog class, which is dialog.show();. I have tried many suggestions given on the site, but, the issue occurs again.
Could anyone help me?
This is the LoadingDialog.java
public class LoadingDialog {
private Activity activity;
private AlertDialog dialog;
LoadingDialog(Activity myActivity){
activity = myActivity;
}
public void startLoadingDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
LayoutInflater inflater = activity.getLayoutInflater();
builder.setView(inflater.inflate(R.layout.custom_dialog, null));
builder.setCancelable(false);
dialog = builder.create();
dialog.show();
}
public void dismissDialog(){
dialog.dismiss();
}
}
This is my Fragment class
public class MyFragment extends Fragment {
View view ;
private Button btn_;
private Activity activity;
private AlertDialog dialog;
private LoadingDialog loadingDialog;
public MyFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.view = inflater.inflate(R.layout.fragment_, container, false);
loadingDialog = new LoadingDialog(getActivity());
btn_ = this.view.findViewById(R.id._button);
eventListnerReinitialiser();
return this.view;
}
public void eventListnerReinitialiser() {
this.btn_.setOnClickListener(v -> {
new ShowDialogAsyncTask().execute();
});
}
public class ShowDialogAsyncTask extends AsyncTask<Void, Void, Void> {
int s = 0;
#Override
protected void onPreExecute() {
loadingDialog.startLoadingDialog();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
for(int i=0;i<1000000;i++)
s = s + i;
Toast.makeText(view.getContext(), "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ;
return null;
}
#Override
protected void onPostExecute(Void result) {
loadingDialog.dismissDialog();
super.onPostExecute(result);
}
}
}
And I have this error log in my console of Android studio
E/WindowManager: android.view.WindowLeaked: Activity com.example.myproject.Menu2Activity has leaked window DecorView#96c506[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:511)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:338)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:322)
You are showing a toast in the doInBackground() of the AsyncTask, and this cannot be done. You can only update the Ui in the main thread.
Showing the toast in the doInBackground() which is running in a background thread throws a exception and your fragment is forced to shutdown at that moment but the dialog is still open which caused the exception.
So try calling the Toast.makeText(view.getContext(), "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ; in the onPostExecute of AsyncTask.
Here is how to do the AsyncTask part.
public class ShowDialogAsyncTask extends AsyncTask<Void, Void, Void> {
int s = 0;
#Override
protected void onPreExecute() {
loadingDialog.startLoadingDialog();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
for(int i=0;i<100_000_000;i++)
s = s + i;
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(MainActivity.this, "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ;
loadingDialog.dismissDialog();
super.onPostExecute(result);
}
}
In addition to what Vivek said also:
Change the ShowDialogAsyncTask to static class
pass the dialog as WeakReference then use weakReference.get() in each place where it is
used
To show dialog pass context.getApplicationContext() as weak reference.
Currently your Activity is leaking through AsyncTask.
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.
I want to show the progress bar in Async task onPreExecute(). But I am unable to pass the context. Can some one help?
public class myClass extends AsyncTask<Void,Void,Void>{
Context ctx;
ProgressDialog d;
String s;
public myClass (String S, Context con) {
this.ctx = con;
this.s = S;
}
#Override
protected void onPreExecute() {
d = new ProgressDialog(this.ctx);
d.setMessage("Please wait...");
d.setIndeterminate(true);
d.show();
}
Calling from the Main Activity as
new myClass(MainActivity.this);
myClassObj.execute(s);
It should be like this, passing into the constructor.
public class myClass extends AsyncTask<Void,Void,Void>{
private ProgressDialog dialog;
private String paramOne;
private int paramTwo;
public myClass (Activity activity, String paramOne, int paramTwo) {
dialog = new ProgressDialog(activity);
this.paramOne = paramOne; // "Hello"
this.paramTwo = paramTwo; // 123
}
#Override
protected void onPreExecute() {
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
Call it like this.
new myClass(YourActivity.this, "Hello!", 123).execute();
I have a better approach for this, use progress bar in your activity or fragment and as soon as you start your asynctask set the visibility to VISIBLE and when you get result in on postExecute set the visibility gone by using the interface in activity. Something like this
/**
* Listener for listening events happening in background task, whether cancelled or completed
* with error or success.
*/
public interface Listener {
/**
* Callback invoked when request is completed and response is got with
* code == {#value java.net.HttpURLConnection#HTTP_OK}.
*/
void onSuccess(Response response);
/**
* Callback invoked when request is cancelled or completed with response
* code != {#value java.net.HttpURLConnection#HTTP_OK}.
*/
void onError(Response response);
}
and in your activity
void onSuccess(Response response){
//Visibility to Gone.
}
There will be two cases of calling AsyncTask,
When calling AsyncTask in same Activity:-
public class myClass extends AsyncTask<Void,Void,Void>{
ProgressDialog d;
String s;
public myClass (String str) {
this.s= str;
}
#Override
protected void onPreExecute() {
d = new ProgressDialog(getApplicatinContext());
d.setMessage("Please wait...");
d.setIndeterminate(true);
d.show();
}
Calling from the Main Activity as
myClassObj.execute();
If u need to call in separate Activity or in separate file then u need to follow the below code:-
public class myClass extends AsyncTask<Void,Void,Void>{
Activity act;
ProgressDialog d;
public myClass (Activity act) {
this.act = act;
}
#Override
protected void onPreExecute() {
d = new ProgressDialog(act.getApplicationContext());
d.setMessage("Please wait...");
d.setIndeterminate(true);
d.show();
}
Calling from the Main Activity as
new myClass(MainActivity.this);
myClassObj.execute(s);
So I am completely new to Andorid programming and can't seem to get a ProgressDialog to show on a ListActivity (ScheduleActiviy in my example) when running an AsyncTask from a separate class (GetGames in my example). I am attempting to use separate class for code re-usability. When I previously had the AsyncTask as an embedded class it seemed to work. I have posted what I believe to be all the relevant code. Any help would be great. Thanks!
ScheduleActivity.java
public class ScheduleActivity extends ListActivity
{
private final String PDIALOG_MSG = "Loading schedule...";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.schedule);
ArrayList<HashMap<String, String>> gamesList = null;
try
{
// Loading information in Background Threads
gamesList = new GetGames(ScheduleActivity.this, PDIALOG_MSG).execute().get();
GetGames.java
public class GetGames extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>
{
private Context context;
private ProgressDialog pDialog;
private String pDialogMsg;
public GetGames(Context ctx, String dialogMsg)
{
context = ctx;
pDialogMsg = dialogMsg;
}
#Override
public void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage(pDialogMsg);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
public void onPostExecute(ArrayList<HashMap<String, String>> rtnList)
{
pDialog.dismiss();
}
Your ProgressDialog should probably be controlled on the Activity level instead of the AsyncTask level. Theoretically I don't see why how you're doing it wouldn't work, but I can show you a method which definitely works (it's what I do) and it organizes things a bit differently:
//In AsyncTask
#Override
protected void onPreExecute() {
showProgressDialog(R.string.importing_pages);
}
#Override
public void onPostExecute(Boolean b) {
hideProgressDialog();
}
//In Activity
public void showProgressDialog(int msgResId) {
showProgressDialog(getString(msgResId));
}
public void showProgressDialog(String msg) {
mProgressDialog = ProgressDialogHelper.buildDialog(this, msg);
mProgressDialog.show();
}
public void hideProgressDialog() {
if(mProgressDialog != null)
mProgressDialog.dismiss();
}
//My progress dialog helper class:
public class ProgressDialogHelper {
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msgResId the resId for the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, int msgResId) {
return buildDialog(activity, activity.getApplicationContext().getString(msgResId));
}
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msg the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, String msg) {
ProgressDialog dialog;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
dialog = new ProgressDialog(new ContextThemeWrapper(activity, android.R.style.Theme_Holo_Dialog));
else
dialog = new ProgressDialog(activity);
dialog.setMessage(msg);
dialog.setCancelable(false);
return dialog;
}
}
You don't have to make a helper class if you don't want to, it's just how I organized it. The main idea here is that the progress dialog should be owned by the Activity instead of the AsyncTask.
Also, the context used must be the activity's, not getApplicationContext(). It looks like you have that part right though.
You can display Progress Dialogs using AsyncTasks. That's not a problem. I do it all the time. What may be the problem is the doInBackground() method. What do you have there?
I also generally nest the AsyncTasks within the Activity class, so that it can call other Activity class methods in the onPostExecute() method. Otherwise, in order for it to communicate back with your Activity you'll have to use something like a handler or static references.
public class TestActivity extends Activity {
private AsyncTask<Void, Void, ArrayList<String>> bgLoader;
private ArrayList<String> listOfStuff;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
listOfStuff = new ArrayList<String>();
textView = (TextView) findViewById(R.id.textView);
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
bgLoader = new MyAsyncTask(this, "Waiting...").execute();
}
private void resumeDoingStuff() {
try {
listOfStuff = bgLoader.get();
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public class MyAsyncTask extends AsyncTask<Void, Void, ArrayList<String>> {
private ProgressDialog progressDialog;
private String message;
private Context ctx;
public MyAsyncTask(Context context, String message) {
this.ctx = context;
this.message = message;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(ctx);
progressDialog.setMessage(message);
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
ArrayList<String> retList = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
try {
retList.add("TEST STRING " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return retList;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
progressDialog.dismiss();
resumeDoingStuff();
}
}
}
In my application , I have a listview and each item has a button. If user clicks the button ,i want to execute some http connection. So i use AsyncTask in the Adapter class. Now the problem is progress dialog is not showing.
private class MyClass extends AsyncTask<Void, Long, Boolean> {
private Context context;
private ServerCall call = new ServerCall();
private ProgressDialog progressDialog1;
public MyClass(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
progressDialog1 = ProgressDialog.show(context, "",
"Please wait...", true);
progressDialog1.setIndeterminate(true);
} catch (final Throwable th) {
}
}
#Override
protected void onProgressUpdate(Long... values) {
super.onProgressUpdate(values);
}
#Override
protected Boolean doInBackground(Void... params) {
//some tasks
return true;
}
#Override
protected void onPostExecute(Boolean result) {
if (mode.equalsIgnoreCase("History")) {
Intent order = new Intent(context, ActicityA.class);
order.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(order);
} else {
Intent order = new Intent(context, ActivityB.class);
order.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(order);
}
}
}
Try this instead'
protected void onPreExecute() {
dialog = new ProgressDialog(Activity.this);
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
//dialog.setCancelable(false);
dialog.show();
}
Follow this steps
[0] start showing progressbar
[1] Execute AsyncTask class
[2] in this class one interface for post the response in main class
[3] Declare one interface class
[4] get Reponse in Main Clss using interface
[5] dismiss Progressbar and Bind your Data
ex.
[0]
progr.setVisibility(View.VISIBLE);
[1]
MyTask task = new MyTask();
task.setdata(new SendData() {
[4] #Override
public void GetStringResponse(String str) {
Log.i(General.TAG, TAG + " Overide GetString-"+str);
final String GetResponse=str;
// here you get response and parse it
[5] // here you can dismiss your progress bar
}
});
task.execute(new String[] {Newsurl[Id]});
[2] Add interface here with Method
SendData objsend;
#Override
protected void onPostExecute(String Result)
{
Log.i("**********", Result);
objsend.GetStringResponse(Result);
}
public void setdata(SendData sendd)
{
Log.i(General.TAG,TAG+"Initialise Interface object");
objsend = sendd;
}
[3] interface class
public interface SendData {
public abstract void GetStringResponse(String str);
}
<pre><code>
public MyClass(Context context) {
this.context = context;
progressDialog1=new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
progressdialog1.setMessage("please wait while loading");
progressdialog1.setIndeterminate(true);
}
Its true that ProgressDialog.show() method returns a ProgressDialog obect, but its better to first create an object of ProgressDialog like:
ProgressDialog progressDialog1 = new ProgressDialog();
and then
progressDialog1 = ProgressDialog.show(context, "",
"Please wait...", true);
And also, try to finish the progressDialog1 in onPostExecute() by calling its dismiss() method.