I'm encountering the following problem:
I created a waiting spinner using Dialog like this
final Dialog progDialog = new Dialog(context);
progDialog.setContentView(R.layout.progress_dialog);
progDialog.setTitle("Calculating...");
progDialog.setCancelable(false);
progDialog.setCanceledOnTouchOutside(false);
WindowManager.LayoutParams lp = progDialog.getWindow().getAttributes();
lp.dimAmount = 0.7f;
progDialog.show();
Afterwards, I'm calculating something in the background
for()...
for()...
After the calculation is finished, I want to dismiss my dialog with
progDialog.dismiss();
However, this results in my dialog never being shown at all. When I remove the last line, the dialog is shown but is never dismissed. Is there a fix to it?
You better try with AsyncTask
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progDialog;
public YourAsyncTask(MyMainActivity activity) {
progDialog = new ProgressDialog(activity);
}
#Override
protected void onPreExecute() {
progDialog.setContentView(R.layout.progress_dialog);
progDialog.setTitle("Calculating...");
progDialog.setCancelable(false);
progDialog.setCanceledOnTouchOutside(false);
progDialog.show();
}
#Override
protected Void doInBackground(Void... args) {
// do background work here
return null;
}
#Override
protected void onPostExecute(Void result) {
// do UI work here
if (progDialog.isShowing()) {
progDialog.dismiss();
}
}
}
Use the above code in your Main Activity. And, do your calculation part in doInBackground.
To set timer for your computation try below code:
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progDialog.cancel();
}
};
Handler pdCanceller = new Handler();
pdCanceller.postDelayed(progressRunnable, 3000);
Adding show/hide:
progDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
theLayout.setVisibility(View.GONE);
}
});
Update:
ProgressDialog class was deprecated as of API 26
Related
Basically I have a loading splash screen which will be executed when button was clicked:
public void onClick(View v) {
// Load the loading splash screen
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
});
And in the LoadingScreen class:
public class LoadingScreen extends Activity{
//A ProgressDialog object
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Initialize a LoadViewTask object and call the execute() method
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in separate thread
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(LoadingScreen.this,"Getting routes...",
"Loading data, please wait...", false, false);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(750);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
//set the current progress of the progress dialog
progressDialog.setProgress(values[0]);
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
}
}
}
With these codes, the loading splash screen did came out. But I wonder is there any other way to show only the pop out dialogue for loading progress bar which on top on my previous screen?
Let's say my previous screen was event details. Then when user selected the button, only the dialogue box with loading progress bar will be shown instead of a new intent with a dialogue box.
Any ideas? Thanks in advance.
EDIT
public void onClick(View v) {
// Load the loading splash screen
new LoadViewTask().execute();
ENeighbourhoodActivity.tvDirection.setText("");
eventModel.setEventX(String.valueOf(eventModel.getEventX()));
eventModel.setEventY(String.valueOf(eventModel.getEventY()));
new GetEventDirectionAsyncTask(new GetEventDirectionAsyncTask.OnRoutineFinished() {
public void onFinish() {
//Hide the callout and plot user location marker
ENeighbourhoodActivity.callout.hide();
EventController.getUserLocation(context);
getActivity().finish();
}
}).execute(eventModel);
}
});
public class GetRegisteredEventAsyncTask extends
AsyncTask<String, Integer, Double> {
static EventController eventCtrl = new EventController();
public static ArrayList<Event> upcomingModel = new ArrayList<Event>();
public static ArrayList<Event> pastModel = new ArrayList<Event>();
public interface OnRoutineFinished { // interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public GetRegisteredEventAsyncTask(OnRoutineFinished callback) {
mCallbacks = callback;
}
public GetRegisteredEventAsyncTask() {
} // empty constructor to maintain compatibility
#Override
protected Double doInBackground(String... params) {
try {
upcomingModel = eventCtrl.getRegisteredUpcomingEvent(params[0]);
pastModel = eventCtrl.getRegisteredPastEvent(params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
if (mCallbacks != null)
mCallbacks.onFinish(); // call interface on finish
}
protected void onProgressUpdate(Integer... progress) {
}
}
In your onClick() method you could write something like:
new LoadViewTask().execute();
and the progress dialog will be shown in that page itself.
what are you doing man, just call your AsyncTask not the intent
public void onClick(View v)
{
new LoadViewTask().execute();
}
});
do your intent in postExecute
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
//START YOUR ACTIVITY HERE
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
Must read the documentation of AsynTask
I am well aware that blocking the UI is not a good idea in general but there are some scenarios where my app simply cannot do any other work until some long running operations (e.g. loading data from a server) are complete.
Assume the user clicks the "Load Data" button. To indicate that no UI interaction is possible until the data is loaded I would like to grey out the screen and show some kind of activity indicator. This is no problem at all, I simply overlay the screen with a new Fragment.
The question is: How can I present this overlay fragment?
public void onLoadDataClick() {
// grey out the screen by simple showing a new Fragment
showActivityIndicatorOverlay();
// Start the long running opeartion
doVeryMuchWork();
dismissActivityIndicatorOverlay();
}
public void showActivityIndicatorOverlay() {
FragmentTransaction ft = context.getSupportFragmentManager().beginTransaction();
ActivityIndicatorOverlayFragment overlayFragment = ActivityIndicatorOverlayFragment.newInstance("Loading Data");
overlayFragment.show(ft, "activityIndicator");
}
This does NOT work. The overlay does not show up. If I remove dismissActivityIndicatorOverlay() the overlay shows up after the long running operation completed. This is not too suprising: I assume that the showing the new fragment is handeled at the end of the current run-loop or at the start of the next loop. Of course the long running operation has to complete before the run-loop ends and thus the overlay is displayed too late...
The obvious solution is of course to run the operation in a background thread using an AsyncTask:
public void onLoadDataClick() {
LoadDataTask loadTask = new LoadDataTask();
loadTask.execute();
}
private class LoadDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
showActivityIndicatorOverlay();
}
#Override
protected Void doInBackground(Void... params) {
doVeryMuchWork();
}
#Override
protected void onPostExecute() {
dismissActivityIndicatorOverlay();
}
}
I was surprised, that this solution doesn't work either. It behaves exactly like the first approach: The overlay does not appear. When onPostExecute() is removed the overlay appears after the operation is complete. the Why is that?
What is the correct solution to present such an activity indicator?
I'd suggest the use of a ProgessDialog.
Declare a ProgressDialog as an instance variable. Something like : ProgressDialog pDialog;
then inside onCreate() :
pDialog = new ProgressDialog(this);
//The next two methods will ensure that the user is unable to
//cancel the Progress Dialog unless you explicitly
//do so by calling `pDialog.dismiss();`
pDialog.setCancelable(false);
pDialog.setCanceledOnTouchOutside(false);
Modify AsyncTask somewhat like this :
private class LoadDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
pDialog.setMessage("Loading Data.. Please Wait.");
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
doVeryMuchWork();
}
#Override
protected void onPostExecute() {
pDialog.dismiss();
}
}
A ProgressDialog is very much the canonical solution for these cases...
private class LoadDataTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog mProgress;
#Override
protected void onPreExecute() {
mProgress = new ProgressDialog(context);
mProgress.setTitle("So much to do");
mProgress.setMessage("Doing very much work");
mProgress.setIndeterminate(true);
mProgress.setCancelable(false);
mProgress.show();
}
#Override
protected Void doInBackground(Void... params) {
doVeryMuchWork();
}
#Override
protected void onPostExecute() {
mProgress.dismiss();
}
}
As for your attempted solutions, the first one does not work for the very reasons you state. The second should, though.
You can do something like this, if you're not doing heavy stuff precisely on setContentView(R.layout.main)
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
handler = new Handler();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
//Do some heavy stuff
return null;
}
#Override
public void onPostExecute(Void result){
handler.post(new Runnable(){
#Override
public void run(){
setContentView(R.layout.main);
}
});
}
}.execute();
}
OR you can use progress dialog
private class LongTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog pd;
Context context;
public LongTask(Context c)
{
this.context = c;
}
#Override
protected void onPreExecute() {
pd = new ProgressDialog(context);
pd.setTitle("Please wait...!");
pd.setMessage("Loding the information");
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
}
#Override
protected Void doInBackground(Void... params) {
// do your heavy tasks here
}
#Override
protected void onPostExecute() {
if (pd.isShowing())
pd.dismiss();
}
}
Call AsyncTask like this
new LongTask(your_activity.this).execute();
In my android app, i am doing time consuming task extending AsyncTask, and want to display the progress in Toast messages. Toast messages are also displayed onPre() and onPost().
I am able to display Toast messages onPre() & onPost() but not able to show onProgressUpdate(Integer... progress).
Following is my code...
public class MainClass extends Activity {
public void Start(View view) {
DemoTasks runner = new DemoTasks(this);
runner.execute("Start");
}
private class DemoTasks extends AsyncTask<String, Integer, Integer> {
private Context context;
public DemoTasks(Context context){
this.context = context;
}
#Override
protected Integer doInBackground(String... params) {
try {
publishProgress(0);
doWork();
Thread.sleep(5000L);
publishProgress(100);
} catch (Exception localException) {
Log.d("POST", localException.getMessage());
}
return 100;
}
#Override
protected void onPostExecute(Integer result) {
Toast.makeText(context, "post", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPreExecute() {
Toast.makeText(context, "pre", Toast.LENGTH_SHORT).show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
Toast.makeText(context, "progress-" + progress, Toast.LENGTH_SHORT).show();
}
}
}
Also in my doInBackgroud(String...params) ...Thread.sleep is also not working.
As soon as onPre() gets executed, onPost() also executes after that!!!!
You can try this,
showProgress ();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
dialog.cancel();
Intent i=new Intent(getApplicationContext(),Main.class);
startActivity(i);
finish();
}
}, 3000); //number of seconds
private ProgressDialog dialog;
public void showProgress () {
dialog = new ProgressDialog(this);
dialog.setCancelable(true);
dialog.setMessage("Please wait");
dialog.show();}
Bascially,you can access the UI on any method, even In doinBackground you can access the UI using runOnUIthread.
here is one AsyncTask Example. This will show a peogress dialog while executing the task.
private class LoginProcessing extends AsyncTask<Object, Void, Void> {
private LoginCredentials myLoginCredentials;
private ProgressDialog progressDialog;
public LoginProcessing(LoginCredentials Credentials) {
super();
myLoginCredentials=Credentials;
progressDialog.setMax(100);
progressDialog.setMessage("Please Wait..");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setProgress(0);
progressDialog.show();
}
protected void onPreExecute (){
}
#Override
protected Void doInBackground(Object... arg0) {
// TODO Auto-generated method stub
//Code to do the process in background
return null;
}
#Override
protected void onProgressUpdate(Long... progress) {
// int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
progressDialog.setProgress(progress);
}
protected void onPostExecute(Void result){
progressDialog.dismiss();
//Your code after the process
}
}
You can call this Task as,
new LoginProcessing(loginCredentials).execute();
In this Example loginCredentials is the parameter I am passing to the AsyncTask. You can change it to your own parameter.
In my Android app, one form has a button which upon click opens up another; the new form performs activities which can take a while. I want the first form to remain open and for the progress dialog to keep spinning while these activities finish.
I've attempted this below, but it just won't work. The progress dialog just finishes and opens up the next window (before described activities on new form have finished)
In the below code SecondForm -
The subroutine "Calculations", is what takes a while to complete
Code:
MainActivity:
final ProgressDialog ringProgressDialog = new ProgressDialog(
MainActivity.this);
ringProgressDialog.setTitle("Loading");
ringProgressDialog.show();
ringProgressDialog.setCancelable(false);
new Thread(new Runnable() {
#Override
public void run() {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(
getApplicationContext(),
SecondForm.class);
startActivity(intent);
}
});
} catch (Exception e) {
}
ringProgressDialog.dismiss();
}
}).start();
SecondForm:
public class CategoryTabs extends Fragment {
static Context mContext;
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
gotstatdata = false;
rootView = inflater.inflate(R.layout.fragment_abc, container, false);
mContext = rootView.getContext();
new Thread(new Runnable() {
#Override
public void run() {
try {
((Activity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
gotstatdata = false;
Calculations(128);
gotstatdata = true;
}
});
} catch (Exception e) {
}
}
}).start();
You are dismissing your dialog as soon as it runs with ringProgressDialog.dismiss();.
That line should be removed and you should do something like send out a broadcast when you are finished to close the progress dialog.
It looks like you might also just want a background thread rather than a second Activity because no user interaction is required.
Looking at AsyncTask would be the easiest way for you to start with background threads and it's 'onPostExecute` method will allow you to dismiss your dialog.
Edit
The basic structure you want is to add the following
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODO: show your dialog from here
}
#Override
protected Void doInBackground(Void... params) {
//TODO: call Calculations(128); from here
//Calculations(128); should live within this async task instead of a new activity
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//TODO: call dismiss on your dialog from here
}
}.execute();
instead of the new Thread(new Runnable() { block you currently have
I am new to android development. I want to develop a dialog with a progressbar in my application. When i click the search button the dialog should appear with the progressbar, showing that the progress is going on before switching to another activity. Please suggest me with sample code.
Use a ProgressDialog. You should do the work on a new thread, though, and use a handler to call back to the activity when finished. Here's how I do it:
private ProgressDialog pd;
private View.OnClickListener searchClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = ProgressDialog.show(MyActivity.this, "Searching...", "Searching for matches", true, false);
new Thread(new Runnable() {
public void run() {
//do work
//.....
finishedHandler.sendEmptyMessage();
}
}).start();
}
}
private Handler finishedHandler = new Handler() {
#Override public void handleMessage(Message msg) {
pd.dismiss();
//start new activity
}
}