NullPointerException when trying to show ProgressDialog from a Static AsyncTask method - android

I have a static AsyncTask in my MainActivity. I run this asynctask to download data from a URL. I'm trying to show a progress dialog from the async task but it crashes on this line: private ProgressDialog dialog = new ProgressDialog(mContext);
I pass the context through to the AsyncTask.
Here is my code:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog = new ProgressDialog(mContext);
public MyTasksParse(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.dialog.setCanceledOnTouchOutside(false);
this.dialog.setMessage("Downloading Files... Please Wait...");
this.dialog.show();
}
#Override
protected JSONObject doInBackground(String... args) {
//get the url and parse it
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
I have tried casting mContext as an Activity as follows:
private ProgressDialog dialog = new ProgressDialog(mContext); but still the same error.
I'm not sure what I'm doing wrong. If anyone can help out, it would be great! Thanks :)

Since you have NullPointerException beacuse the variable mContext is null at this point:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog = new ProgressDialog(mContext);
...
...
this will help:
private static class MyTasksParse extends AsyncTask<String, String, JSONObject> {
private Context mContext;
private ProgressDialog dialog;
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext)
}
When you receive the value of context in the constructor then you can instatiate correctly the ProgressDialog =).

mContext is null when you pass it to the constructor of ProgressDialog, thus throwing a NullPointerException.
This should work:
private Context mContext;
private ProgressDialog dialog;
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext);
}

The mContext is null when you initialise the ProgressDialog. That's why the crash is happening.
You need to change:
private ProgressDialog dialog = new ProgressDialog(mContext);
to:
private ProgressDialog dialog;
And initialise the progress dialog in onPreExecute:
dialog = new ProgressDialog(mContext);

You are getting NullPointerException beacuse mContext is null.
You need to init ProgressDialog inside constructor like
public MyTasksParse(Context context) {
mContext = context;
dialog = new ProgressDialog(mContext)
}

Related

AsyncTask onPreExecute new progressdialog

