Is it possible to load a new activity in the background before switching the view to that activity?
For example, I would like to have a slash screen activity that gets called and displays a splash screen. While this splash screen is displayed, the next activity is loaded, and when it is done loading (when it's onCreate() is finished) then the splash screen activity ends, and the new activity is displayed.
I know another option would be to display the splash screen in the new activity, and use async task to load all the data before removing the splash image... but I am stuck on that approach as well. The activity first has to load a fair amount of data, and then it has to dynamically add GUI elements based on that data. Once the GUI is fully loaded, I then want to remove the splash screen. The problem is that I cannot touch the UI thread from doInBackground(). How do I create my activity behind a splash screen, if I cannot update the UI from doInBackground? I know that onProgressUpdate() can access the UI thread, but I can't figure out how to implement it.
Any ideas? Thank you!
Since you don't have an example of your code, I am not sure what kind of data you are loading and how you are dynamically configuring the UI based on the data, but I'll try to answer as much as I can. As a result, the answer may sound a little generic.
First, define 2 layout xml files - one for the splash screen and one for your "main" activity.
So you'll end up with /res/layout/splash_screen.xml and /res/layout/main.xml
In your onCreate(), load the splash_screen layout:
setContentView(R.layout.splash_screen);
In your async task, you will load up whatever data you need to do, and you will save all that data in some sort of data structure. I'm gonna use a LinkedList of String for example's sake.
private class MyTask extends AsyncTask<Uri, Integer, List<String>> {
#Override
protected List<String> doInBackground(Uri... params) {
List<String> myList = new LinkedList<String>();
// load up the list with data you are trying to get
myList.add("foo");
myList.add("bar");
// whatever you return here will be passed in as a parameter to the onPostExecute()
return myList;
}
#Override
protected void onPostExecute(List<String> result) {
setContentView(R.layout.main2);
// set layout elements with data that from the result
TextView myTextView = (TextView) findViewById(R.id.some_label);
myTextView.setText(result.get(0));
// or just call some function you defined in your activity instead
}
}
So basically, have 2 different layout file and use the splash_screen layout, and use the async task the load the data and save it in some data structure you define, and use that data structure to load your UI elements in onPostExecute() after using setContentView() to change back to your main layout.
One special note:
With the above code, it will show the splash screen again and reload all the data again if you rotate the screen. If you want to avoid that, you can use the onSaveInstanceState() and save whatever data you want in the outBundle and read that data back in onCreate's savedInstanceState bundle and load the UI elements back up. This will require a separate thread (or you can just search about it) if you wanted to know more about handling rotation.
One of the solution to solve your problem I can think about is to use one activity for displaying the splash screen and your content. Since you can call setContentView() method at any time (not only in onCreate() method) just define all the views you want in separate XML files and pass the relevant id to setContentView() when it's time to switch.
You could also use one layout with your views and splash screens and hide / unhide attributes. When your data is loading setVisibility to your splash screen to Visible while your root view remain unvisible. When finish loading - do in the opposite way.
Related
I have the following question/problem:
according to my knowledge with setContentView(...) we bring a layout into view.
So far so good but at which point will it be shown on the screen?
//quote
public class MainActivity extends Activity {
GlobalDataBase g_db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_user_layout);
//here will come the rest of the declaration and
//a database initialization which is a little time consuming
//example
g_db = (GlobalDataBase) getApplicationContext();
g_db.initialize();
}
// other subroutines and so on
} //point where the layout will be shown on the device
//endquote
Only after the last } ,which defines the end of the activity, the layout will be shown on the display.
Now my question is, if it is possible to force the layout be shown on the display directly after the setContentView(...)
In my program the loading of the database will take a lot of time depending on the internet speed. Sometimes it takes around 20 seconds where the screen is blank.
I want to show a message like "Database loading..." on the screen before I inizialize the database. But that doesnt work because the message is shown only at the end of the } which defines the end of the activity.
Any suggetions?
Thanks for your support
This is happening because you are using DB on main thread. If you do DB initialization on background thread then it will solve the problem.
You can use Running Android tasks in background threads to implement this DB initalization on background and communicate to main thread when query is complete with result if needed.
I'm trying to solve this, right now I have a Details Page activity (which loads dinamically from the DB depending on the item that was selected from a ListView). Each Details page can have between 1 and 5 images, which are downloaded from an online server. The problem I have is that the activity is not showing until the pictures were downloaded.
Basically the activity won't show until onCreate finishes. I'm using a thread to download the image so the UI doesnt freeze, My question is, where could I download and set the ImageView to the downlaoded bitmap so the user will see the activity and information straight away after clicking on the list item and then download and set the image after downloaded?.
I tried putting the thread on the onResume but I think it doesnt help either. What would be the best way?
Regards,
George
You need to implement an AsyncTask. Which executes on a background thread and prevents blocking of the main thread. You simply create a class that extends AsyncTask like below
EDIT - Yes, this will display your Activity even before the images get downloaded. You simply call the execute() method of your AsyncTask in onCreate() Have a look at the page on AsyncTasks above for a complete overview. It's really simple to implement you just need to be aware of configuration changes if your AsyncTask has not completed.
You might also want to look into caching your bitmaps in memory to prevent them from being unnecessarily downloaded again.
public class DownloadItemDetails extends AsyncTask<String, Void, ArrayList<Bitmap>{
protected ArrayList<Bitmap> doInBackground(String...params){
//Download each Bitmap here, and add them to a list to be displayed later
}
protected void onPostExecute(ArrayList<Bitmap> results){
//This method executes on the main thread, so after your downloads finish
//You can set your imageviews in your Details Page here
}
}
According to your curiosity to make user happy, I think you have to use Android Universal Image Loader library from Github. This library provide you asynchronous image loading, caching and displaying.
You can also use ShutterBug - Remote Image Loader from Github for same. It also fetch remote images and cache them. It is particularly suited for displaying remote images in lists, grids, and maps.
I'm developing an Android 3.1 application.
I want to execute an AsyncTask after activity is shown. I want to show something to user before execute AsyncTask.
I've read that it is not recommend to execute AsyncTask on onCreate().
Where I have to execute AsyncTask on onStart() or onResume()?
I want to left enough time to show activity before execute it.
onCreate(), onStart() and onResume() are lifecycle methods called by the operating system and shouldn't be called directly. You can however override them to have your code executed at these stages of the activities lifecycle:
However, if you want your AsyncTask to start after all of your Views have been inflated and drawn to the screen then you need to put the code in this:
toReturn.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
toReturn.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// asyncTask.execute();
}
});
In the above example toReturn is a view in your onCreate() method. It can be any view you like.
This pulls a ViewTreeObserver from the View and add's a listener to it which will be called when the view has finished being drawn to the screen. It's important you keep the "removeGlobalOnLayoutListener()` line in as this will stop the code firing every time the View is drawn.
Answer is in onResume()
I hade same requirement in my activity where i need to show some list with other buttons and images..
List were getting data from server so used AsyncTask for that..
But before that required to show empty listview and other part of the screen..
so first when it goes to onCreate() I set empty arraylist to listview's adapter then in onResume() call the Asynctask and in that task fill the ArrayList and call adapter.notifyDataSetChanged()
Then another problem occure..when i go to next activity and come back it always call the asynctask even if i dont require..
So had put some condition like if(arrayList.size()==0) then call asynctask else dont.
You can put yur code in the onWindowsFocusChanged method. You can use a thread inside it to manage the timer to start your specific asynctask.
Be aware that this would be performed each time your activity have the focus, not only the first time you launch your activity (I don't know if this could be a problem for you).
implement a View object and override the onDraw().
that way you'll know exactly when the first screen is visible to the user
How can I make loading page in android? I want it when my application starts.
Like the loading pages in games?
Could You help me with that?
There are loads of examples in the internet, search by "splash screen"
http://www.anddev.org/viewtopic.php?t=815
One way of doing it would be to set your contentview in onCreate() then do all the loading in an async task and when that finishes load the 'real' layout in the onPostExecute. Check out http://developer.android.com/reference/android/os/AsyncTask.html
That way you load your "real" layout when it actually finishes loading rather than picking a generic time to switch views. This is of course assuming that you want a loading page and not a splash screen. If you want that, checkout the other answers.
Here's a quick example... Say you have a file called Hello.java .. You'd set your content view to your loading layout in OnCreate() then call this class with something like.. new DownloadFilesTask().execute(); put this private class in it...
private class DownloadFilesTask extends AsyncTask<String, String, String> {
protected Long doInBackground(String... params) {
//grab stuff from the server, compute pi to 100000 places etc.
}
public void onPostExecute(String result) {
//this will now switch us to our real layout, you can now do all your fancy UI stuff! :)
setContentView(R.layout.reallayout);
}
}
Basically this is multithreading the easy way. onPostExecute runs back on the UI thread (your main one) while doInBackground does everything on a separate thread so no black screens! I'd really urge you not to use Runnable in this situation.
You mean a splash screen right? a simple google search would reveal a lot :)
This piece of work helped me to make a splash screen.
Rather than copy and pasting the code, try to understand how he uses Threading with a time limit to achieve this target.
I just tried a stupid approach and it crashed my app... Basically I have an activity that has three tabs (containing three activities). Each of the tabs gets its input from an xml file downloaded off the net. Everything is fine but when I start my app, it has download the xml file and there's a "wait" time for this.
I managed to get around this by adding a splash screen. It looks beautiful but the problem is when I click on the second tab, it still has to get the list off the net, so it looks ugly now... It waits before displaying the list. So what I did was design an AsyncTask that just downloads the xml file. In my main activity, I spawn two tasks initially and send the URL and Intent as parameters. And inside the acitivities that start inside the tabs, I use a wait(). Inside the AsyncTask, after it is done with the download, I notify the Intent using notify(). This crashed! Of course, I didn't expect it to work but just wanted to try :) Writing it so that I can either get a feedback as to why this failed or to prevent others from wasting their time on this...
Now, I am sure many face the problem of a "wait" time inside the tabs. How do I solve this? I am thinking of either dimming the screen and then displaying a series of toasts or display a progress indicator inside the tabs or pre-fetching the xml files... I don't have a clue on how these can be achieved... Any thoughts?
Credit: To Mark. Thanks!
Problem: Display a Progress Indicator when your application is busy doing some work
Approach:
public class Approach extends ListActivity {
ProgressDialog myProgressDialog = null;
ListView myList = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myList = getListView();
myProgressDialog = ProgressDialog.show(getParent(),
"Please wait...", "Doing extreme calculations...", true);
//Do some calculations
myProgressDialog.dismiss();
}
}
There are a few challenges (like updating some UI elements). You might want to spawn a different thread to do your calculations if needed.
Also, if you are interested in this, you might be interested in Matt's approach too: android-showing-indeterminate-progress-bar-in-tabhost-activity
ProgressDialog.
Or, make the tabs have android:visibility="gone" until such time as the data is ready, then make them visible. In the interim, show some sort of loading graphic (perhaps with a RotateAnimation applied).