Very unusual error while dismissing ProgressDialog in AsyncTask - android

I've developed an Android 2.2 application and I get only one time this error:
java.lang.IllegalArgumentException: View not attached to window manager
This error occur when I dismiss ProgressDialog. This dialog is on an AsyncTask. Here is my code:
private class LoadGatesAsyncTask extends AsyncTask<Void, Void, Boolean>
{
private Context mContext;
private ArrayList<Gate> mGatesList;
private ProgressDialog mLoadingDialog;
public LoadGatesAsyncTask(Context context)
{
this.mContext = context;
mLoadingDialog = new ProgressDialog(mContext);
mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mLoadingDialog.setMessage(getString(R.string.msg_loading_gates));
mLoadingDialog.setCancelable(false);
mLoadingDialog.show();
}
#SuppressWarnings("unchecked")
#Override
protected Boolean doInBackground(Void... params)
{
Boolean result = false;
try
{
[ ... ]
}
catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(Boolean result)
{
super.onPostExecute(result);
if (result)
{
[ ... ]
mLoadingDialog.dismiss();
}
else
{
mLoadingDialog.dismiss();
Toast toast = Toast.makeText(mContext,
getString(R.string.msg_error_loading_gates),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER,
toast.getXOffset() / 2,
toast.getYOffset() / 2);
toast.show();
}
}
}
How can avoid this error programmatically? Is there any check that I could do to avoid dismiss it if it isn't attached to window manager?

are you instantiating LoadGatesAsyncTask in OnCreate?
If so move the loadingDialog instantiation to OnPreExecute rather than in the Constructor.

You could add the check:
if(mLoadingDialog.isShowing()){
mLoadingDialog.dismiss();
}

You are initializing this ProgressDialog in constructor, not in onPreExecute() and that is wrong because you are dismissing the ProgressDialog in onPostExecute, you need to do it on the same UI thread.
If you initialize the object - AsynTask, you get your constructor called. So your ProgressDialog will be shown, but you haven't called .execute() on the AsyncTask yet! So when you're trying to dismiss it, the compilator is finding itself on a different Thread.
EDIT: Clarifying misunderstood statement.

I think the real problem is behind the attached Activity behind the progressDialog,
it's changing to a new reference (instance),
So that the progressDialog.OwnerActivity=null (usually when in rotation onCreate is called)
it's solved by attaching the new recreated Activity to the owner : progressDialog.OwnerActivity = myActivity; (it will be passed a local parameter in your class, in the constructor pass it,
like :( here C# android, similar to java.. same idea)
class ProgressDialogAsync: AsyncTask //extends asynctask
{
//used parameters
Activity Activity;
string Title;
string Message;
ProgressDialog AsyncDialog;
public ProgressDialogAsync(Activity Activity, string Title, string Message)
{
this.Title = Title;
this.Message = Message;
this.Activity = Activity;
}
protected override void OnPreExecute()
{
AsyncDialog = new ProgressDialog(Activity);
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params) {
//do background operation
}
protected override void OnPostExecute(Java.Lang.Object result)
{
//do something
AsyncDialog.OwnerActivity = Activity;
AsyncDialog.Dismiss();
base.OnPostExecute(result);
}

Related

App getting stuck when trying to parse json response containing 25,000 json objects in Xamarin Android?

In my app I send a request to the server and get a JSON response containing a lot of JSON objects (about 25,000). Then I try to parse it by deserializing it. When sending the request to the server I show a progress dialog and after the response is received I dismiss it. But the progress dialog gets stuck after the response is received because the deserializing takes time. So to avoid the UI getting stuck I'm showing a progress dialog before deserializing and put the deserializing code in a Thread and then in the RunOnUiThread() method I'm dismissing the progress dialog. It works only for the first time but from the second time onwards again my UI gets stuck. The below is my code:
mProgressDialog = new ProgressDialog (this);
mProgressDialog = ProgressDialog.Show (this, null, "Loading list", false, false);
new Thread(new ThreadStart(() =>
{
drugsList = Newtonsoft.Json.JsonConvert.DeserializeObject<IList<Drugs>>(resp1);
RunOnUiThread(() => DismissDialog ());
})).Start();
Could you please let me know if there is any way to resolve this issue?
Thank you.
Edit:
I have tried to use an Async Task too but I'm not sure how to return IList<Drugs> from the DoInBackground() method. It saying that it can return only Java.Lang.Object type. The below is my code:
public class LoadingTask : AsyncTask
{
private ProgressDialog _progressDialog;
private String _resp1;
private Context _context;
public LoadingTask (Context context, String resp1)
{
_context = context;
_resp1 = resp1;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
_progressDialog = ProgressDialog.Show(_context, "Loading In Progress", "Please wait...");
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
IList<Drugs> dList = JSONHelper.DeserializeToList<Drugs>(#params[0].ToString());
return dList.ToString();
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
_progressDialog.Dismiss();
loadDrugs ((IList<Drugs>)result);
}
}
I'm not sure how to return IList<Drugs> instead of Java.Lang.Object.
My Drugs class extends Java.Lang.Object ie; public class Drugs : Java.Lang.Object
Edit 2:
After returning IList<Drugs> in DoInBackground():
public class LoadingTask : AsyncTask
{
private ProgressDialog _progressDialog;
private String _resp1;
private Context _context;
public LoadingTask (Context context, String resp1)
{
_context = context;
_resp1 = resp1;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
_progressDialog = ProgressDialog.Show(_context, "Login In Progress", "Please wait...");
}
protected override IList<Drugs> DoInBackground(params Java.Lang.Object[] #params)
{
IList<Drugs> dList = JSONHelper.DeserializeToList<Drugs>(#params[0].ToString());
return dList;
}
protected override void OnPostExecute(IList<Drugs> result)
{
base.OnPostExecute(result);
_progressDialog.Dismiss();
loadDrugs ((IList<Drugs>)result);
}
}
Probably you are using a parser that loads the entire data and creates a set of objects to access that data (providing which is known as an abstraction layer). You should try to load the data in chunks, maybe this blog post can help you

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

More than one level of function call in AsyncTask doInBackground() causes "Activity has leaked window" crash! Why?

I have a simple AsyncTask whose doInBackground() calls a function fn1 which in turn simply calls another fn2. The result is a "Activity has leaked window" crash! When I call fn2 directly from doInBackground() everything works fine. Does that mean in a thread one cannot have more than 1 level of fn calling?( Thread-> fn1->fn2)
I am new to Java and android, so please bear with me if that is a basic question! Thnx.
My code algo is something ike this :
MyActivity:
MyLibrary myLib;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myXML);
myLib = new MyLibrary(MyActivity.this);
new myTask().execute();
}
private class myTask extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MyActivity.this, "", "Fetching Data...");
}
#Override
protected Void doInBackground(Void... params) {
myLib.fn1();
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
MyLibrary :
Context ctx;
String iVar;
public MyLibrary(Context context){
this.ctx = context;
}
public void fn1()
{
fn2();
Log.d("TAG", "Function 1";
}
public void fn2()
{
iVar = "100";
Log.d("TAG", "Function 2";
}
Add the following in your Activity's code:
#Override
protected void onPause() {
super.onPause();
if(progressDialog != null)
progressDialog.dismiss();
}
It will dismiss the dialog window in case you move away from activity.
Usually this error happens when the Activity that you're referencing already got removed from the top of the ActivityStack. You should really check if the AsyncTask got embedded correctly into your Activity's Lifecycle.
Best wishes,
Tim
Somehow ProgressDialog may have got crashed during nested function call.

Android ProgressDialog context problems

Quick summary: I'm making an application that parses a binary file, stores vertices and their properties, and displays them in openGL. I'm trying to implement a ProgressDialog while it parses, but I'm having considerable trouble. I've tried implementing this in many places, but this is my current setup:
public class PointViewer extends Activity{
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
filePath = extras.getString("file_path");
mGLView = new GLSurfaceView(this);
theRenderer = new OpenGLRenderer();
mGLView.setRenderer(theRenderer);
//Parse the file and set the arrays
theRenderer.setLAS(filePath);
setContentView(mGLView);
}
...
}
The Rendering class...
public class OpenGLRenderer extends Activity implements GLSurfaceView.Renderer {
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setLAS (String fileName){
new ProgressTask(this).execute();
}
...
/*
* The class for the progress dialog
*/
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Context context;
//private List<Message> messages;
public ProgressTask(Context ctx) {
context = ctx;
dialog = new ProgressDialog(context);
}
/** progress dialog to show user that the backup is processing. */
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Error", Toast.LENGTH_LONG).show();
}
}
protected Boolean doInBackground(final String... args) {
try{
ptCloud = new PointCloud(args[0]);
...
dialog.setProgress(percentParsed);
return true;
} catch (Exception e){
Log.e("tag", "error", e);
return false;
}
}
}
When I call dialog = new ProgressDialog(context); It errors on a null pointer exception, I'm assuming because there is a context issue... Does anyone have any ideas?
First, you shouldn't create OpenGLRenderer yourself, because its an Activity and is supposed to be managed by system. When you create OpenGLRenderer yourself, then this activity has its context incorrectly initialized. And when your create ProgressDialog with invalid context, you receive NullPointerException.
But even if you start OpenGlRenderer correctly, your app will still crash at line:
dialog.setProgress(percentParsed);
You should use publishProgress instead and update ProgressDialog in AsyncTask's onProgressUpdate function. That's because you can't update UI from non-ui thread.
maybe try replaceing "this" with "OpenGLRenderer.this" inside your setLAS() method. It doesn't seem like it from the code you've posted but sometimes if you are making that call from a different object type it will try to pass in an OnClickListener (or whatever object your calling from) instead of an activity, thus the object has no context. Like I said doesn't seem like that is the case, but worth a shot.
Also where are you calling setLAS() from? perhaps post that section of your code too.
Edit:
Try modifying your setLAS() method to have a Context parameter and pass it in from your first activity, and just pass it along from the second activity to the async task instead of using the context from the second activity.

Android: Problems with ProgressDialog

Dear Android hackers,
I am trying to do the following in my Android App: When the User clicks on a list item in a ListActivity, a ProgressDialog should show up, some preloading should happen and after it's done, another Activity should be called using an intent.
I tried different approaches. What didn't work at all was using an Async Task. Apparently I cannot show, dismiss or edit my ProgressDialog out of the Async Task, if that Class is not a Member of my original Activity.
I switched to a simple Thread then, this is how I'm trying to do it:
dialog = ProgressDialog.show(BookmarkActivity.this, "", "Loading...",true);
new Thread() {
public void run() {
// do something
dialog.setMessage("Change Message...");
// do more
dialog.dismiss();
// ...
Intent intent = new Intent(BookmarkActivity.this, ThreadActivity.class);
BookmarkActivity.this.startActivity(intent);
}
}.start();
This works almost, but the changing of the dialog message does not. I'm getting errors saying something about "leaked windows". (I can post the complete log if it is needed).
My questions:
How can I use an Async Task for this, where the Class has it's own file?
How can I change the ProgressDialog out of my Thread or AsyncTask without causing an error for changing the UI in another thread?
Thanks in advance, Jan Oliver
Ok, with the help of Jason, I put together this Async Task. That works!
public class ThreadPreLoader extends AsyncTask<Object, String, Void> {
private Activity mActivity;
private ProgressDialog mDialog;
public ThreadPreLoader(Activity activity) {
mActivity = activity;
}
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage("Loading...");
mDialog.show();
}
protected Void doInBackground(Object... args) {
publishProgress("Loading something else..");
return null;
}
protected void onProgressUpdate(String... msg) {
mDialog.setMessage(msg[0]);
}
protected void onPostExecute(Void result) {
mDialog.dismiss();
}
}
Thanks again, Jason.
You should use an Async Task, Define a custom Async Task which receives the context (this) of the original activity.
Then keep that context for later Dismissing the dialog.
From your doInBackground() method you can call postProgress( int progress) which will cause onProgressUpdate() to be called in the async task , this method is on the UI thread so it will not cause cross thread errors.
Once doInBackground() is complete the method onComplete() will also be called on the UI thread, this is where you can use your saved context and dissmiss the dialog (context.dissmissDialog()
Take a look at Android's Handler class. If you create the Handler in the onCreate method of your activity, Runnables that are sent to the post method of the handler are then run on the UI thread of your activity:
Handler h;
protected void onCreate(Bundle bundle) {
h = new Handler;
new Thread() {
public void run() {
// your run code
h.post(new Runnable() { /* change dialog here */ });
}
}.start();
}
I'm not sure that's the best option, but worth a try.
In AsyncTask
You should do you work which need time in doInBackground and calling intent like things, that you need to do after this task should be in onPostExecute
public class ThreadPreLoader extends AsyncTask<Object, String, Void> {
private Activity mActivity;
private ProgressDialog mDialog;
public ThreadPreLoader(Activity activity) {
mActivity = activity;
}
protected void onPreExecute() {
mDialog = new ProgressDialog(mActivity);
mDialog.setMessage("Loading...");
mDialog.show();
}
protected Void doInBackground(Object... args) {
//do more
publishProgress("Loading something and reached somewhere..");
//do more
publishProgress("Loading something and reached somewhere..");
//do more
return null;
}
protected void onProgressUpdate(String msg) {
mDialog.setMessage(msg);
}
protected void onPostExecute() {
Intent intent = new Intent(BookmarkActivity.this, ThreadActivity.class);
BookmarkActivity.this.startActivity(intent);
mDialog.dismiss();
}
}

Categories

Resources