class AddStudent extends AsyncTask<String, Void, ResultData> {
private ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(AddStudentActivity.this);
pDialog.setMessage("Adding Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
private Context context;
//CHANGE HERE....ADD PARAMATER
TextView tv_msg;
public AddStudent(Context context, TextView tv_msg) {
this.context = context;
this.tv_msg = tv_msg;
}
I have an error in (AddStudentActivity.this);
Error = com.blablablabla.AddStudentActivity is not an enclosing class.
What's the problem?.
How can I fix this?.
If the asynctask is not a nested class of an activity you need to set/add the context as a parameter to the constructor.
class AddStudent extends AsyncTask<String, Void, ResultData> {
private ProgressDialog pDialog;
private Context context;
public AddStudent(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context) ;
pDialog.setMessage("Adding Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
}
TextView it is part of the activity.
Or, if the asynctask is a nested class of an activity, then you can do what you want. More you can read in the example below:
ProgressDialog and AsyncTask
You have not posted your entire code, so this is a bit of speculation, but here goes:
Most probably you have created a separate file for your AddStudent AsyncTask, or put it outside your AddStudentActivity class. You need to make AddStudent an inner class of AddStudentActivity to be able to use AddStudentActivity.this.
More info here : Android: AsyncTask recommendations: private class or public class?
pDialog = new ProgressDialog(AddStudentActivity.this) ;
change to
pDialog = new ProgressDialog(context) ;
its work.
Error = com.blablablabla.AddStudentActivity is not an enclosing class.
above error comes whenever you try to use Activity context in other separate class .
This should even harmful for you when it will give you memory leaks.
pDialog = new ProgressDialog(context);

Android - Having troubles displaying\dismissing a progress dialog while using AsyncTask

I'm making a url request using AsyncTask, and want to display some sort of progress spinner while the request is processed. The AsyncTask class is located within another Activity VerificationActivity which extends Activity. The app crashes on this line: dialog = new ProgressDialog(context); Probably the problem is with the context of the app, I tried VerificationActivity.this and creating a local instance of VerificationActivity and passing it as a context.
SmsTask smsTask = new SmsTask(VerificationActivity.this);
/*
* some code
*/
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
ProgressDialog pd;
SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pd = new ProgressDialog(mContext);
pd.setProgressStyle(AlertDialog.THEME_HOLO_DARK);
pd.show(mContext,"Please wait","Sending...");
}
protected Boolean doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
httpclient.execute(httppost);
b.set(true);
} catch (IOException e) {
e.printStackTrace();
}
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// result holds what you return from doInBackground
if(pd.isShowing()){
pd.dismiss();
}
Log.i("result from async: ",""+result);
}
}
This is the error message I'm getting:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
UPDATE:
I fixed the context issue based on the answers here, and ran a test, simulated some heavy work inside the doInBackground method using the Thread.sleep() method, but the progress spinner still doesnt show. Any ideas?
UPDATE2:
I managed to show the progress dialog as i need, but now im not able to dismiss it. I assume it is because I cant dismiss UI elements, do i need to run the progress dialog inside runOnUIThread?
I assume you pass the activity as context and by the time the task is going to be executed, the activity might be gone and the you'll get NullPointerException, so 2 options you have;
Check for the context- of it's null you might not need the loading dialog at all
Use the Application context
Hi please see below the updated AsynTas.
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
private ProgressDialog dialog;
private SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
Log.i("executing Pre - execute","");
dialog = new ProgressDialog(mContext );
dialog.setMessage("Loading...");
dialog.show();
}
protected Boolean doInBackground(String... params) {
//.... dosing stuff
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
if(dialog.isShowing()){
dialog.dismiss();
}
super.onPostExecute(result);
}
}
private Context context;
you have defined context here, but you didn't initialize it. You can initialize it by a constructor
public SmsTask(Context con){
context = con;
}
and when you call your SmsTask pass context to it.
You need to get the application context -
dialog = new ProgressDialog(getContext());

AsyncTask not receiving calling activity context

I'm getting the error message "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application.
Yes, I know this error is all over stackoverflow and it's based on not getting the context of the activity... however, I am pulling that context and still receiving the error.
From MainActivity:
new MemberStream(this).execute();
From MemberStream:
>
public HomeActivity activity;
ProgressDialog dialog;
public MemberStream(HomeActivity a) {
this.activity = a;
dialog = new ProgressDialog(a.getApplicationContext());
}
#Override
protected void onPreExecute() {
this.dialog.setMessage("Loading");
this.dialog.show();
}
#Override
protected Boolean doInBackground(String... params) {
updateMembers(url, 0);
return true;
}
When I run the application, I get the preceding error on
dialog = new ProgressDialog(a.getApplicationContext());
Any ideas?
public Activity activity;
ProgressDialog dialog;
public MemberStream(Activity a) {
this.activity = a;
dialog = new ProgressDialog(a);
}
You alread have a context object (Your activity)
dialog = new ProgressDialog(a);
You already have a activity context passed to the asynctask constructor.
To know when to use activity context and when to use application context check the link below and answer by commonsware
When to call activity context OR application context?
You can use this
public Context context ;
ProgressDialog dialog;
public MemberStream(Context c) {
context = c;
dialog = new ProgressDialog(c);
}

What is the context in Async task

