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.
Related
There's a "download" button in each listview item. While the button is clicked, it will start a worker thread to down files. And at the same time, the button changed to progressbar and showing the progress rate.
So please show me some proper ways.
Use an AsyncTask since it has special methods for communicating with the main (UI) thread despite being asynchronous.
Here is an example:
http://android-er.blogspot.com/2010/11/progressbar-running-in-asynctask.html
Something like this:
public class DownloadTask extends AsyncTask<Void, Void, Boolean> {
protected void onPreExecute() {
ProgressDialog() progress = new ProgressDialog(context);
progress.setMessage("Loading ...");
progress.show();
}
protected Boolean doInBackground(Void... arg0) {
// Do work
return true;
}
protected void onPostExecute(Boolean result) {
progress.dismiss();
}
}
This should be nested in your activity class and executed like this:
new DownloadTask().execute();
You will likely need to adjust the asynctask to fit your needs but this will get you started.
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.
Goal: Have a ProgressDialog which shows "Loading..." until next Activity is completely loaded and shown on screen.
Tried with ProgressDialog context and activity set to originating Activity. Also tried with getApplicationContext() and getParentContext(). Exceptions on the last two approaches. Need to do this as destination Activity is slow to render due to non-simple Layout file. (Cannot fix that right now due to organizational issues.) Turns out the destination Activity takes 1-2 seconds to OnCreate and then screen goes black for up to 5+ seconds then it paints. The rendering is just slow. Did review with Hierarchy Viewer and see lots of red balls but can't fix now.
Read up on some related but haven't found a fix. E.g. What's the difference between the various methods to get a Context?
E.g. both of these crash. Using the "this" of source Activity doesn't work either.
// Context parentContext = this.getParent().getBaseContext();
Context parentContext = this.getApplicationContext();
ProgressDialogMenuable theProgressDialog = new ProgressDialogMenuable(parentContext,this);
theProgressDialog.setTitle("yeeha");
theProgressDialog.setMessage("weewah");
theProgressDialog.setIndeterminate(true);
theProgressDialog.setCancelable(true);
theProgressDialog.show();
Also, oddly, nothing happens when I do this:
theProgressDialog.show();
ActivityHelper.changeActivity(this, v, InsMyHoldingsActivity.class, extraMap, -1, -1);
User clicks button to show next activity but the ProgressDialog conflicts with the Activity launch and nothing actually happens other than the button becoming yellow ontouch. Button below works. removing ProgressDialog creation and it works. No console messages logged. A little offputting to the developer for sure.
You can show a progress dialog like this -
Define this
private ProgressDialog pd = null;
in your activity class
Put this in your onCreate (Dont setContentView directly here)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.pd = ProgressDialog.show(this, "Fancy App",
"Loading...Please wait...", true, false);
// Start a new thread that will download all the data
new IAmABackgroundTask().execute();
}
// Background heavy lifting
class IAmABackgroundTask extends
AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
// showDialog(AUTHORIZING_DIALOG);
}
#Override
protected void onPostExecute(Boolean result) {
// Pass the result data back to the main activity
ActivityName.this.data = result;
if (ActivityName.this.pd != null) {
ActivityName.this.pd.dismiss();
}
setContentView(R.layout.main);
}
#Override
protected Boolean doInBackground(String... params) {
//Do all your slow tasks here but dont set anything on UI
//ALL ui activities on the main thread
return true;
}
}
Also go through this :http://developer.android.com/training/improving-layouts/index.html for optimizing layout performance.
Also Use Traceview to look for bottlenecks
There is two ways to
First approach To use Async Task
If you are doing heavy tasks eg loading data from server or parsing xml in that case use AsynTask<> If you want to call ActivityB from ActivityA then
*step-1*create a AsyncTask class. write all background tasks inside doBackground() method and after completion of task you want to call an activity that code write inside onPostExecute() post execute method
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.view.View;
public class LoadingDataFromServer extends AsyncTask {
Context currentContext = null;
boolean isCancelled = false;
public LoadingDataFromServer(Context context) {
currentContext = context;
}
#Override
protected void onPreExecute() {
if (DashboardActivity.progressBarLayout != null) {
DashboardActivity.progressBarLayout.setVisibility(View.VISIBLE);
// Log.i(TAG,".....Now make progress bar visible.....");
}
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
// do background processing
try {
// do background tasks eg sever communication
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object result) {
// TODO Auto-generated method stub
// progressDialog.dismiss();
// call second Activity
Intent i = new Intent(currentContext, com.ActvityB.class);
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
isCancelled = true;
super.onCancelled();
}
}
step-2 In the activity fro where you want to jump to new activity (eg in ActivityA) call the execute() of AsynTask
new LoadingDataFromServer(context).execute(null);
Second approach
First show progress dialog.
create a thread to do all background tasks. when the thread completes the task then cancel the progress dialog and call the next activity
or
when thread complets the task then call next activity pass this object (progress dialog) and inside that new activity dismiss this dialog.
Here is my code that can help.
In this, I'm only posting the first method of AsyncTask i.e onPreExecute.
User_AsyncTask extends AsyncTask:
public class User_AsyncTask extends AsyncTask<String, String, String>
{
String response = "";
#Override
protected void onPreExecute()
{
try
{
if (progressDialog != null)
progressDialog.cancel();
}
catch (Exception e)
{
}
progressDialog = ProgressDialog.show(DisplayDetails.this, "", "Please wait...", true, true);
progressDialog.setCancelable(false);
progressDialog.show();
}
When a button is clicked I'm calling the async class in a function and I need to show progressDialog until it runs the displaylist function. But it shows up only after the function finished running and closes immediately. Please help me what am I doing wrong here.
public class FilterAsyncTask extends AsyncTask<Void, Void, Void> {
ProgressDialog dispProgress;
#Override
protected void onPreExecute()
{
dispProgress = ProgressDialog.show(Filter.this, "Please wait...",
"Loading...", true, true);
}
protected Void doInBackground(Void... params) {
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
MerchantsActivity.displayList();
dispProgress.cancel();
finish();
}
}
Your AsyncTask will complete immediately because you do exactly nothing in doInBackground()! That's where your long-running background non-UI code is supposed to go...
I would recommend you not to use the static ProgressDialog#show method. Rather donew ProgressDialog() and initialize it accordingly and finally call show(). I have never used the static method and do not know how it works, but I have used the other option. Furthermore the static method seems to have no available documentation.
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.