Understanding AsyncTask with web server accessing - java

New programmer. Questions at the bottom.
I have an array of fleets that corresponds to vehicles. I would like to make successive calls to the server with each slot in my fleet array.
I wish to do this with an AsyncTask.
private class refreshTruckInformation extends AsyncTask<URL, Void, Void> {
#Override
protected void doInBackground(URL... urls) {
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onPostExecute(Void... voids) {
}
}
**How do I pass in my array of fleets so that I can use them in my doInBackground?
I also want to have a progress bar that goes based on the percentage of fleets it has gone through. What is a good way to do this?**
Thanks!

**How do I pass in my array of fleets so that I can use them in my doInBackground?
Remember that refreshTruckInformation is still a class. So you can use any constructor or settier methods to pass your array.
I also want to have a progress bar that goes based on the percentage
of fleets it has gone through. What is a good way to do this?**
From your doInBackground method you can publis progress using publishProgress method. This progress parameter will be catched in onProgressUpdate method
For example
private class RefreshTruckInformation extends AsyncTask<URL, Void, Void> {
private int[] b;
public RefreshTruckInformation (int[] a){
// use array
b = a;
}
public void setArray(int[] a){
// use array
b = a;
}
#Override
protected void doInBackground(URL... urls) {
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onPostExecute(Void... voids) {
}
}
And call using
RefreshTruckInformation r = new RefreshTruckInformation (yourArray);
or call method like
r.setArray(yourArray);
and execute like
r.execute();

Related

Static field with leak context

My code is
// Asynctask class to handle load data from database in background
private class SyncGetLocations extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mPrgLoading.setVisibility(View.VISIBLE);
mScrollView.setVisibility(View.GONE);
mToolbarView.setVisibility(View.GONE);
}
#Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Get data from database
getLocationDataFromDatabase(mSelectedId);
return null;
}
… etc
Android studio report that this Asynctask class should be static else leaks might occur.
When change to static get a lots of errors like non-static methods and fields cannot be referenced from a static context.
I added:
MyActivity myactivity = new MyActivity();
myactivity.mPrgLoading.setVisibility(View.VISIBLE);
…
all look nice until I run application and get error because I try to access void fields.
Advices?
The problem is that when you make the inner class static you no longer have access to the Activity and its properties. One workaround would be to have a weak reference to your Activity inside the AsynkTask:
private static class YourTask extends AsyncTask<Void, Void, Void> {
private WeakReference<YourActivity> activityReference;
YourTask(YourActivity context) {
activityReference = new WeakReference<>(context);
}
#Override
protected String doInBackground(Void... params) {
return "task finished";
}
#Override
protected void onPostExecute(String result) {
YourActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
activity.myVariable = "example";
TextView textView = activity.findViewById(R.id.textview);
textView.setText(result);
}
}
Anyway I think that creating the AsyncTask as a top level class instead of as an inner class would also solve your problem (as an inner class you have the risk of the class being alive more time than it needs to because of the AsyncTask).

Java Wait for thread(in another class) to finish before executing code in activity