I am running an Async(doInBackground) task in android.
I need to populate a progress bar for the task. So i am showing a progressDialog in onPreExecute,
The signature of ProgressDialog.show is Show(Context,Title,message)
But what would be the Context here?
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(???, "Loading", "Please Wait");
}
Create a constructor for your AsyncTask that takes a context as a parameter.
public class async extends AsyncTask<String, Integer, String>{
private Context context;
public async(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// Manipulate progress bar
}
Then use this to execute it
async mTask = new async(context).execute(params);
Context can be only of Activity ,Service or Brodcast not of any other class like Asyncktask.So put the Context of that Activity where you are using that AsyncTask class.
You can pass the activity context in the AsyncTask constructor to create the ProgressDialog :
MyAsyncTask constructor :
public MyAsyncTask(Context context){
progressDialog = new ProgressDialog(context, "Loading", "Please wait...");
}
onPreExecute method :
#Override
protected void onPreExecute()
{
progressDialog.show();
}
or store the context and create the dialog in the onPreExecute methods (but I prefer use the first way) :
public class MyAsyncTask extends AsyncTask{
private Context mContext;
public MyAsyncTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(this.mContext, "Loading", "Please Wait");
}
}
And in activity when you declare MyAsyncTask, you pass the activity:
MyAsyncTask asyncTask = new AsyncTask(this);
asynchTask.execute();
Add this function in your class
private Context getDialogContext() {
Context context;
if (getParent() != null)
context = getParent();
else
context = this;
return context;
}
In your asynctask use it as follows
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(getDialogContext(), "Loading", "Please Wait");
}
if you want to use only this as context then your Asynctask should be written as an inner class of a class which extends the Activity class. Then your context is the name of the class which extends Activity. Still it is better practice to pass the context like this:
ClassExtendingActivity.this
you can pass current activity view reference like MainActivity.this

Android AsyncTask Better way of accessing Activity Context

It took my quite a while to get this to work, but It's clearly not best practice. In short, I need to show a dialog when my AsyncTask finishes, but getApplicationContext() does not work, neither does passing it as a parameter when creating the AsyncTask. So I've declared a public variable for the context in my AsyncTask class and set it before I execute:
private OnClickListener clickLoadRefs = new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("H","Clicked Load Refs");
RefreshRefPoints refreshRefPoints = new RefreshRefPoints();
refreshRefPoints.myCtx=v.getContext();
refreshRefPoints.execute(v.getContext());
}
};
private class RefreshRefPoints extends AsyncTask<Context, Integer, Integer> {
private Integer nPoints=0;
public Context myCtx;
private ProgressDialog pd;
protected Integer doInBackground(Context... ctx) {
Log.d("H","doInBackground()");
dbHelper.clearRefPoints();
requestRefPoints();
nPoints = parseRefPointsCSV();
return nPoints;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPreExecute()
{
pd = ProgressDialog.show(myCtx, "Refreshing Reference Points", "Loading...", true,false);
Log.d( "H", "onPreExecute()" );
}
protected void onPostExecute(Integer result) {
pd.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(myCtx);
builder.setTitle("Reference points refresh complete");
builder.setMessage(result+" records loaded");
builder.setPositiveButton("OK",null);
builder.show();
Log.d("H","onPostExecute()");
}...etc
Can anybody just show me the proper way of passing the context?
Thanks
Define a constructor method and pass context a parameter. It would be better.
Here what I meant:
private class RefreshRefPoints extends AsyncTask<Void, Integer, Integer> {
private Integer nPoints=0;
private Context myCtx;
private ProgressDialog pd;
public RefreshRefPoints(Context ctx){
// Now set context
this.myCtx = ctx;
}
}
That's all.
You may also use YourActivityName.this to refer to the activity Context. Because Activites extend Context, so its valid to do so.
Pass context in constructor as
private OnClickListener clickLoadRefs = new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("H","Clicked Load Refs");
RefreshRefPoints refreshRefPoints = new RefreshRefPoints(Your_ActivityName.this);
refreshRefPoints.myCtx=v.getContext();
refreshRefPoints.execute(v.getContext());
}
};
private class RefreshRefPoints extends AsyncTask<Void, Integer, Integer> {
private Integer nPoints=0;
public Context myCtx;
private ProgressDialog pd;
public RefreshRefPoints (Context ctx) {
myCtx = ctx;
}

Categories

Resources