I'm trying to create ProgressDialog during parsing of JSON objects. So I'm using AsyncTask:
private class JsonUtility extends AsyncTask<String, Void, String> {
//getting activity context like that since outer activity is not enclosing
public JsonUtility(Activity activity){
super();
mActivity = activity;
}
public JsonUtility(){}
#Override
protected void onPreExecute(){
super.onPreExecute();
dialog = ProgressDialog.show(mActivity, "Loading...", "Please wait...", true);
}
#Override
protected String doInBackground(String... params) {
//...operate with JSON
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
dialog.hide();
}
}
and I'm getting information from JSON like that:
public ArrayList<CoursesData> getCourses(Activity activity){
ArrayList<CoursesData> resultArrayList = new ArrayList<>();
try {
JSONArray jArray = new JSONArray(new JsonUtility(activity).execute(coursesUrl).get());
//...and so on
}
activity is passed to JsonUtility when Fragment is created with getActivity():
ArrayList<CoursesData> coursesDatas = parserJson.getCourses(getActivity());
is it correct way to pass activity context from Fragment?
Or probably problem lies somewhere else? This ProgressDialog simply doesn't appear although the loading takes about 2-3 sec.
Please help me to solve this problem.
change mActivity to getParent()... its working for me
Related
I am newbie to android and facing issue on Progress dialog,though myriad question and answers are here but none is working for me.Any help will be greatly appreciated.
I want to show a spinning wheel on my login page of app,all my Async Task activties are in different class and I am passing the activity reference to my HttpClientHelper class which is handling Async Task.No progress dialog appears when i click on Login button.
Most of the answers have mentioned to implement the Async Task in Activity class but i have created a utility class which is handling the POST/GET in background.
Hence in thin non activity class i dont have the reference of Context so i passed LoginActivity.this in HttpClientHelper constructor.
AM i doing something wrong here.Due to multiple use of POST/Get i can implement them in each activity.
Please find the sample files these are not actual code I am posting the steps
public class LoginActivity extends AppCompatActivity {
btnSignIn.setOnClickListener(new View.OnClickListener() {
HttpClientHelper httpClientHelper = new HttpClientHelper(LoginActivity.this);
JSONObject json = httpClientHelper.postJSON(apiURL
, params);
...... rest of the code
}
}
Here is the HttpClientHelper
public class HttpClientHelper {
private Activity activity;
private static HttpURLConnection urlConnection;
private static String result;
private static JSONObject jsonObject = null;
public HttpClientHelper(){
}
public HttpClientHelper(Activity activity){
this.activity=activity;
}
public JSONObject postJSON(String url, Map<String, String> params) {
Params param = new Params(url, params);
PostAsyncTask myTask = new PostAsyncTask();
try {
jsonObject = myTask.execute(param).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return jsonObject;
}
private class PostAsyncTask extends AsyncTask<Params, String, JSONObject> {
JSONObject json = null;
ProgressDialog progressDialog;
public PostAsyncTask(){
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressDialog = new ProgressDialog(activity);
progressDialog.setTitle("Login");
progressDialog.setMessage("Loading..Please Wait");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected JSONObject doInBackground(Params... args) {
json = HttpClientHelper.getJSONFromURL(args[0].url, args[0].params);
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
super.onPostExecute(json);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
}
Progress dialogue is associated with UI and any updates in view is not recommended to put inside a AsyncTask. UI updates or changes should occur in the UI thread.
In your case, the desired result can be achieved by setting a listener to the AsyncTask. Simply add a listener class and implement the listener in the activity class.
Here's an example.
HttpResponseListener.java
public interface HttpResponseListener {
public void httpResponseReceiver(String result);
}
Now in your LoginActivity implement the interface like this:
public class LoginActivity extends AppCompatActivity implements HttpResponseListener {
// rest of your code
// initialize your progress dialogue here and execute the asynctask
progressDialogue.show();
myTask.execute();
myTask.mHttpResponseListener = this;
#Override
public void httpResponseReceiver(String result) {
if(result == null)progressDialogue.dismiss();
else {
// Use result to serve your purpose
progressDialogue.dismiss();
}
}
}
Now in your AsyncTask class, set the result in post execute.
private class PostAsyncTask extends AsyncTask<Params, String, JSONObject> {
JSONObject json = null;
ProgressDialog progressDialog;
public HttpResponseListener mHttpResponseListener;
public PostAsyncTask(){
}
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(Params... args) {
json = HttpClientHelper.getJSONFromURL(args[0].url, args[0].params);
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
super.onPostExecute(json);
mHttpResponseListener.httpResponseReceiver("OK");
}
#Override
protected void onCancelled() {
mHttpResponseListener.httpResponseReceiver(null);
}
}
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.
I retreive data from server by means of external class which contains AsyncTask:
public class GetTask extends AsyncTask<String, Void, JSONObject> {
private Context context;
ProgressDialog dialog;
public GetTask(Context cxt) {
context = cxt;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
dialog.setTitle("Load...");
dialog.setMessage("Data...");
dialog.show();
super.onPreExecute();
}
#Override
protected JSONObject doInBackground(String... url) {
// code for retreive data
return jArray;
}
protected void onPostExecute(JSONObject object) {
dialog.dismiss();
super.onPostExecute(object);
}
}
I call this task from my activity:
Tasks task = new Tasks();
JSONObject json = task.new GetTask(this).execute(ServerURL).get();
My data retrieved successfully but ProgressDialog show after super.onPostExecute(object); method, why?
P.S. dialog show after:
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
on internal Looper.class
Sorry my english is bad. ))
I found the solution, need use callback and not use .get() method. I call my task:
callTask(linkODeatails, obj);
callTask:
void callTask(String link, String object){
task.new GetTask(this).execute(link + object);
}
I create interface:
public interface AsyncTaskCompleteListener {
public void onTaskComplete(JSONObject result);
}
And added on my task:
private Activity activity;
private AsyncTaskCompleteListener callback;
public GetTask(Activity act){
this.activity = act;
this.callback = (AsyncTaskCompleteListener)act;
}
them called:
callback.onTaskComplete(result, object);
I currently have a class UserFunctions that does all my user actions e.g. register, login etc. In the UserFunctions class there's a JSONParser object that does all the actual HTTP calls and returns the JSONObject.
public class UserFunctions {
private JSONParser jsonParser;
private static String registerURL = Constants.registerUrl;
// constructor
public UserFunctions(){
jsonParser = new JSONParser();
}
public JSONObject register(){
// getting JSON Object
JSONObject json = jsonParser.getJSONFromUrl(registerURL);
// return json
return json;
}
...
}
and then in my event handler of my activity classes I just do UserFunctions.register().
My question is, I now want to do all these calls in a background thread and at the same time show a ProgressDialog. I know running in the background thread is achieved with the AsyncTask.
But how should I achieve this design such that I can still do UserFunctions.register() in my Activity class, everything to be done in a background thread and a progressDialog shown.
Ok for this there are two parts the progress dialog and the async task, you need to move your JSONparser into the actual async task. If you want to use multiple progress dialogs just call them before calling the asynctask and close them when it returns
private class JsonRetriever extends AsyncTask<Url, Void, JSONObject>{
private JSONParser jsonParser;
private ProgressDialog dialog;
public JsonRetriever(Context c){
dialog= new ProgressDialog(c);
jsonParser= new JSONParser();
}
protected void onPreExecute() {
dialog.setMessage("Starting retrieval");
dialog.show();
}
protected JSONObject doInBackground(Url... params) {
try{
return jsonParser.getJSONFromUrl(params[0]);
}catch(Exception e){
return false;
}
return true;
}
protected void onPostExecute(final JSONObject success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
Then to call this just do
public JSONObject register(){
return new JSONRetriever(this).execute(registerURL).get();
}
Do as the following:
1)Declare you dialog in activity class like this:
ProgressDialog dialog;
2)then declare you AsyncTask as below:
private class RegisterUser extends AsyncTask<String,Integer,String>{
String nessage="";
#Override
protected void onPreExecute(){
dialog = ProgressDialog.show(context, "Registering user",
"Please wait.....");
}
#Override
protected String doInBackground(String... params) {
// provide yourcode to register the user then return message
return message="you are registered";
}
protected void onPostExecute(String result) {
dialog.dismiss();
if (result.equlas("you are resgisted"))
// optinal if you want to do as below
// do something here showing toast or any thing of your prefreance
}
}
Would this help you?
#Override
public void onCreate(Bundle savedInstanceState) {
new MyAsyncTask(this).execute();
}
privateclass MyAsyncTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Context context;
public ProgressTask(Context context) {
this.context= context;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
protected Boolean doInBackground(final String... args) {
// do you registering or whether here
// in this model you can return a boolean to the PostExecute.
}
}
Have a look at publishProgress() from the AsyncTask-Class i think its what you are looking for.
This method is used for updating the UI, when the Background-Thread done some Work. You can call it when ever you want it in the doInBackground()-Method.
So I'm relatively new to Android (and Java). I've made a class which has your usual AsyncTask with a ProgressDialog in a static method because I want to call it from multiple Activities.
public class SomeClass {
// Some other methods, etc.
public static void SomeFunction(final Context context, String FilePath) {
new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
protected void onPreExecute() {
dialog = ProgressDialog.show(context, "", "Loading...", true);
}
protected Void doInBackground(Void... unused) {
for (int i=0; i<15000; i++)
System.out.println("Gatorade me, Bitch: " + i);
return null;
}
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
}.execute();
}
}
The problem is that the statement
dialog = ProgressDialog.show(context, "", "Loading...", true);
in the onPreExecute() section of the AsyncTask gives error. The code runs fine without it.
So what can I do to solve this issue without creating a new java class file for AsyncTask. I know that works but I just want to make one file for this entire class so I can use it in multiple programs.
Thanks for your help!
Check whether you are passing application context or activity context while calling the function.
With application context, you cannot show the Progress Bar. If thats the case, try passing activity context.
SomeFunction(ActivityName.this,"path");