I am working on android app and i have a images slider in my app,now i want to when i click on my slider image,the images are display in another activity but it takes a little time while to open,now i want to implement and add a loading progress bar when display the image in another activity,can anyone tell me how i can implement progress bar when i click my image slider and when open another activity it's start progressbar and when images are display it's dimiss?any help,idea and sugession will be much appreciated,Thanks in advance.
This is my activity when i click on my image and anothe activity open:
iv_openimage = (ImageView) findViewById(R.id.iv_openimage);
iv_openimage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(VarientDetails.this,ImageSwitcher.class);
intent.putExtra("imageurls", imageurls);
Log.d("CMH", "images url = " + imageurls);
startActivity(intent);
}
});
and this is my imageswitcher activity were i can display my images:
public class ImageSwitcher extends Activity {
ImageView iv_getimage;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.imageswitcher);
iv_getimage = (ImageView) findViewById(R.id.imageView1);
ArrayList<String> resultArray = getIntent().getStringArrayListExtra("imageurls");
Log.d("CMH imgswtchr", "images url = " + resultArray);
Picasso.with(getBaseContext()).load(resultArray.get(0))
.into(iv_getimage);
}
}
What you want to do is put the resource intensive tasks in a so called AsyncTask. This AsyncTask runs on a different thread then the UI thread. Put it can do UI operations in it's onPostExecute();
So what you want is to do something along the lines of:
start activity
set progressbar visible
start asynctask
In the AsyncTask:
execute image task that takes up time
hide progressbar
For more info about AsyncTask you can go here: http://developer.android.com/reference/android/os/AsyncTask.html
Also, the reason that your current implementation isn't optimal is because it all runs on the same thread. This makes the UI thread unavailable at a certain time. This is bad practice, and gives the user a bad experience. So I'd always recommend using an AsyncTask for operations like this. While it is possible to show the progressbar before and after the task is done, the task would still lock the UI thread.
Edit
As requested, here is something I'd do in your situation:
I'd first create an inner class that extends AsyncTask like this
private class ImageLoadTask extends AsyncTask<String, Param, String>
{
#Override
protected String doInBackground(String... params)
{
//do something to retrieve the images
}
#Override
protected void onPostExecute(String result)
{
//hide the progressbar
}
}
Then in the Activity itself to start this AsyncTask simply do:
progressBar.setVisibility(View.Visible);
ImageLoadTask imgTask = new ImageLoadTask();
imgTask.execute("parameter");
Related
I need to process some data when the user click the button in one activity, so the screen looks like the app stops for 2-3 seconds. It isn't a lot but I want to give the user information that everything is ok and IMO the best way will be the progressbar which is visible only when data are processed.
I found the code of ProgressBar and it looks like this:
<ProgressBar
android:id="#+id/loadingdata_progress"
style="?android:attr/progressBarStyle"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBottom="#+id/fin2_note"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="invisible" />
and inserted it on the middle of my layout.
And to try if the progressbar works, I put this code
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
into onCreate method and everything looks fine.
Then I recreated the code to show this progressbar only if the data is processed.
After click the user invoke this method
public void fin2_clickOnFinalization(View v)
{
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
// code where data is processing
loadingimage.setVisibility(View.INVISIBLE);
}
and nothing appear on the screen. I don't know where is the mistake. If I found the progress bar by id, It's strange for me that I can control it in onCreate method but in onclick method it's out of my control.
Your UI thread cannot show progress bar cause it is busy due to your data processing. Try to use this kind of code :
public void fin2_clickOnFinalization(View v) {
new YourAsyncTask().execute();
}
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... args) {
// code where data is processing
return null;
}
#Override
protected void onPostExecute(Void result) {
loadingimage.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
loadingimage.setVisibility(View.VISIBLE);
}
}
EDIT:
AsyncTask let you run code in separate thread and make app more responsive, just put time-consuming code inside doInBackground.
You're not giving the UI time to refresh. Your "data processing" code is running on the UI thread, blocking any visible changes. By the time the system gets control to refresh the display, you've already set it back to invisible.
To fix this, move your processing code to a separate thread or AsyncTask. Then you can set the progress bar to visible, start the task, and have it turn itself invisible once it's done.
I'd recommend AsyncTask for this purpose about 90% of the time on Android, since it comes stock with useful callbacks. The developer guide for it(in the Javadoc linked above) is pretty explicit, and outlines all the steps you need to take.
AsyncTask is too heavily-weighted for such task.
A better much solution
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
Or even simpler (does essentially the same thing as solution above)
runOnUiThread(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
You can try to create a global ProgressDialog not in the layout but in your activity like:
public class MyActivity {
ProgressDialog progress = null;
protected void onCreate(...) {
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setTitle("Progress");
}
public void fin2_clickOnFinalization(View v)
{
progress.show();
// code where data is processing
progress.dismiss();
}
}
Hope i it helps
I have an activity 'Activity1' and also another activity named 'Activity2'. The 'Activity2' is loaded upon clicking a button in 'Activity1'. I wanted to display the progress dialog until the new activity is loaded . Can you please show me the code to do this
Display the progress dialog in Activity2's onCreate method, then do all the time-consuming loading in an AsyncTask. In the AsyncTask's onPostExecute() method, dismiss the progress dialog.
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.
yes by using AsynTask<> you can get your result
in OnPreExecute Show your Progress dialog,in OndoInBackground run your activity,in onPostExecute remove your dialog
get the idea Get Concept
The other answers (using AsynTask) are correct, but the question you need to figure out is what is causing your delay. Is it something happening on the back end of Activity1 or something happening on the front end Activity2. If you're doing some processing before starting Activity2 then follow the advice of Last Warrior or Ted Hopp... if you have some lengthy loading process in Activity2 then you'll need to initiate the progress dialog as the first thing that happens onCreate of Activity2 and then move whatever is taking up processing resources off into an AsynTask (or just another thread) there.
I guess in the unlikely event that both A1 and A2 are requiring extra time on the end and front of each respectively, you'll need to open and close a progress dialog... I don't think there's a way to keep one open in the foreground as you move from one activity to the other.
you can do it through AsyncTAsk. Which code taking time for executing just put that into
doInBackground()
override method of asyncTask and
startActivity(intent) ----just put into onPostExcute()
protected class InitTask extends AsyncTask<Context, Integer, Integer> {
#Override protected Integer onPreExcute( Context... params ) {
//assign progressbar here
}
#Override protected Integer doInBackground( Context... params ) {
//do all the stuffs here
return super.doInBackground( params )
} #Override protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//update progress bar
}
#Override protected void onPostExecute( Integer result ) {
super.onPostExecute(result);
//start activity here
}
}
I recently discovered that since my app is pulling so much data from a few URLs, it takes about 3-7 seconds for it to load the main layout. So, I made a layout called 'loading' to display, which is just simply a TextView that states "Please wait while data is being collected...". However, when I run my app, it won't display the 'loading' layout. It simply goes black for a while, like it used to before, and then go to the main layout. I tried cleaning the project too, and it still does this. Here's a portion of my Main.java:
#Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.loading);
populateArray();
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set up click listeners for all buttons
View v1 = findViewById(R.id.continueButton);
v1.setOnClickListener(this);
View v2 = findViewById(R.id.colorCheck);
v2.setOnClickListener(this);
View v3 = findViewById(R.id.terms);
v3.setOnClickListener(this);
}
populateArray(); is the method that is pulling all the information of the internet. So, I figured, "Why not tell it to set the content view immediately to 'loading', have it run populateArray();, then display the main layout?" Obviously, I must be missing something here. Any ideas?
==========================================================================
EDIT: I tried using AsyncTask, but I'm getting a force close. I'm also getting a warning saying the AsyncTask class is never used. Here's my code:
P.S. ProgressDialog dialog; is a global definition.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialog = ProgressDialog.show(this, "",
"Please wait while data is collected...", true);
// Set up click listeners for all buttons
View v1 = findViewById(R.id.continueButton);
v1.setOnClickListener(this);
View v2 = findViewById(R.id.colorCheck);
v2.setOnClickListener(this);
View v3 = findViewById(R.id.terms);
v3.setOnClickListener(this);
}
And...
private class LoadData extends AsyncTask <String[][], String, String> {
#Override
protected String doInBackground(String[][]... voidThisArray) {
String voidThisString = null;
populateArray();
return voidThisString;
}
#Override
protected void onPostExecute(String voidThisString) {
setContentView(R.layout.main);
dialog.dismiss();
}
}
I would give you the LogCat for the force close but for some reason the LogCat isn't displaying anything...
You want to use an AsyncTask to first: create a ProgressDialog that will display the loading message. Then the AsyncTask will work in the background collecting all of the data.
Hope that helps.
private class Task extends AsyncTask<Void,Integer, Void> {
private ProgressDialog dia;
#Override protected void onPreExecute() {
dia = new ProgressDialog(MyContext.this);
dia.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dia.setMessage("Loading. Please wait...");
dia.setCancelable(false);
dia.show();
// Set up preserver download stuff
}
#Override protected Void doInBackground(Void... voids) {
// perform server download stuff
}
#Override public void onProgressUpdate(Integer... prog) {
if (prog == null)
return;
dia.setProgress(prog[0]);
}
#Override protected void onPostExecute(Void voids) {
// Do any post op stuff
dia.cancel();
}
}
You should see this page for information about threading. Basically if your application is going to do any long running operation, you want it in a thread. Your UI is locking up because your performing this operation on your UI thread.
As far as progress updates, I personally use a ProgressDialog to show when something is happening, although you could build a custom view to indicate this.
Look at AsyncTask and execute
populateArray();
in doInBackground method of AsyncTask.
And call
setContentView
only once you can show loading by using onPreExecute and onPostExecute method of AsyncTask
I have a ListActivity which launches another Activity based on the list selection. This second Activity needs to load a fair bit of data from the internet and as such there is a noticeable delay between when the user clicks on an item and when the Activity displays.
This is a problem because I currently have no way to indicate to the user that their click is being processed (even just changing the colour of the selected list item would be sufficient but I can't find a good way to do that). Ideally I'd be able to display an indeterminate ProgressDialog while the second Activity is loading.
I've tried a few different approaches for this but nothing seems to work as desired.
I've tried the following:
Retrieving the serializable data (not all of it but some part) in an AsyncTask in the first Activity and passing it as an extra to the second. This didn't really work well as a ProgressDialog I created in onPreExecute() didn't display immediately (it seems delayed by the processing done in doInBackground() for some reason.)
Here is the code for that:
AsyncTask<String, Void, String> read = new AsyncTask<String, Void, String>() {
Dialog progress;
#Override
protected void onPreExecute() {
progress = ProgressDialog.show(SearchActivity.this,
"Loading data", "Please wait...");
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
DatasetReader reader = new DatasetReader();
reader.setFundID(params[0]);
reader.addDatsets(FundProfile.datasets);
reader.populate();
return reader.toString();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progress.dismiss();
}
};
read.execute(selectedItem.getUniqueID());
try {
action = new Intent(SearchActivity.this, FundProfile.class);
action.putExtra("data", read.get());
} catch(Exception ex) {
ex.printStackTrace();
}
In the second Activity's onCreate() method (this does not work at all):
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setProgressBarVisibility(true);
Here is the onCreate() method for the second approach:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitleColor(Color.WHITE);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setProgressBarVisibility(true);
try {
setContentView(R.layout.fund_profile);
// init some data
setProgressBarVisibility(false);
} catch(Exception ex) {
FundProfile.this.finish();
}
}
If you have long operations you should not be doing them in onCreate in any case as this will freeze the UI (whether or not the activity is displayed). The UI set by onCreate will not appear and the UI will be unresponsive until after the onCreate call finishes.
It seems you can start your second activity and display a progress bar (or requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);), then start an ASyncTask which will be responsible for updating your UI once data has been retrieved.
Adam,
It sounds like you are looking for the Indeterminate Progress bar: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.html
You can display this while you are loading your second Activity then set the visibility to false once the second Activity has loaded its data.
Move creating the Intent -- and really anything you need to do after the AsyncTask completes -- into onPostExecute:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progress.dismiss();
Intent action = new Intent(SearchActivity.this, FundProfile.class);
action.putExtra("data", result);
// ... do more here
}
The problem is that AsyncTask.get() blocks until the task is completed. So in the code above, the UI thread is blocked and the ProgressDialog is never given a chance to appear until the task completes.
I'm displaying some data by using SQLite. When I click on one button data come from database. It takes some time. At that time the screen is black. At that time I want to display the rotating spinner before the data dispay. Any ideas?
Android provides a ProgressDialog for accomplishing what you want.
First i would like to suggest to have a look at AsyncTask page, so that you will come to know about the AsyncTask exactly.
Now, Implement AsyncTask as given below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new performBackgroundTask().execute();
}
private class performBackgroundTask extends AsyncTask <Void, Void, Void>
{
private ProgressDialog Dialog = new ProgressDialog(main.this);
protected void onPreExecute()
{
Dialog.setMessage(getString("Please wait..."));
Dialog.show();
}
protected void onPostExecute(Void unused)
{
Dialog.dismiss();
// displaying all the fetched data
}
#Override
protected Void doInBackground(Void... params)
{
// implement long-running task here i.e. select query/fetch data from table
// fetch data from SQLite table/database
return null;
}
}
Enjoy !!!
You should not execute long running tasks in UI thread as this blocks the UI redraw and makes app look unresponsive.
Use AsyncTask to execute long running tasks in background, while still updating the screen.
You can look at the standard music picker as one example of how to do this:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java
In addition to the whole "queries must be done off the main UI thread," this shows an indeterminant progress while first loading its data, fading to the list once the data is available. The function to start the query is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#581
And to do the switch is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#569
The layout has the list view put in a frame layout with another container holding the progress indicator and label. The visibility of these is changed to control whether the list or progress indicator are shown:
https://android.googlesource.com/platform/packages/apps/Music/+/master/res/layout/music_picker.xml