so I am trying to learn how to create basic Android applications.
I am stuck on this problem:
The Home Activity has a button that once pressed does two things:
1. Call a REST-Api on my backend-server. The server returns JSON-Objects. The JSON objects are mapped to Java Objects. Finally they are added to a static list.
Start a new intent that launches an Activity with a List Layout.
OnCreate() the ListLayout is filled with data from the static List obtained in step 1.
The Problem is that step 2 does not work as intended because step 1 is asynchronous. So step 2 runs before step 1 finishes to fill the static list with data from the server, resulting in an empty List being displayed on the ListActivity.
How can I wait for step 1 to finish before starting the new Activity so the data is displayed correctly?
Thanks.
Use AsyncTask.
Inside the method doInBackground() put your code for performing API call. After the API call is completed, the method onPostExecute() gets called where you can put the code to go to the next activity.
Check detailed guide here: https://developer.android.com/reference/android/os/AsyncTask
Create an AsyncTask class and override their method as this example :
public class DownloadTask extends AsyncTask<String,String,String>{
#Override
public void onPreExecute()
super.onPreExecute();
{
/// initialize loading animation if you want
}
#Override
public String doInbackGround(String... params)
{
///call your rest request
return resulofyourrequest;
}
#Override
public void onPostExecute(String result)
{
super.onPostExecute(result);
// stop loading animation if you already started one in onPreExecute
///do the stuff you need after you get the result and start your activity here
}
}
and to run your class
new DownloadTask().execute(your_url);
Related
I am getting all the dates between two given dates and then creating fragments for each date in between. The problem is when I use Asynctask and put the method in the doinbackground sometime it works and sometime it doesn't.
Specially when I open Asynctask containing activity from another activity. But on button click inside activity it works with a progressbar.
public class WaitForLoad extends AsyncTask<String, Integer, String>{
#Override
protected void onPreExecute() {
super.onPreExecute();
pro_bar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pro_bar.setVisibility(GONE);
}
#Override
protected String doInBackground(String... strings) {
get_con_fro_sta_to_end(dat_ran_sta, dat_ran_end);
return null;
}
}
So according to Asynctask documentation it should be 3 sec. But if I put a entire year in the method it takes about 8 sec to load or so.
So is there any workthrough Asynctask or Can you suggest me an example alternative Like maybe using a handler or so.
I think you're changing Interface from your "get_con_fro_sta_to_end()" method...This is not allowed from a Background Thread and then it should be changed somehow.
AsyncTasks have the "void onProgressUpdate()" that is used to execute code in the UiThread/MainThread every time "publishProgress()" is called from "doInBackground()".
DoInBackground() should NOT touch Interface but just prepare Data/Things to be displayed using "onPostExecute()" (which runs code in the UiThread/MainThread)
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
asyntask.execute();
}
I'm reading data from some API. Is it possible to call doInBackground() from onPostExecute?
I want do it recursively like (network task and update in UI ) for 5 times. Thanks in advance.
Starting the AsyncTask again from inside onPostExecute is a horrible idea. As you want to do it recursively like 5 times for network calls along with UI update, I would like to suggest you to keep an interface to keep track of the AsyncTask call.
So here's an example about how you can achieve the behaviour. You may create an interface like this.
public interface MyResponseListener {
void myResponseReceiver(String result);
}
Now you declare the interface in your AsyncTask class too. So your AsyncTask may look like this.
public class YourAsyncTask extends AsyncTask<Void, Void, String> {
// Declare an interface
public MyResponseListener myResponse;
// Now in your onPostExecute
#Override
protected void onPostExecute(final String result) {
// Send something back to the calling Activity like this to let it know the AsyncTask has finished.
myResponse.myResponseReceiver(result);
}
}
Now you need to implement the interface you've created already in your Activity like this. You need to pass the reference of the interface to the AsyncTask you're starting from your Activity
public class MainActivity extends Activity implements MyResponseListener {
// Your onCreate and other function goes here
// Declare an AsyncTask variable first
private YourAsyncTask mYourAsyncTask;
// Here's a function to start the AsyncTask
private startAsyncTask(){
mYourAsyncTask.myResponse = this;
// Now start the AsyncTask
mYourAsyncTask.execute();
}
// You need to implement the function of your interface
#Override
public void myResponseReceiver(String result) {
if(!result.equals("5")) {
// You need to keep track here how many times the AsyncTask has been executed.
startAsyncTask();
}
}
}
doInBackground() is called before calling onPostExecute.
Since you cannot perform network tasks on the UI thread, an AsyncTask is created.
The AsyncTask executes in the background, performing the network task on the worker thread. Then after the background task is completed, onPostExecute() is called that makes the UI changes on the UI thread.
This should help : https://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/training/basics/network-ops/index.html
The AsyncTask class is used to do some work in background and publish the results to the MainThread so it's generally not possible because the work that's being done in the worker thread may not be doable in MainThread, (like the NetworkOnMainThreadException when you do networking in MainThread).
I suggest you to make an array of your jobs and call the execute() method of your subclass of AsyncTask and it will serialize the jobs to be done in a worker thread.
I am using AsyncTask so that the function I want executes immediately and does not wait till the end to be executed..
but for some reason I don't why it executes in at the end of all process!
I looked at other solutions and found that Thread should be executed at the end but for AsyncTask it should be executed whenever it is called..
here is my code
private void LogMeIn()
{
string CheckValue;
// Here I call the AsyncTask
new GCM().execute(null,null,null);
//gcmRegID is a public variable and should has GCM value assigned to it by now, but I it is empty as GCM() has not been executed yet
//This is always return empty string
CheckValue = gcmRegID;
}
This is the AsyncTask that wait till the end to be executed
//This is the AsyncTask
private class GCM extends AsyncTask<String, String, String> {
private String resp;
private Context context;
#Override
protected String doInBackground(String... params) {
GCMHelper gcmRegistrationHelper = new GCMHelper (
getApplicationContext());
try {
gcmRegID = gcmRegistrationHelper.GCMRegister("123456789");
} catch (Exception e) {
e.printStackTrace();
}
return gcmRegID;
}
}
I tried to put the call for GCMRegister in onPreExecute but i get an error that it has to be in the main thread
it is like i am going in circles....
the call has to be in the main thread and the main thread will be executed at the end of the function...
it is like no way to get the GCM code in the middle!!!!
How can I make this AsyncTask executes when it called??
Thanks
Without seeing more of your code it's hard for me to tell but I would take a look at where you are calling LogMeIn(). Because your AsyncTask and call to execute are nested in the LogMeIn() function, it won't be called until LogMeIn() is first called.
AsyncTask goes through the following 4 steps in order after calling execute():
onPreExecute()
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
These can be added to your GCM class and used however you like. Note that you don't call them directly. AsyncTask does it automatically after calling .execute().
Only the tasks specified in doInBackground(Params...) are executed on a background thread. The rest are all done on the UI(or main) thread. I would suggest putting either a toast or a log inside onPreExecute() and in onPostExecute() to debug where/when GCM().execute is actually being called and then to tell you when the background task is complete. This will give you a better idea of what is going on.
Make sure you aren't trying to update the UI in doInBackground().
Would love to help more but we would need to see more of your code.
#Override
public void onPreExecute() {
super.onPreExecute();
Log.d("GCM", "onPreExecute: called");
}
#Override
public void onPostExecute(String resultOfDoInBackground) {
super.onPostExecute(resultOfDoInBackground);
Log.d("GCM", "onPostExecute: called");
}
AsyncTask keeps a queue of tasks and a thread pool,the thread pool execute the tasks one by one,so if you have too more tasks ,you will find it not execute your tasks immediately.
And in one process ,all your AsyncTask share one thread pool.In this case,you should make one task queue by yourself,you can just use HandleThread to execute a timely task.
Try placing your new GCM().execute(null,null,null); in the protected void onCreate(Bundle savedInstanceState) method. this way it will be called once the app is ran. This way you will have your GCM id before you get to the LogMEIn method.
Try this -
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new GCM().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
} else {
new GCM().execute();
}
I have a problem regarding Async task
Async from android
Using 2 activities "A" and "B"
by entering a word to search from the url and and store value in DTO and then fetching values from getter and setter.
My complication is that i have implemented async in my activity "B" and that activity is fetching value from same DTO.
Problem is that how my post know that do in background have fetched value from DTO and DTO have fetched value from internet...in case of slow internet connection.
I m sending intent from "A" to "B" and showing the results on "B"
PROBLEM:
1. If i remove async then app shows black page and also freezes (in case of slow connection only) but data is displayed
2. If i use aync then sometimes progress dialog show for long time and inspite of knowing that data is already displayed in UI
code links https://www.dropbox.com/s/p27rpokz68sryv3/SearchData.java
https://www.dropbox.com/s/rm3i52djiay327u/SearchData_DTO.java
https://www.dropbox.com/s/2hpufx2a12480on/Search.java
Pls suggest me the possible solution for this
Regards
You need to listen for asyntask complete listener, For that let your activity A impliment interface and call that method from Activity B,s Asyntask,s onpostexecute method
Thus your activity A will come to know that B has finished his task and you can do next thing..
Hope this helps
public interface AsyncTaskCompletedListener {
public void OnResultSucceeded(String result);
}
public class LoginAsyncTask extends AsyncTask<String, Void, String> {
AsyncTaskCompletedListener mAsyncTaskCompletedListener;
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
mAsyncTaskCompletedListener.OnResultSucceeded(result);
}
}
Here is the interface Let Activity A impliment this and from Activity invoke this from onpostexecute
From Activity A
LoginAsyncTask customloginasync = new LoginAsyncTask(getActivity(),
FATCH_USER_LIST, arglist);
customloginasync.execute();
customloginasync.setOnResultsListener(new AsyncTaskCompletedListener() {
#Override
public void OnResultSucceeded(String result, int asyncTaskNo) {
Logger.logInfo("CustomLogin data=========" + result);
ParseAvailableUserData(result);
}
});
One of my activities make a http request to a webservice to get some weather data when I start the application.
The issue that the activity will take 3-4 seconds to display because of the webservice request. ( Tested on actual device )
I know I m not doing this the right way. All I m doing is on the onCreate method, I m making the request , getting the xml back, parsing and displaying the data.
What is the best way to deal with webservice requests in Android so the application won't display a white screen while the request is being made? Maybe some threads.......
I know this is not happening on other application I have in my device that make request to get live data.
Notes:
1) The xml I getting back is not that big ( 5 elements with 5 nested elements on each one).
2) I tried with the 3G network and Wifi but the response time is still the same.
sample code:
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.clock_weather);
// this is where it is making the request and parsing the xml.
WeatherSet set = getWeatherCondition("New York, NY");
TextView currentWeather = (TextView) findViewById(R.id.current_weather);
currentWeather.setText("" + set.getWeatherCurrentCondition().getTempFahrenheit());
TextView currentWeatherH = (TextView) findViewById(R.id.current_weatherH);
currentWeatherH.setText("H: " + set.getWeatherForecastConditions().get(0).getTempMaxFahrenheit());
TextView currentWeatherL = (TextView) findViewById(R.id.current_weatherL);
currentWeatherL.setText("L: " + set.getWeatherForecastConditions().get(0).getTempMinFahrenheit());
ImageView currentWeatherIcon = (ImageView) findViewById(R.id.current_weather_icon);
String imageUrl = set.getWeatherCurrentCondition().getIconURL();
Drawable bitmapDrawable = getImageBitmap(imageUrl);
currentWeatherIcon.setImageDrawable(bitmapDrawable);
setForecastInfo(set, R.id.day1, R.id.day1_icon, R.id.day1_temp, 1 );
setForecastInfo(set, R.id.day2, R.id.day2_icon, R.id.day2_temp, 2 );
setForecastInfo(set, R.id.day3, R.id.day3_icon, R.id.day3_temp, 3 );
setForecastInfo(set, R.id.day4, R.id.day4_icon, R.id.day4_temp, 4 );
}
The time for your response is unpredictable - your network connection can be very poor and take seconds to transfer a few bytes. So the correct way to do this ( as you propose ) is to use thread. In our case android provides very useful class to handle this situations - AsynTask. After you read the docs you will notice that it has 3 very powerful methods that can help you
onPreExecute runs in the ui thread - very helpful to show some spinner or some progress indicator to show the user that you are doing some work in background
doInBackground runs in background - do your background work here
onPostExecute runs in the ui thread- when your are done with your background work hide the progress and update the gui with the newly received data.
private class getWeather extends AsyncTask<Context, Void, Cursor> {
ProgressDialog dialog = null;
protected void onPreExecute () {
dialog = ProgressDialog.show(CLASS.this, "",
"Loading. Please wait...", true);
}
#Override
protected Cursor doInBackground(Context... params) {
WeatherSet set = getWeatherCondition("New York, NY");
return null;
}
protected void onPostExecute(Cursor c) {
dialog.dismiss();
}
}
Then where you have WeatherSet set = getWeatherCondition("New York, NY"); now, you'll put new getWeather().execute(this);
I suggest reading how the AsyncTask works, and see why this should work. It goes outside the onCreate() method.
This is regarding AsyncTask, I just want to help understanding the concept, it is really useful:
DownloadFilesTask dft = new DownloadFilesTask(this);
//Executes the task with the specified parameters
dft.execute(Void1...);
...
...
...
dft.cancel(boolean);
private class DownloadFilesTask extends AsyncTask<Void1, Void2, Void3> {
//Runs on the UI thread before doInBackground(Void1...)
protected void onPreExecute() {
}
//runs in BACKGROUNG threat
protected Void3 doInBackground(Void1... urls) {
//it can be invoked from doInBackground(Void1...) to publish updates
//on the UI thread while doInBackground(Void1...) is still running
publishProgress(Void2...);
}
//Runs on the UI thread after publishProgress(Void2...) is invoked
protected void onProgressUpdate(Void2... progress) {
}
//Runs on the UI thread after doInBackground(Void1...) has finished
protected void onPostExecute(Void3) {
}
//runs in UI threat after cancel(boolean) is invoked and
//doInBackground(Void1...) has finished
protected void onCancelled(Void3) {
}
}
You can use AsynchTask class for your web service.You can write your time consuming task in on doInBackground.Also you can use a progress Dialog.
Here You can see how to work with AsynchTask.You can also update your UI while web service is parsing without waiting for the complete parsing using onPostUpdate method.
The response time is normal. Don't worry. Make it a point to run the web-service call in a separate thread.
Regarding the white screen, as soon as you start the web service call, fire a ProgressDialog box. This will run till you receive the response. As soon as you receive the response, dismiss the progressDialog box and start the new activity where you can display the result.
Use the following URLs for reference
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
http://thedevelopersinfo.wordpress.com/2009/10/16/showing-progressdialog-in-android-activity/
I have implemented the idea I'm giving you and it works perfectly.
Hope I was of some help
What is the best way to deal with webservice requests in Android so the application won't display a white screen while the request is being made?
Because you said 'white screen" I am assuming you are not using a progress dialog. You need to show a progress spinner/dialog to let the user know you are processing.
Have you check how large the data is? If the data is too large you really cant do anything , if you have control over the service its best to reduce the size.