I have an activity, composed of an AsyncTask aiming to launch a request when the user clicks on the button. I have been looking for answers, but I didn't find the same problem, or it didn't the same for me. The code is doing what I want, but the ProgressDialog looks blocked as the spinner is not turning sometimes (almost all the time).
When I click on the button :
AsyncTask is launched -> showDialog() is called onPreExecute -> startSearch ( SearchManager launches a new AsyncTask with in the doInBackground there is a heavy call with network ) -> doInBackground in Activity waits for SearchManager to be loaded -> display.
Code for button :
button_search.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new SearchTask().execute();
}
});
Code for AsyncTask in Search Activity :
private class SearchTask extends AsyncTask<Void,Void,Void>{
#Override
protected void onPreExecute(){
showDialog(DIALOG_LOADING_ID);
searchManager.startSearch();
}
#Override
protected Void doInBackground(Void... params) {
while(searchManager.isLoading()){
try {Thread.sleep(150);} catch(Exception e){};
}
return null;
}
#Override
protected void onPostExecute(Void ret){
try {dismissDialog(DIALOG_LOADING_ID);} catch (Exception e){};
if ( searchManager.errorOccurred() ){
//Error
} else {
//No Error
}
}
Code for SearchManagerAsyncTask : which is directly launched by startSearch
protected class SearchAsync extends AsyncTask <Void,Void,Void>{
#Override
protected Void doInBackground(ComSearchAds... datas) {
global.getDataManager().doSearch();
//... When finished
setIs_loading(false);
}
}
I'm apparently doing something wrong, but can't find what and how to avoid this. Thanks for your help !
SOLUTION :
Finally, it appears that the not spinning ProgressDialog was because I was using the same instance of ProgressDialog and
showDialog(DIALOG_LOADING_ID);
//doInBackground
dismissDialog(DIALOG_LOADING_ID);
used with causes problem, I changed to
removeDialog(DIALOG_LOADING_ID)
and now it's working fine.
Thanks All, and hope it can help someone someday !
You don't need to create another task , just instead of doing the search stuff via another activity.
all you need to do is to put you search cod ein doInbackGround() of search task. e.g
#Override
protected Void doInBackground(Void... params) {
global.getDataManager().doSearch();
return null;
}
also use class level variable to get search result to store true/false
#Override
protected void onPostExecute(Void ret){
// Set you result here
setIs_loading(my_searh_result);
try {dismissDialog(DIALOG_LOADING_ID);} catch (Exception e){};
if ( searchManager.errorOccurred() ){
//Error
} else {
//No Error
}
}
Could you please try to add a ProgressBar control in your layout file and set its Visible to true when starting async task and set to gone when end of process reached. Below is the code for the same.
<ProgressBar
android:layout_width="wrap_content"
android:id="#+id/progressBar1"
android:layout_height="wrap_content"></ProgressBar>
It's hard to say, but try this for onClickListner:
button_search.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new SearchTask().execute();
setIs_loading(true);
searchManager.startSearch();
}
});
It's a pretty wild guess, but it might work
Related
I've an Activity that contains a lot of data and elements.
When it has too information, the activity wait in white for be shown, that is not I want, I actually want to show a activity while it's loading the data.
So, How can I to know when my activity it's fully created?
My intention is to launch in a second thread the activity across the waiting activity.
You should load that data asynchronously, in another thread if it takes that much time to load. Launch another thread (by using an AsyncTask for example of plain Java Threads), load the data and show some loading-View on the Activity that notifies the user that something is happening in the background.
You can use AsyncTask and can show progress dialog till the data is loaded.
private class FetchRSSFeeds extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
// Fetch the data from URL
// do background process
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
// Setting data to list adaptar
setListData();
}
}
This method called after on create in activity
#Override
public void onStart() {
super.onStart();
}
I am trying to get along with AsyncTask..
what my problem was that i was building a table of textviews dynamically, based on the output of a procedure.. But then i figured that by using asynctask i can do it in a more efficient way..So, what i did is as follows:
private class DisplayReport extends AsyncTask<Void, Void, Boolean>{
protected void onPreExecute(){
//Message -- "Please wait while the Report Loads..."
}
#Override
protected Boolean doInBackground(Void... params) {
//Here i fetch the data from the procedure via a web service
//parse the result of web service and set a bool variable true or false based on whether the dataset fetched is empty or not.
}
protected void onPostExecute(Boolean value){
if(value == true){
"Please try again later!!"
}
else{
runOnUiThread(GenTable);
}
}
private Runnable GenTable = new Runnable(){
public void run(){
try {
displayReport(result); // in this method i build the table.
} catch (Exception e) {
ad.setTitle("Error..");
ad.setMessage(e.toString());
}
}
};
}
the above async class is an inner class in my main class which extends activity.
and this is how i am executing the asynctask..
DisplayReport dr = new DisplayReport();
dr.execute();
now when i debug, i get the "source not found" error on dr.execute()..
i tried searching a lot on the net, but i simply cannot find out anything concrete. Also, please let me know if my approach is incorrect..
this question might seem very silly, but i am new to android and java as well and any help would be really great..
Thanks!
Execute is going to start a new thread. You don't want to debug into it. Instead, put breakpoints in onPreExecute, doInBackground, and onPostExecute and you can see when each of those gets called.
onPostExecute is already being run in the UI thread, so you should not create another runnable for it. Just make your onPostExecute like this:
protected void onPostExecute(Boolean value){
if(value == true){
String message = "Please try again later!!";
// Do something here with your message
}
else{
displayReport(result);
}
}
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();
}
The goal:
Using Google App Engine server and Android client, I'm trying to put on the Google map at the Android client Users overlays. Every 30 seconds I'm polling the server and getting Vector that contains users and adding it to the map.
Current status:
I'm dong all that using in one new thread, So after running the app I got:
weird behaviors(delayed overlays, multiple overlays) and after that crushed with ConcurrentModificationException.
After reading a bit i figured out that I need to work with AsyncTask.
Correct me if I'm wrong,But I understand that everything done in the Activity at at onCreate is "running" in UIhread so I need to put the "Logic" (All the Network handling) in doInBackground and all the UI Handling like putting overlays on the map in onPostExecute.
My Question are:
1) In the current status I'm doing:
new Thread()
{
#Override
public void run()
{
super.run();
while(true)
{
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
putNewOnlineUserOnTheMap();
}
}
}.start();
What is the right way to convert this To AsyncTask?
Do I poll the server still using new thread in the doInBackground or there is right way to do this?
2) Is there a specific list of what counts as UI to put in onPostExecute or any concepts list?
In my case I guess that in need to put putNewOnlineUserOnTheMap() in onPostExecute.
Thanks.
Something similar to the following:
class UpdateTask extends AsyncTask<Void, Vector, Void>{
#Override
protected Void doInBackground(Void... params) {
// this is running in a background thread.
while (!isCancelled()) {
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
// send the result back to the UI thread
// onProgressUpdate will be called then
publishProgress(responseFromServer);
}
return null;
}
#Override
protected void onProgressUpdate(Vector... values) {
// this is executed on the UI thread where we can safely touch UI stuff
putNewOnlineUserOnTheMap(values[0]);
}
}
You can't use the result of the task since the task is finished then. But you can use the progress publishing mechanism to get periodic results. If you use it like that and do the modification on the UI thread you should not get ConcurrentModificationException because you do the modifications on the one thread that can safely modify the UI.
One thing to note here: create new instances of your Vector in the background thread and then use it to update the UI. But don't touch the same object afterwards in the backgroundthread. That way you don't need any synchronization since after the background thread sends it away it is only the UI thread that touches it. (and you could use a simple ArrayList instead of a Vector)
AsyncTask uses generics and varargs.The parameters that are passed to the asyntask are . TypeOfVariableArgumentsParameters is passed into the doInBackground(), ProgressParam is used for progress information and ResultParam must be returned from doInBackground() and is passed to onPostExecute() as parameter.
example:--
protected class ParsingTask extends AsyncTask> {
private ProgressDialog loadingDialog = new ProgressDialog(JsonParserActivity.this);
protected void onPreExecute() {
loadingDialog.setMessage("loading app store..");
loadingDialog.show();
}
#Override
protected ArrayList<Items> doInBackground( Context... params ) {
// do ur process here.
return result;
}
if (!this.isCancelled()) {
}
return result;
}
#Override
protected void onProgressUpdate(String... s) {
super.onProgressUpdate(s);
Toast.makeText(getApplicationContext(), s[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute( ArrayList<Items> response ) {
//if u r dealing with list view and adapters set the adapter here at the onPostExecute()
loadingDialog.dismiss();
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(getApplicationContext(), "The operation was cancelled", 1).show();
}
}
You can use AsyncTask like below. Hope this will help you..
Class YourClass{
void YourClass(){
NetworkTask nT = new NetworkTasK();
nT.execute();
}
}
protected class NetworkTask extends AsyncTask<Void, String, Boolean>
{
#Override
protected Boolean doInBackground(Void... params)
{
try
{
String response;
while(keepreceiving)
{
response = in.readLine();//Prog Counter stops here until getting i/p.
if(response != null)
yourFunctionForResponse(response);
}
}
catch (Exception ex)
{
}
return null;
}
private void yourFunctionForResponse(String response){
//things to do....
}
}
You may also try runOnUiThread(Runnable action) along with this to implement your work.
I'm using following code to fill a custom ListPreference dialog. Since the fill procedure takes a lot of time i want to show a progress dialog during the fill procedure.
My problem is that filler.execute() does not block onPrepareDialogBuilder and functions goes till the end before values are filled causing an exception... Any idea?
#Override
protected void onPrepareDialogBuilder(Builder builder) {
// Load data
if (this.getEntries()==null) {
FillerTask filler = new FillerTask();
filler.execute();
}
Log.d(TAG, "Filler finished");
super.onPrepareDialogBuilder(builder);
}
Here is Filltertask code, basically he looks for every activity with a MAIN Intent filling a list:
private class FillerTask extends AsyncTask<Void, Void, String[][]> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
Log.d(TAG, "Dismiss dialog");
dialog = ProgressDialog.show(MyListPreference.this.getContext(), "", "Doing stuff...", true);
}
#Override
protected String[][] doInBackground(Void... params) {
return fill();
}
public String[][] fill() {
Log.d(TAG, "Fill started");
CREATE LISTS...
// Done
Log.d(TAG, "Fill done");
String[][] result = new String[][] {entryNames, entryValues};
return result;
}
#Override
protected void onPostExecute(String[][] result) {
Log.d(TAG, "Post execute");
MyListPreference.this.setEntries(result[0]);
MyListPreference.this.setEntryValues(result[1]);
dialog.dismiss();
}
}
My problem is that filler.execute() does not block onPrepareDialogBuilder and functions goes till the end before values are filled causing an exception... Any idea?
That is the entire point behind an AsyncTask. The "Async" in AsyncTask means asynchronous.
Use your AsyncTask to get your data. Then, in onPostExecute(), display the dialog.
Found the solution, best way to do this is override the onClick method and let the AsyncTask postExecute call the "super()", so click is not passed until content is loaded and during load progress bar is correctly displayed.
asyntask doesn't lock main thread, it just drops a message to message queue of main thread