In my android application I am trying to create a situation similar to ios delegate function.
(in ios->)where a class that perform the checking is called and after finish checking it will be redirected back using delegate to viewcontroller and perform next function.
Here is my Class
public class Checking{
private boolean flag;
public boolean getFlag(){
return flag;
}
public void checkFunction(){
//..... check database
if(need to do call webservice){
Thread thread = new Thread(){
#Override
public void run(){
// Perform webservice calling
}
};
thread.start();
}
else{
//end
}
}
}
Here is my Activity
public class ActivityA extends Activity{
#Override
public void onResume(){
doChecking();
}
public void doChecking(){
Checking check = new Checking();
check.checkFunction();
// should finish preform checking in Checking class before proceed
if(check.getFlag()){
// perform next function
}
else{
// show alert
}
}
}
Problem with this is that right after calling the Checking class it straight away perform the if else below the function call. Which in some situation the check in Checking class have not finished and an empty alert is shown. The thread might or might not start depending on the database checking.
Can someone provide me a solution to overcome this?
I know something is missing after calling the Checking class but I am not quite sure what to put it there in order to achieve the result.
Thanks in advance.
What you basically want to do is Hit a web service and then wait till you get the response of web service.
First thing, you don't need to create your own Thread t hit web service. Instead you can use AsyncTask
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Below is code of AsyncTask
class MyAsync extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
//Hit your web service here
}
#Override
protected void onPostExecute(final Void unused) {
//Process the result here
}
}
If you want to restrict user from accessing the app till web service is hit. You can show dialog from another method, like below:
class MyAsync extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
loadingDialog.setMessage("Please wait...");
loadingDialog.setCancelable(false);
loadingDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
//Hit your web service here
}
#Override
protected void onPostExecute(final Void unused) {
if (loadingDialog.isShowing()) {
loadingDialog.dismiss();
}
//Process the result here
}
}
It can be implemented in the following way, by passing the activity in the Checking class's construtor and using it to call showAlert() function in the ActivityA class.
public class Checking{
Activity activity_;
public Checking(Activity activity){
this.activity_ = activity;
}
private boolean flag;
public boolean getFlag(){
return flag;
}
public void checkFunction(){
//..... check database
if(need to do call webservice){
Thread thread = new Thread(){
#Override
public void run(){
// Perform webservice calling
//after all the process
Handler handler = new Handler();
handler.post(new Runnable{
#Override
public void run(){
(MyActivity) activity_.showAlert();
}});
}
};
thread.start();
}
else{
//end
}
}
}
public class ActivityA extends Activity{
#Override
public void onResume(){
doChecking();
}
public void doChecking(){
Checking check = new Checking(ActivityA.this);
check.checkFunction();
}
public void showAlert(){
// should finish preform checking in Checking class before proceed
if(check.getFlag()){
// perform next function
}else{
// show alert
}
}
}

Android Individual AsyncTask

I am having a slight problem in Android Async Task. In my MainActivity, I am calling GetEventAsyncTask which will execute the method inside called retrieveEventJSON:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context = this;
public void onSingleTap(float x, float y) {
final Point point = mMapView.toMapPoint(x, y);
eventModel.setEventX(String.valueOf(point.getX()));
eventModel.setEventY(String.valueOf(point.getY()));
new MyAsyncTask(new MyAsyncTask.OnRoutineFinished() {
public void onFinish() {
CreateEvent.createEventDialog(context, point.getX(),
point.getY(), eventAddress); //this will be called after the task finishes
}
}).execute(eventModel);
}
});
new GetEventAsyncTask().execute();
}
In my GetEventAsyncTask, basically I am just retrieving the data returned from JSON and save them into an array:
public class GetEventAsyncTask extends AsyncTask<Event, Integer, Double> {
EventController eventCtrl = new EventController();
String eventAddress;
Event eventModel = new Event();
public interface OnRoutineFinished{ //interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public GetEventAsyncTask(OnRoutineFinished callback){ //constructor with interface
mCallbacks = callback;
}
public GetEventAsyncTask(){} //empty constructor to maintain compatibility
#Override
protected Double doInBackground(Event... params) {
try {
eventAddress = eventCtrl.getStreetAddressFromGeometry(eventModel.getEventX(), eventModel.getEventY());
eventCtrl.retrieveEventJSON();
} 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) {
}
}
Then when the navigation drawer item onselected, I am calling the plotting marker on map method which takes in the array I saved just now:
case 0:
eventCtrl.plotEventOnMap(context);
break;
I tried to print out the data retrieved in retrieveJSON and it did printed out. But somehow, when I tried to plot onto the map, it does not shows anything. I wonder which part that I overlapped or reinitialize some Object?
The strange thing is if I put getEventAsyncTask under MainActivity, it did run and retrieved the data. But however, if I shifted the getEventAsyncTask out as an individual class, it stopped working. I wonder why is it so?
Thanks in advance.

need to run tasks only after Async task has finished

