Android setContentView suppressed by AsyncTask in onCreate - android

I want to show some message and a progress bar while my app initializes.
I need to insert some dictionaries of words into a SQLite database the first time my app is run. To do this I have an AsyncTask which opens my SQLiteOpenHelper and closes it again, just so the database initialization is done once.
private class AsyncDbInit extends AsyncTask<Void, Void, Void> {
private Context context;
private Intent intent;
public AsyncDbInit(Context context, Intent intent){
this.context = context;
this.intent = intent;
}
#Override
protected Void doInBackground(Void... params) {
DatabaseHandler db = new DatabaseHandler(this.context);
db.close();
return null;
}
#Override
protected void onPostExecute(Void param) {
context.startActivity(this.intent);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... params) {}
}
This AsyncTask is called in my onCreate() method, but I've also tried to run it from onStart() and onResume() without succes.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dispatcher);
... //some code finding the right intent
new AsyncDbInit(this, nextIntent).execute();
}
Somehow this last line, which calls the AsyncTask, stops my UI from showing up; the screen just stays blank until the AsyncTask is completed and the new activity is started.
When I comment that line out, the UI shows up just fine.
The only thing I can come up with is that the SQLiteOpenHelper somehow blocks the UiThread, but I couldn't find anything about that either.

In the AsyncTask we have some methods. Just like in doInBackground() we do the things we wants to be done in the background and there are two methods also whch are onPreExecute() and onPostExecute(). Create and progress dialog and show the dialog in onPreExecute() method and dismiss it in onPostExecute() method.

Try using AsynTask.executeOnExecutor() with the thread pool executor. If this works, it means something involved with loading your UI is also using an AsyncTask. AsyncTasks by default run sequentially on a single work thread and this can introduce contention. This serial execution is often what you want, but not always.
Does you UI use any libraries to load strings or other content? Can you provide your layout XML?

Related

How run two AsyncTasks in one Activity?

I have two Activitys (mainActivity & downloadActivity) and I have 2 AsyncTasks in downloadActivity
In downloadActivity first it execute getFileAsyncTask for reading a JSON file for adding some images and create a ListView from images, if user clicks on an image, the downloadAsyncTask was called and it starts to download something from the internet.
My problem is here: when the second AsyncTask is running I go back to mainActivity and comeback again to downloadActivity the first AsyncTask wasn't called until the downloadAsyncTask completed.
public class downloadActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
new getFileAsyncTask().execute();
...
}
private class getFileAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//fetch a json file from internet and add images in ListView
return null;
}
}
//there is a Base Adapter class
//if user clicks on an image it calls this downloadAsyncTask.execute()
private class downloadAsyncTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
//download the file
}
}
#Override
protected Void doInBackground(Void... unused) {
//download the file
}
}
note: I want to write something like shopping apps. For example, user can download file and surf into shop to see products .
If you want to run multiple AsyncTasks in parallel, you can call executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of execute() on your task. By default, AsyncTasks run in serial, first come first serve.
Be careful that the two threads do not interact on the same data, this can cause some strange and hard to trace errors.
you can make it in one asynk class that have two methodes first fetch json file wait response in doInBackground ... if it is ok call download file methode. Those methodes will return an httpResponse object
You can override onBackPressed function in activity and finish the current activity before go to previous activity. When again you come to downloadActivity it call it's oncreate method and call first AsynctTask.
Make one class task like:
Declare progress bar globally in main thread.
Now what you have to do is start one async task in main thread like:
public class myactivity extends Activity {
private ProgressDialog _dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.base_screen);
new abc().execute();
}
class abc extends AsyncTask(String,String,String) {
#Override
protected void onPreExecute() {
_dialog = new ProgressDialog(_ctx);
_dialog.setCancelable(false);
_dialog.setMessage("Loading");
_dialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
#Override
protected void onPostExecute(String result) {
// in post execute of this class you can run a new thread of your downaloder thread. and in post execute of last thread you have to dismiss the progess bar.
new download activity.execute();
}
}
}
}
}

onCreate sometimes running in background

I'm not quite sure how to debug the phenomenon I'm currently seeing in my Android application.
I have an Activity which is just doing some networking stuff (which needs to be done in background).
This activity is launched from a PreferencesFragment using an Intent.
When the user selects the preference item, the Intent is fired and the Activity is started (then it does the networking stuff and quits using finish()).
I created an AsyncTask to perform the networking actions in the background.
(I thought that onCreate will most probably run in the UI thread...)
But then, an exception occurred:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Did onCreate() already run in the background???
To test that, I moved the networking functions directly into onCreate().
This was working well...
... at least several times.
Suddenly, an exception was thrown:
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: android.os.NetworkOnMainThreadException
Moving the code back to the AsyncTask helped... for some time.
Does anyone know why this phenomenon might occur?
Are there scenarios when onCreate() runs in the UI thread and others when onCreate() runs in background?
My class is as simple as this:
public class ReregisterInDb extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
new ReregisterAsyncTask().execute(""); // solution 1
// solution 2
//GCMFunctions gcmFunctions = new GCMFunctions(getApplicationContext());
//gcmFunctions.registerInDb();
super.onCreate(savedInstanceState);
finish();
}
class ReregisterAsyncTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
GCMFunctions gcmFunctions = new GCMFunctions(getApplicationContext());
gcmFunctions.registerInDb();
return null;
}
}
}
try to move the call of the method finish() of the activity in the method onPostExecute of async task
You can't do anything before calling super.onCreate(...) put that right at the beginning as I've shown below. EDIT: Also, your use of getApplicationContext in the AsyncTask is likely causing an issue, try creating a global Context variable and initializing that in onCreate and see if that works.
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
new ReregisterAsyncTask().execute(""); // solution 1
finish();
}
class ReregisterAsyncTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
GCMFunctions gcmFunctions = new GCMFunctions(mContext);
gcmFunctions.registerInDb();
return null;
}
}
I finally found out the reason for this strange behavior.
I did not post the contents of the registerInDb() method.
In that method, there is a Toast:
Toast.makeText(context,
"Not currently registered with GCM. [...]",
Toast.LENGTH_LONG).show();
This message is causing the exceptions...
The solution is:
call the function in the UI thread so that the Toast messages work and
enter code heremove the AsyncTask to only cover the actual network code.
Sorry for not giving all the details. I did not think that the Toast message was the root cause.
I learned that you cannot have Toasts in AsyncTasks. The always have to run on the UI thread.

