I'm trying to show a "Loading" dialog before the async task starts working. With the following code what happens is that the dialog doesn't show untill all the async task is done his operations, the dialog is being prompted only in the end.
Here's the code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
loadMap();
progressBar = ProgressDialog.show(Map.this, "",
"Loading. Please wait...", true);
//firing the asynctask here
}
The asynctask is doing pretty heavy operation, it takes like 10 seconds till I'm able to see the layout, that's why I want to prompt the user with a "Loading" dialog. but the user is able to see it only in the end of the asynctask operations for some reason.
What should I do?
EDIT: Forgot to mention that in the onProgressUpdate I'm doing some UI operations (Adding the overlays to the mapview). That's why the UI is freezing probably. but I just want to know how to show the loading dialog before, I don't care if the UI freezes after the "loading" dialog shows. Actually I do care, but I don't know if there's any better solution.
EDIT2: The loadmap function:
public void loadMap()
{
mapView = (TapControlledMapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
mapController.animateTo(new GeoPoint((int)(47.975 * 1E6), (int)(17.056 * 1E6)));
mapView.setOnSingleTapListener(new OnSingleTapListener() {
#Override
public boolean onSingleTap(MotionEvent e) {
itemizedOverlay.hideAllBalloons();
return true;
}
});
myLocationOverlay = new FixedMyLocationOverlay(this, mapView);
mapView.getOverlays().add(myLocationOverlay);
mapView.invalidate();
zoomToMyLocation();
editText = (EditText)findViewById(R.id.search);
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
onSearchRequested();
EditText editText = (EditText)v;
editText.clearFocus();
}
});
}
Have you tried moving loadMap() in to the asynctask ?
Related
In my project I have a lot of asynctask, which all follow this pattern:
#Override
protected void onPreExecute() {
super.onPreExecute();
crossfade(progressBar, contentView);//hide content, show progress bar
}
#Override
protected Void doInBackground(String... arg0) {
//some work
}
protected void onPostExecute(Void unused) {
crossfade(contentView, progressBar);
}
Code for crossfade:
void crossfade(View contentView, View loadingView){
Runnable r = new Runnable(){
#Override
public void run() {
if(contentView != null){
contentView.setAlpha(0f);
contentView.setVisibility(View.VISIBLE);
contentView.animate()
.alpha(1f)
.setDuration(CROSSFADE_TIME)
.setListener(null);
}
if(loadingView != null){
loadingView.animate()
.alpha(0f)
.setDuration(CROSSFADE_TIME)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
if(loadingView != null){
loadingView.setVisibility(View.GONE);
}
}
});
}
}
};
runOnUiThread(r);
}
The problem happens when asynctask executes faster than animation time, causing second crossfade call before the first one is finished, resulting in both views being invisible.
I tried queueing runnables to execute them sequentially, but the problem is if user clicks a lot of buttons or many fragments are being loaded(they use crossfade method too), UI thread becomes overloaded and it may crash my app. The only solution I see so far is to add extra delay to all my asynctasks, using Thread.sleep(CROSSFADE_TIME), however it looks like a really dirty hack and I'm not sure if it's a good user experience.
In case someone needs it in future, adding loadingView.animate().cancel() and contentView.animate().cancel() before animation cancels previous animations and everything works ok.
Why are you running the crossfade animation in a separate thread? Try to do the animation without
Runnable r = new Runnable(){ and runOnUiThread(r);
I have a game quiz, and if a user's answer is wrong a popup screen pops up and stays on screen for 3 seconds. I do this with Handler. Since the game is time limited, they come up with solution to press back button to remove popup from the screen :) and move along. So I disabled the back button for that popup activity. BUT, now I have another problem. It seems that my Handler count time from the last click, so if I click back button on that popup screen Handler count time from that click. If I click it again, it starts from beggining. I've tried to click it 10-12 times and my popup screen was on for half a minute. :) And that's not good. How to make my popup be on for 3 seconds no metter if click back button or not during his time on?
My popup class:
public class WrongAnswer extends Activity{
TextView wrong;
String correctAnswer, correct;
public final int delayTime = 3000;
private Handler myHandler = new Handler();
public void onUserInteraction(){
myHandler.removeCallbacks(closePopup);
myHandler.postDelayed(closePopup, delayTime);
}
private Runnable closePopup = new Runnable(){
public void run(){
finish();
}
};
#Override
public void onBackPressed() {
//do nothing
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.wrong);
Bundle extras = getIntent().getExtras();
if(extras !=null) {
correct = extras.getString("correctAnswer");
}
inicijalizujVarijable();
myHandler.postDelayed(closePopup, delayTime);
}
private void inicijalizujVarijable() {
wrong = (TextView) findViewById(R.id.tvWrong);
Typeface pogresanFont = Typeface.createFromAsset(getAssets(), "Bebas.ttf");
wrong.setTypeface(pogresanFont);
Wrong.setText("Wrong answer!\nCorrect answer is:\n\n" + correct);
}
}
Remove this:
public void onUserInteraction(){
myHandler.removeCallbacks(closePopup);
myHandler.postDelayed(closePopup, delayTime);
}
It's resetting your handler on any interaction, which results in the behaviour you describe.
As a side note, it seems rather heavy to dedicate an Activity to this functionality, I think you'd be better off using a Dialog or similar.
You can show popup as Dialog and setCancelable() to false.
http://developer.android.com/reference/android/app/Dialog.html#setCancelable(boolean)
I want to make the hand phone continuously refresh the RSSI values of other devices while the phone is being moved away from them.
In order to make the screen display keep updating the new RSSI values, I choose to use AsyncTask so as not to freeze my UI.
But somehow my code does not work. Every time it is run, the app dies. For debugging purpose, I put a Toast.makeText there. But nothing appears on the screen. So maybe that means my AsyncTask is actually not executed at all?
AsyncTask Codes:
private class Refresh extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
while(true){
Toast.makeText(getApplicationContext(), "Loop is being executed", Toast.LENGTH_SHORT).show();
init();
startDiscovery();
}
}
}
OnCreat() Codes:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
startDiscovery();
new Refresh().execute();
}
Do please help me!
Where am I wrong?
ToT
Progress Dialog not showing up was solved by removing the blocking call.
My purpose is to download large amount of data from internet and keep the end user informed about download status, however I have to wait to the data to complete downloading for proceeding to the next step, and because of that I have to block the code from executing.
Blocking causes the progress dialog not to show up or freeze. I need tip for implementing those tasks the best way. Because my tasks are simple it seems for me to be overkill to implement task complete listener and I was wondering if there was any other way to solve my problem?
You can use this:
#Override
protected void onPreExecute() {
dialog= ProgressDialog.show(YourActivity.this, "", "MessageYouWantToDisplay");
}
#Override
protected void onPostExecute(T result) {
dialog.dismiss();
}
You call the class that extends AsycTask by typing:
new NameOFClass().execute();
Try this first as a test and put a Thread.sleep() in you doInBackground method to understand how it works. And after that use it in your project with your true methods, data etc.
Try this:::
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(YourActivity.this);
dialog.setMessage("Progress start");
dialog.show();
Log.d(TAG, "Showing dialog");
}
#Override
protected void onPostExecute(T result) {
dialog.dismiss();
Log.d(TAG, "Dismissing dialog");
}
I have a progress dialog I am trying to show when a user clicks a button to launch a new activity. The spinner should be displayed on the current page until the other activity appears. ( The activity can take sometimes up to 4-5 seconds to launch and without the spinner it just shows a pressed button that looks frozen )
This is what I have, it's only working if I remove hideProgressDialog();, but then the spinner will still be there when I back to the previous activity, obviously.
What am I doing wrong ?
Progress Dialog :
public void showProgressDialog(Context context) {
if(this.progressDialog != null) {
this.progressDialog.dismiss();
this.progressDialog = null;
}
this.progressDialog = ProgressDialog.show(context, "", "Chargement en cours, veuillez patienter");
}
public void hideProgressDialog() {
if(this.progressDialog != null) {
this.progressDialog.dismiss();
this.progressDialog = null;
}
}
Function :
public void startActivity(Context context, Class<? extends Activity> activityClass) {
try {
showProgressDialog(context);
Intent intent = new Intent(this, activityClass);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
hideProgressDialog();
}
catch(Throwable e) {
e.printStackTrace();
}
}
Example of a button click where this calls the function to show the spinner :
#Override
public void onClick(View view) {
if(view.getId() == R.id.changeBannerButton) {
getBaseApplication().startActivity(this, BannerListActivity.class);
}...
Call hideProgressDialog() in the onResume() method. This way, if the user presses the back button, the onResume() method gets called and immediately hides the progress dialog.
Well First off you should use the new DialogFragment class with FragmentManager. Because showdialog() is deprecated from API level 8
Next you should use showdialog and removedialog for adding and removing the dialog.
And you should use the onCreateDialog to handle the dialog and the operations. Like start a new thread to run do the job when you are displaying the progressdialog.
Try to load data in a seperate thread on start of activity. But before start of that process show the progress dialog. Now once the process is done use runOnUI to hide the progress dialog..
Indicate the user that data is being loading
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
and this:
Android - using runOnUiThread to do UI changes from a thread