AsyncTask task go to a endless loop - java

i have problem with some kind a endless loop with AsyncTask..
this is my method with AsyncTask in a fragment class
public AsyncTask<Void, Void, Void> refreshTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Looper.prepare();
System.out.println("UŠAO SAM U DO IN BACKGRASD");
Ponuda.deleteAll();
ArrayList<Ponuda> novaLista= new ArrayList<Ponuda>();
novaLista= (ArrayList<Ponuda>) Ponuda.getAll();
System.out.println("PONUDE: "+ novaLista.size());
((MainActivity)getActivity()).loadData();
Looper.loop();
System.out.println("asdasd"+ Looper.myLooper());
return null;
}
#Override
protected void onPostExecute(Void Void) {
System.out.println("UŠAO SAM U DO IN Post");
mSwipeRefreshLayout.setRefreshing(false);
ArrayList<Ponuda> novaLista= new ArrayList<Ponuda>();
novaLista= (ArrayList<Ponuda>) Ponuda.getAll();
System.out.println("PONUDE: "+ novaLista.size());
RVAdapter adapter = new RVAdapter(novaLista,getContext());
rv.setAdapter(adapter);
super.onPostExecute(Void);
}
};
#Override
public void onRefresh() {
System.out.println("Refreshana je stranica");
refreshTask.execute();
}`
and this is the method that i call from fragment
public void loadData(){
System.out.println("Poziva se funkcija za dohvat podataka");
DataLoader dataLoader;
dataLoader = new WebServiceDataLoader();
if(Ponuda.getAll().isEmpty() || Grad.getAll().isEmpty()){
System.out.println("Dohvaćamo web podatke");
Toast.makeText(this, "Dohvaćamo podatke s weba", Toast.LENGTH_LONG).show();
dataLoader = new WebServiceDataLoader();
} else {
System.out.println("Dohvaćamo lokalne podatke");
Toast.makeText(this, "Dohvaćamo podatke lokalno", Toast.LENGTH_LONG).show();
dataLoader = new DatabaseDataLoader();
}
dataLoader.loadData(this);
System.out.println("asdasdasd");
}
When i debug, the program runs this function and go to fragment inicialization and then go to a endless loop. First it go to ActivityThread class, then to Handler class, then to Looper class it repeat thoose classes again and again. Can somebody please help me?

The problem is the use of the Looper within the AsyncTask's doInBackground() method. AsyncTask is not a generic threading mechanism: it is intended to do short-lived things on a background worker thread which is managed by the system. Your doInBackground() method should not block indefinitely, loop forever, etc. The Looper class is normally used by threads which are going to use a message queue in Android, which allow you to attach Handler objects to them.
This article will help clarify how AsyncTask works: http://po.st/Cei3m2

Related

How can I modify a variable declared in the UI Thread, from an other thread?

I'm currently working on my first Android application.
The application accesses a database to get some informations that I want to print on the screen. To send requests and get answers on the network, I need to use a new thread (I'll name it "N thread"), different from the UI Thread. This part is ok.
Now, I want to modify the variable eventList to get the values stored in a collection, in the N thread.
public class MainActivity extends AppCompatActivity {
public List<Event> eventList = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* I fill the list in an other thread */
new Thread(new Runnable() {
public void run(){
eventList = new WebService().getEvents(); //returns a list
}
// if I check here, eventList contains elements
}).start();
/* I check the result */
TextView respView = (TextView) findViewById(R.id.responseView);
if(eventList != null)
{
respView.setText("Ok");
} else {
respView.setText("Not ok");
}
...
}
The problem is : eventList is not modified. How can modify this variable and print it from the UI thread ?
Thank you for your help.
You can use runOnUiThread function or Handler to update UI from other thread. I suggest you reading the below tutorial first: AndroidBackgroundProcessing
Try this
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params)
{
eventList = new WebService().getEvents();
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView respView = (TextView) findViewById(R.id.responseView);
if(eventList != null)
{
respView.setText("Ok");
} else {
respView.setText("Not ok");
}
}
});
}
}.execute();
private class EventsDownloader extends AsyncTask<Void, Void, Void> {
protected Long doInBackground(Void... params) {
eventList = new WebService().getEvents()
}
protected void onPostExecute(Void result) {
TextView respView = (TextView) findViewById(R.id.responseView);
if(eventList != null)
{
respView.setText("Ok");
} else {
respView.setText("Not ok");
}
}
}
This AsyncTask does what you want, the doInBackground runs on a thread and the 'onPostExecute' runs on the UI thread, and it's only called after the doInBackground finishes. This class is "managed" by the OS. To run it you just need to instantiate it and call 'execute'. I recommend doing something like this
The thing with your code is that the thread runs at the same time as the rest of your code (the calls to the setText), this means when it runs the setText the Thread is still getting the events.

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
}
}
}

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 to preserve data generated in an AsyncTask?

I am working on Android AsyncTask, I wish to make a progress bar during my program is loading. Here's how I make it.
A class is declared here...
private ArrayList<String> result1 = new ArrayList<String>(); //class variable
onCreate()
{
Some stuff here...
new ATask().execute();
for (int i = 0; i <result1.size();i++)
{
output = output +result1.get(i) + "\n\n";
}
textView.setText(output);
}
private void do0()
{
ArrayList<Sentence> result = new ArrayList<Sentence>();
ArrayList<String> result2 = new ArrayList<String>();
result = do1("link", true); //just some function I am working
result1 = do2(result,10);//do2 return ArrayList<String>
}
private class ATask extends AsyncTask<String, Void, String>{
private ProgressDialog progress = null;
#Override
protected String doInBackground(String... params) {
do0();
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPostExecute(String result) {
progress.dismiss();
//adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
progress = new ProgressDialog(ReadWebPage.this);
progress.setMessage("Doing...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.show();
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
};
My intention is that, while the progress bar is loading, it will finish the do0() and modify result1, then my oncreate can use that result1 to display in it's TextView. However my TextView is always empty in this setting. So I move the
for (int i = 0; i <result1.size();i++)
{
output = output +result1.get(i) + "\n\n";
}
textView.setText(output);
into the do0() (right after the result1 = do2()), but then the program will crash. I am not familiar with these thread settings, thanks for your help in advance.
You'll be better served with a thread that holds a Handler object that was initialized on the main thread. Using the handler, you can post() little snippets to be executed on a main thread - like update a progress bar. You can do the same Handler trick from the AsyncTask, but IMHO threads are cleaner.
Said snippets should be implemented as Runnables. Feel free to use a nested anonymous class one-liner.
The problem is with the design of your code. AsyncTask happens asynchronously, so as soon as you call execute on your AsyncTask the rest of your onCreate will execute immediately. AsyncTask will essentially run on a new thread and execute in parallel with your Activity.
What I think you want is to set your TextView in the onPostExecute method of your AsyncTask. onPostExecute gets called after doInBackground is finished.
Also, it is important to keep in mind that doInBackground happens on a background thread, so you cannot make changes to your Activity's UI from code within it. onPre/PostExecute run on the UI thread, so you can make UI changes there, but any code within those methods will also block the UI.

Show ProgressDialog, Retrieve Data, and WAIT FOR IT

I'm writing an app that at many points will attempt to retrieve account information from a website. I'd like to write a single function ("getAccount()") to do the following:
Show a ProgressDialog
Make the call to the website
Wait for a response
Clear the ProgressDialog
Return control to the calling function after the first four steps are done
I'm not having a problem with getting the data from the page; the problem I have is with the whole "show dialog / wait for completion / return control to the calling function" portion. Either the ProgressDialog doesn't show at all, or the function returns to the caller immediately after making the data request from the site, without giving it enough time to retrieve the data.
Any help would be most appreciated.
EDIT: I'm adding a bit of code below for what I have with AsyncTask. Notice that I have the line MsgBox("done") inside grabURL(); this is simply a Toast call. When I run this code, "done" pops up while the HTTP request is still being made. This MsgBox line only exists so I can see if grabURL is properly waiting for GrabURL to finish (which it isn't).
public void grabURL() {
new GrabURL().execute();
MsgBox("done");
}
private class GrabURL extends AsyncTask<String, Void, Void> {
private ProgressDialog Dialog = new ProgressDialog(MyContext);
protected void onPreExecute() {
Dialog.setTitle("Retrieving Account");
Dialog.setMessage("We're retrieving your account information. Please wait...");
Dialog.show();
}
protected Void doInBackground(String... urls) {
try {
// Get account info from the website
String resp = GetPage(ThePage); // I have this classed out elsewhere
// Some other code that massages the data
AccountRetrievalSuccess = true;
} catch (Exception e) {
AccountRetrievalSuccess = false;
}
return null;
}
protected void onPostExecute(Void unused) {
Dialog.dismiss();
}
}
The message box done appears because AsyncTask is using a separate thread(s) to run doInBackground. The call to execute does NOT block. You could move message box done to onPostExecute following the call to dismiss. Tip. You may want to call progress.cancel in onPause or you may get unwanted behaviour on orientation change. Finally, if you are retrieving info in doInBackground, consider returning the info in doInBackground. The info will be passed to onPostExecute. So if the info is object MyInfo consider:
private class GrabURL extends AsyncTask<String, Void, MyInfo> {
Can't say for sure without seeing some code but sounds like you are making a asynchronous call to the website when you want to make a synchronous call (which will block and wait for return data) to the website instead.
You want to use an AsyncTask, generate a non-user-cancellable ProgressDialog in the onPreExecute, do your work in doInBackground, and dismiss it in onPostExecute.
Something like this:
public class MyApp extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// blah blah blah
URL url;
try
{
url = new URL("http://example.com");
new MyTask().execute(url);
}
catch (MalformedURLException e)
{
}
}
protected void doSomeStuff()
{
// stuff to do after the asynctask is done
}
protected void throwAWobbly()
{
// stuff to do if you didn't get the data
}
// inner class to do the data getting off the UI thread,
// so android doesn't "not responding" kill you
private class MyTask extends AsyncTask<URL, Void, Boolean>
{
private ProgressDialog dialog;
private boolean gotData = false;
protected void onPreExecute()
{
// create a progress dialog
dialog = ProgressDialog.show(MyApp.this, "",
"Doing stuff. Please wait...", false, false);
}
protected Boolean doInBackground(URL... urls)
{
// get your data in here!
return gotData;
}
protected void onPostExecute(Boolean result)
{
// get rid of the progress dialog
dialog.dismiss();
if (true == result)
{
// got all data!
doSomeStuff();
}
else
{
// oops!
throwAWobbly();
}
}
}
}

Categories

Resources