How to check if an activity is continuing

In my app, I am trying to run multiple photos through a photo editor (one at a time). I have it set up in a for-loop at the moment, but I feel like it is overloading the photo editor and not actually waiting until the current edit session is over, so I wanted to put a control statement in my for-loop to check if the session was still active.
Is this possible?
Easier to tell when the current is over than polling to see if it is still active. If you start it with startActivityForResult, your calling activity will be notified when the invoked activity ends.
Have a look at Starting Activities and Getting Results in the Activity docs for an example.
You might also want to consider running this in an async task. This will pull your heavy processing away from the UI thread. Async task let's you do progress updates as well.
http://developer.android.com/reference/android/os/AsyncTask.html
public class MainActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.logo_page);
// Call async task.
my_async as = new my_async(this);
as.execute();
}
--
my_async:
public class my_async extends AsyncTask<Object, Integer, String> {
private parentClass activity;
public my_async (parentClass activity) {
this.activity = activity;
}
#Override
protected String doInBackground(Object... arg0) {
// Do stuff
return "MyString";
}
protected void onPostExecute(String contents) {
activity.contents = contents;
}

AsyncTask onPostExecute not going back to previous activity

I have two AsyncTasks that I am using, one is called up after a dialog returns in the FragmentActivity and there is code after the .execute I call. The other .execute is called just in an if...else. The one called after another dialog returns, does what it is supposed to, it executes, on post execute it pops back the activity to the previous one and everything works.
The other the onPostExecute is never called. I did a break point in the doInBackground which executes and returns the null, just like the other one does but the onPostExecute never happens, is there some issue with having too many AsyncTasks in one FragementActivity, or too many calls to execute? I am stuck and hoping its something stupid I am just not seeing, so I am posting the code but I really cannot figure out why the onPostExecute never gets called in the AddEventWorker but does in the AddEventFromDialogWorker. The way I test the application it does so happen the AddEventFromDialogWorker gets called, works, and then anything to the AddEventWorker does not work (does do the doInBackground but not the onPostExecute).
Any ideas or avenues for me to try?
private class AddEventWorker extends AsyncTask<Void, Void, Void>{
protected void onPostExecute() {
getFragmentManager().popBackStack();
}
#Override
protected Void doInBackground(Void... params) {
mGoogleApi.addEvent(mSession, allGoogleAccounts.get(0).getGoogleCalendarName());
return null;
}
}
private class AddEventFromDialogWorker extends AsyncTask<String, Void, Void>{
protected void onPostExecute() {
Toast.makeText(mContext, "Event added to google calendar!", Toast.LENGTH_SHORT);
getFragmentManager().popBackStack();
}
#Override
protected Void doInBackground(String... params) {
mGoogleApi.addEvent(mSession, params[0]);
return null;
}
}
Your onPostExecute() method is never invoked because you are not overriding the base class' onPostExecute() method. The signature should be protected void onPostExecute(Void result). If you used #Override the compiler would have told you about this issue :)

Updating an Activity from an AsyncTask

So I'm an iOS developer learning android, and I'm having a difficult time understanding some things. Right now I have a datamanager class. In that class it has an AsyncTask to update the data. OnPreExecute I pop an activity to show it is updating. I understand I could use extras to pass initial information to the UpdateActivity. My problem is I'm not sure how to send new information in OnProgressUpdate. Here is my code widdled down:
private class myTask extends AsyncTask<Integer,String,Void>{
#Override
protected void onCancelled() {
super.onCancelled();
isUpdating = false;
}
#Override
protected Void doInBackground(Integer... params) {
//My BG Code
}
#Override
protected void onPostExecute(Void result) {
// TODO Remove updating view
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
Intent myIntent = new Intent(mContext,UpdateActivity.class);
mContext.startActivity(myIntent);
}
}
AsyncTask is designed to work best when nested in an Activity class.
What makes AsyncTask 'special' is that it isn't just a worker thread - instead it combines a worker thread which processes the code in doInBackground(...) with methods which run on the Activity's UI thread - onProgressUpdate(...) and onPostExecute(...) being the most commonly used.
By periodically calling updateProgress(...) from doInBackground(...), the onProgressUpdate(...) method is called allowing it to manipulate the Activity's UI elements (progress bar, text to show name of file being downloaded, etc etc).
In short, rather than firing your 'update' Activity from an AsyncTask, your update Activity itself should have a nested AsyncTask which it uses to process the update and publish progress to the UI.
You have two options:
1) Pass an instance of activity to your AsyncTask constructor in order to invoke some method on it:
new MyTask(this).execute();
So, you can do:
public MyTask (Activity activity) {
this.activity = activity;
}
public void onPostExecute(...) {
activity.someMethod();
}
2) Pass a Handler instance and send message from onPostExecute() to the activity.

Categories

Resources