I am using a TabActivity with 4 separate Activities - one for each tab.
One of the Activities is a ListView that has a custom ArrayAdapter.
The issue is that when I press the Tab to change to this view, the Activity loads the content in before the view changes, this appears as though nothing happens for a couple of seconds until the xml is loaded and parsed etc.
I have looked for an example but this is my first Android appllication and I am having difficulty in understanding the flow.
Can anyone point me to some code that will allow me to instantly change the view (I can inform user content is loading) while loading the content in the background thread
thank you
EDIT - I am porting code over from an existing iOS app - I wasn't able to better articulate the problem as I didn't realise how the UI thread could be blocked in this situation, and due to the complexity of the existing code and deadline I didn't want to change the structure too much.
I narrowed down the issue before I saw your code Jennifer but it is the solution I used so Ill mark yours as right.
here is what I used if it helps anyone else, I had to put the function I called to trigger the data load onto a background thread and then display the content when that thread had done its work
This class was declared within my
public class TableView extends ListActivity
Which was hard for me to get my head around having not done this before ;)
public class GetContentTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog pdialog;
#Override
protected void onPreExecute(){
super.onPreExecute();
pdialog = new ProgressDialog(TableView.this);
pdialog.setTitle(progressDialogTitle);
pdialog.setMessage(progressDialogMessage);
pdialog.show();
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
setUpAndLoadList(); // the function to display the list and fill it with content
pdialog.dismiss();
}
#Override
protected Void doInBackground(Void... params) {
doInitialLoad(); // The function to load any xml data from server
return null;
}
}
You can use a progress Dialog (can inform user content is loading)
ProgressDialog dialog;
private class XMLOperation extends AsyncTask<String, Void, String> {
/*
* (non-Javadoc)
*
* #see android.os.AsyncTask#onPreExecute()
*/
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
System.out.println("onPreExecute");
dialog= ProgressDialog.show(mContext, "", "Loading Content....");
dialog.setCancelable(false);
}
#Override
protected String doInBackground(String... urls) {
//do your Background task
}
protected void onPostExecute(String result) { //dismiss dialog
try {
if(dialog.isShowing()){
dialog.dismiss();
}
} catch (Exception exception) {
dialog.dismiss();
}
}
Use AsyncTask, or (possibly) a separate thread.
http://developer.android.com/reference/android/os/AsyncTask.html
I would also throw in my 2 cents and say don't use TabActivity. Just have your own buttons that look like tabs, but that's not really critical to this topic.
Related
I have an application that loads a dialog with some images specified in the dialog's XML layout. I've read a lot about using images in Android and being careful with the VM budget so I believe that any handling of images with the potential to take up a decent amount of memory should be handled off of the main thread. With that said I was wondering if it is wise to load an entire layout off of the UI thread using an ASyncTask. I have a working code but I couldn't find out if this was good practice through some Google searches. Here is the code below.
This is the case statement that triggers when the user presses a button to load the dialog.
case R.id.showDialog:
vibrator.vibrate(vibrateMilis);
mDialog = new Dialog(getActivity(), R.style.CustomDialog);
new LoadLayout().execute("");
break;
And here is the ASyncTask
private class LoadLayout extends AsyncTask<String, Void, String>
{
ProgressDialog progressDialog;
#Override
protected String doInBackground(String... params)
{
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setContentView(R.layout.dialog_layout);
mDialog.setCancelable(true);
return null;
}
#Override
protected void onPostExecute(String result)
{
progressDialog.cancel();
mDialog.show();
}
#Override
protected void onPreExecute()
{
progressDialog = new ProgressDialog(
getActivity());
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected void onProgressUpdate(Void... values)
{
// Do nothing
}
}
So this code works but the question I have is this. Is this considered good practice? It seems a bit hacky for my taste. I didn't come across this with multiple Google searches so that's why I'm a bit concerned. I mean if it was good practice it would've been documented somewhere right?
Thanks for any input.
Have you refer the android developer site. your approach is wrong. For more guidance please refer Vogella Documentation. Its a nice explaination of AsyncTask.
Also refer below example code for the AsyncTask.
// The definition of our task class
private class PostTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
displayProgressBar("Downloading...");
}
#Override
protected String doInBackground(String... params) {
String url=params[0];
// Dummy code
for (int i = 0; i <= 100; i += 5) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return "All Done!";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
updateProgressBar(values[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dismissProgressBar();
}
}
Hope it will help you a lot.
Enjoy Coding... :)
I think you are doing it in a wrong way , because :
First,when call method doInBackground() , It will in other thread , you can only change UI elements in main thread .
Second,show a dialog is not waste time,you can call it in onPreExecute() or onPostExecute(String result),and just do actions in doInBackground() that make user wait ,like get data from network or database.
You can not load whole Layout in background thread(pls note AsyncTask.postExecute() is executed on main thread). Because all the UI components should be modified from only Main Thread(also called UI thread). You can use the background thread just to gather the information that is needed for displaying UI.
I have a button, and when I clicked on it, I load other Activity, onCreate of this I call a method that fills a spinner with data from a Web Service.
Well, When I click at this button the screen stay "frozen" and then shows the Activity. So, I thought that it could be a good thing shows a progress dialog for user, and after gets the return of the Web Service, ends the progress dialog.
I tried use Handler, and now I'm trying to use AsyncTask, but, geting NullPointerException, because my program is filling spinner before web service get called.
private void fillSpinner(){
//runWebService();
new CallWebServiceAsyncTask().execute(null);
mAdapter = new PlanesAdapter(this, allPlanes);
mList.setAdapter(mAdapter);
}
class CallWebServiceAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(PlanesActivity.this);
progressDialog.setMessage("Loading...");
progressDialog.show();
}
#Override
protected Void doInBackground(Void... v) {
runWebService();
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
because my program is filling spinner before web service get called.
you should fill data after getting data in onPostExecute Method
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
mAdapter = new PlanesAdapter(this, allPlanes);
mList.setAdapter(mAdapter);
}
What #SamirMangroliya suggested is correct but you even need to know where you are going wrong. When you call an AsyncTask you are asking the application to do some actions in the background which will take place in the non-UI thread. Now when you call execute() on your AsyncTask object the application code written in the function doInBackground(Void... v) runs in background and your control returns to the next statement following the call to execute() [new CallWebServiceAsyncTask().execute(null)], which in your case is the action of filling the adapter values. These values are yet to be received from the webservice. The only place where you can be sure that your background action is completed is the function onPostExecute(Void result) where as suggested you can create your adapter.
I am on a dilemma on how to achieve "Creating a loading screen" on a AsyncTask mainly using progressDialog.
What I am doing is that I have a method which takes no inputs and just shows a textview.
private class DownloadFilesTask extends AsyncTask {
So what my method does is simply like 1 + 1 = 2 but in a more complex way of storing a giganormous string which then get shown on a textview.
So my question is how do I achieve the result of a progress dialog before this long load?
Android already has a progress dialog class built-in. I'd recommend using that, unless there's something about it that doesn't suit your needs.
private progressDialog pd;
public void runMethod(){
new doStuuff.execute();
}
private Class doStuff extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
//Everything in your code except for anything that is xml or relates with any view. Mostly calculations
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
//Your main background view code ends up falling here
pd.dismiss();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
//Your optional view and where it starts
pd = ProgressDialog.show(View_Book_As_Whole.this, "Loading", "Please wait...");
}
}
I was being too noob not to understand the concept but it is relatively easy once you understand it. onPreExecute() means that it runs before anything and it takes priority first then goes to doInBackground(), and then onPostExecute() it runs the final task. This all works in the background of the UI.
I need to make a transition screen, ou just put a dialog, because the app give a black screen when is creating the database.
I have google, and find some solutions for this. One of then, is just put a progress dialog when the database is been created.
My problem, and newbie question is, where do i put the progress dialog.
A -> BlackScreen -> B where A is the inicial menu, and B the other screen. I have tried to put the dialog on A and/or in B and dont work. So where can i put the code of the progress dialog, so it shows in the BlackScreen ?
Make use of Asyntask . put your database operation of creating database in asyntask in pre execute start dialog post execute cancel dialog in background perform database operation
http://developer.android.com/reference/android/os/AsyncTask.html
For that You have to use Async task :
class DownloadAsyncTask extends AsyncTask<String, String, Void>
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(Login.this, "", "Please Wait ...");
}
#Override
protected Void doInBackground(String... arg0) {
//Do your Task
}
#Override
protected void onProgressUpdate(String...values){
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
progressDialog.dismiss();
}
}
//Create the Object
DownloadAsyncTask downloadAsyncTask = new DownloadAsyncTask();
downloadAsyncTask.execute();
now till your work get's completed it shows progress dialog inside the doInbackground write your logic and onPostExecute dismiss the dialog and call Intent of other Activity.
I have developed an android application .In that application getting information from web and displayed in the screen.At the time of getting information i want to load a progress dialog to the screen after getting the information i want dismiss the dialog
Please any one help me how to do this with some sample code
Thanks in advance
You need to implement an AsyncTask.
Example:
class YourAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
//show your dialog here
progressDialog = ProgressDialog.show(this, "title", "message", true, false)
}
#Override
protected Void doInBackground(Void... params) {
//make your request here - it will run in a different thread
return null;
}
#Override
protected void onPostExecute(Void result) {
//hide your dialog here
progressDialog.dismiss();
}
}
Then you just have to call
new YourAsyncTask().execute();
You can read more about AsyncTask here: http://developer.android.com/reference/android/os/AsyncTask.html
The point is, you should use two different thread 1st is UI thread, 2nd is "loading data thread"
from the 2nd thread you are to post the process state to the 1st thread, for example: still working or 50% is done
use this to post data