How do i make sure that the async tasks finishes before i run certain tasks. I need to use a variable AFTER the async tasks changes the value of that variable. If i run the code before async is done running then im screwed. any help? im obviously new to async tasks. If you look at my code im probably not using onPostExecute() as it was intended so advice would be helpful. My initial thought was to keep adding things to the async task but im thinking that this is just bad practice since i have tons of things that must be run in series. Basically, what i think it boils down to is: how do i make sure that the tasks in the UI thread dont start to run before my async task has finished.
public class MainActivity extends MapActivity {
myJSONmap;
public void onCreate(Bundle savedInstanceState) {
new AsyncStuff().execute();
locatePlace(myJSONmap);
class AsyncStuff extends AsyncTask<Void, Integer, JSONObject> {
#Override
protected JSONObject doInBackground(Void... params) {
jObject = GooglePlacesStuff.getTheJSON(formatedURL);
return null;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
myJSONmap = JSONextractor.getJSONHMArrayL(jObject); // getting the parsed data from the JSON object.
//the arraylist contains a hashmap of all the relevant data from the google website.
}
}
You probably want to read more about AsyncTask on Android Developer
http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
About tips, my personal choice is to pass a Boolean to onPostExecute. That way you can evaluate if the doInBackground was succesful, an then figure out what to do (Error message or update the layout).
Keep in mind that in onPostExecute method ideally should only make the screen update, assuming you have the data ok. In your example, why not include the
myJSONmap = JSONextractor.getJSONHMArrayL(jObject);
on the doInBackground? And then call
locatePlace(myJSONmap);
Like this:
class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
String errorMsg;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... v) {
try{
jObject = GooglePlacesStuff.getTheJSON(formatedURL);
myJSONmap = JSONextractor.getJSONHMArrayL(jObject);
//do stuff
return true;
} catch (JSONException e){
errorMsg="Something wrong in the json";
return false;
}
}
#Override
protected void onPostExecute(Boolean success) {
if(success){
locatePlace(myJSONmap);
//update layout
} else {
//show error
}
}
}
You can ue below code to execute async task -
MyAsyncTask_a asyncTask_a = new MyAsyncTask_a();
asyncTask_a.execute();
Once doInBackground() task is finished then only control will go to postExecute().
You can't perform any UI operations in doInBackground , but you can do so in preExecute() and postExecute().
class MyAsyncTask_a extends AsyncTask<Void, Void, Integer> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... arg0) {
// TODO Auto-generated method stub
return 1;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
Hope this will help you.

How should I refactor my code in order to avoid the Network on Main Thread exception on Android?

In my MainActivity I have a class initialization like so:
Presentation presentation = new Presentation("link");
Presentation is a class which gets initialized using values from a .JSON file on a web server:
public Presentation(String URL) {
// Do stuff
doNetworking();
}
private doNetworking() {
// Network access here
// This throws the Network on Main Thread exception
}
In my MainActivity, I need all the values of Presentation to be there in the next step:
Presentation presentation = new Presentation();
// Do some stuff with it
Using the AsyncTask I am not sure how I should go about doing this, so far I have something like this:
public Presentation(String URL) {
// Do stuff
new InitializePresentation().execute(URL);
}
private class InitializePresentation extends AsyncTask<String, Void, Boolean> {
// Amongst other things
protected Boolean doInBackground(String... params) {
// Do the networking stuff here
}
}
What I need is to refactor this code so that it is asynchroneous but behaves like a synchroneous call. Any help is greatly appreciated.
edit
How does one refactor a code to accomplish this?
Bitmap b = new Bitmap();
Load bitmap from network;
Use bitmap in imageview;
Can this be used in this fashion? Or do I have to use it like
Async, doInBackground() {
Load bitmap from network
Use bitmap in imageview
Continue with application
}
Thank you!
You can show a progress dialog while doing the network stuff:
private ProgressDialog progressDialog;
private Context context;
public InitializePresentation (Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(context, "", "loading", true);
}
/*
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected String doInBackground(String... arg0) {
// Do the networking stuff here
}
#Override
protected void onPostExecute(final String result) {
progressDialog.dismiss();
}

Categories

Resources