How to place while loop inside Asynctask - Android - android

I have a asynctask which uses a json function in the doInBackground() and it returns the variables to onPostExecute. The problem is I want the json function to be in a while loop, Every time it goes in the loop it collects a comment. So I could have 15 comments and I want to send them all to onPostExecute to be placed into views. Here is my code
class loadComments extends AsyncTask<JSONObject, String, List<String>> {
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected List<String> doInBackground(JSONObject... params) {
//do your work here
List<String> results = new ArrayList<String>();
int i = 0;
while (i < 5 ){
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
result = json2;
results.add(result);
i++;
}
return results;
}
#Override
protected void onPostExecute(List<String> results) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
commentView.setText(json2.getString(KEY_COMMENT));
LinearLayout.LayoutParams commentViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentViewParams.setMargins(20, 10, 20, 20);
commentView.setBackgroundResource(R.drawable.comment_bg);
commentView.setTextColor(getResources().getColor(R.color.black));
commentBox.addView(commentView, commentViewParams);
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
This code does not work but its an example of what I am trying to accomplish

what you could do is:
1. write a function that parses your json data and initialise all required variables as global variables
2. run your function inside the doInBackground() method of AsyncTask without passing any parameters
3. set values to views from the onPostExecute() method

Related

Accessing null ArrayList from JSON in Main Activity

I know this question has been asked a lot but I still can't figure out how on my code. I'm trying to get values out of this block of code:
private void getAnswerKey(){
class GetAnswerKey extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
JSON_STRING = s;
showAnswerKey();
}
#Override
protected String doInBackground(Void... params) {
RequestHandler rh = new RequestHandler();
String s = rh.sendGetRequest(Configuration.URL_GET_ANSWER);
return s;
}
}
GetAnswerKey gA = new GetAnswerKey();
gA.execute();
}
private void showAnswerKey () {
correctAnswers = new ArrayList<Integer>();
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray result = jsonObject.getJSONArray(Configuration.TAG_JSON_ARRAY);
for (int i = 0; i < result.length(); i++) {
JSONObject jo = result.getJSONObject(i);
int answerKey = jo.getInt(Configuration.TAG_ANSWERKEY);
correctAnswers.add(answerKey);
System.out.println((i + 1) + "a. " + options[correctAnswers.get(i)]); //data are there
}
} catch (JSONException e) {
e.printStackTrace();
}
}
How do I access correctAnswers arrayList on my main activity? correctAnswers itself isn't empty in this code, but when I tried accessing it on other method, it's null. I've tried passing data to other method. Still return null. I have the arrayList as global variable. Any ideas how??
Like suvojit_007 might have correctly assumed, you may be attempting to access the arraylist before it is populated..
You can use interfaces. Create your interface...
public interface ResponseInterface {
public void getResponse(String data);
}
In your AsyncTask declare your interface
private ResponseInterface responseInterface;
Create a constructor within the AsyncTask with the interface as a parameter
public GetAnswerKey(ResponseInterface responseInterface) {
this.responseInterface = responseInterface;
}
Within your onPostExecute, call the interface
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
responseInterface.getResponse(s);
}
... and finally when executing your AsyncTask, do this...
new GetAnswerKey(new ResponseInterface() {
#Override
public void getResponse(String data) {
// do whatever you want with your answers here.
// Also, whatever function that is accessing the
// arrayList, call it here, that way you avoid any
// possibility of the arrayList being null
}
}).execute();

Why my AsyncTask doInBackground() is not passing a value to onPostExecute()?

when i run my code, it returns a value as "null"`
private class MessageActivityLoaderTask extends AsyncTask<Void, Void, Contentlist> {
private LinkedMultiValueMap<String, String> formData;
Activity activity;
public MessageActivityLoaderTask(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
formData = new LinkedMultiValueMap<String, String>();
mProgress.setMessage("Please wait..");
mProgress.show();
}
#Override
protected Contentlist doInBackground(Void... params) {
String url = getString(R.string.base_url) + "/example/example1/1";
Contentlist mess = null;
try {
mess = RestUtils.exchangeFormData(url, HttpMethod.GET, formData, Contentlist.class);
} catch (Exception e) {
e.printStackTrace();
mProgress.dismiss();
}
return mess;
}
protected void onPostExecute(Contentlist result) {
if (result== null) {
Toast message = Toast.makeText(ListobjectsActivity.this, "result is empty", Toast.LENGTH_SHORT);
message.show();
} else {
ListactivityAdapter adapter = new ListactivityAdapter(this.activity, result.getContents());
ListView list = (ListView) activity.findViewById(R.id.account);
list.setAdapter(adapter);
mProgress.dismiss();
}
}`
Your AsyncTask looks like it is set up correctly, so onPostExecute() will receive the ContentList returned by doInBackgroun(). Since onPostExecute() is seeing a null, then doInBackground() is returning a null. That means that either doInBackground() is getting an exception and mess is never set to a non-null value by falling through the catch or RestUtils.exchangeFormData() is returning a null.
I suggest that you debug the code in this area to see what is really going on. It is not likely to be an AsyncTask problem.

AsyncTask doInBackground return empty ArrayList<String> to onPostExecute

I am parsing data from URL in doInBackground and setting values to UI thread in onPostExecute. So my array ArrayList is global variable:
ArrayList<String> arraylist=new ArrayList<String>();
Now, i parse html in doInBackground and add values to global ArrayList , so when i return arraylist to onPostExecute ArrayList() is empty
Here is my code:
ArrayList<String> arraylist=new ArrayList<String>(); // global
new readtextfile21().execute(rezultat1);
public class readtextfile21 extends AsyncTask<String, ArrayList<String>, ArrayList<String>> {
#Override
protected ArrayList<String> doInBackground(String... params)
{
Ion.with(getActivity().getApplicationContext())
.load(rezultat1)
.asString()
.setCallback(new FutureCallback<String>() {
#Override
public void onCompleted(Exception e, String result) {
String htmlStringSlike = result.substring(result.indexOf("<!-- BEGIN .shortcode-content -->"), result.length());
int startPositionSlika=htmlStringSlike.indexOf("<div class=\"shortcode-content\">");
int endPositionSlika=startPositionSlika+"<div class=\"shortcode-content\">".length();
while (htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf("<!-- END .shortcode-content -->") < 0) {
endPositionSlika++;
}
htmlStringSlike=htmlStringSlike.substring(startPositionSlika,endPositionSlika);
while(htmlStringSlike.length()>0){
startPositionSlika = htmlStringSlike.indexOf("src=");
if(startPositionSlika>0) {
String slikaUTekstu=null;
startPositionSlika+= "src=".length() + 1;
endPositionSlika = startPositionSlika;
while (htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".jpg") < 0 && htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".jpeg") < 0 && htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".png") < 0) {
endPositionSlika++;
}
slikaUTekstu = htmlStringSlike.substring(startPositionSlika, endPositionSlika);
htmlStringSlike=htmlStringSlike.substring(endPositionSlika);
arraylist.add(slikaUTekstu);// when i log values are here
}
else break;
}
}
});
return arraylist;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
System.out.println("u onpost" + result);
for(int i=0;i<result.size() ;i++){ // result size here is 0???
slikaTv[i] = (ImageView) v.findViewById(nizSlikaID[i]);
Picasso.with(getActivity()).load(result.get(i)) // programski slika u dodati layout
.into(slikaTv[i]);
v.findViewById(mLayoutIdArray[i]).setVisibility(View.VISIBLE);
}
}
protected void onProgressUpdate() {
}
protected void onPreExecute()
{
}
}
Change your doInBackground() method trying with the code below, sorry but i never used this library so i could have made some mistakes.
#Override
protected ArrayList<String> doInBackground(String... params)
{
try {
String result = Ion.with(getActivity().getApplicationContext())
.load(params[0])
.asString()
.get();
} catch (Exception e){
e.printStackTrace();
}
if (result != null){
String htmlStringSlike = result.substring(result.indexOf("<!-- BEGIN .shortcode-content -->"), result.length());
int startPositionSlika=htmlStringSlike.indexOf("<div class=\"shortcode-content\">");
int endPositionSlika=startPositionSlika+"<div class=\"shortcode-content\">".length();
while (htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf("<!-- END .shortcode-content -->") < 0) {
endPositionSlika++;
}
htmlStringSlike=htmlStringSlike.substring(startPositionSlika,endPositionSlika);
while(htmlStringSlike.length()>0){
startPositionSlika = htmlStringSlike.indexOf("src=");
if(startPositionSlika>0) {
String slikaUTekstu=null;
startPositionSlika+= "src=".length() + 1;
endPositionSlika = startPositionSlika;
while (htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".jpg") < 0 && htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".jpeg") < 0 && htmlStringSlike.substring(startPositionSlika, endPositionSlika).indexOf(".png") < 0) {
endPositionSlika++;
}
slikaUTekstu = htmlStringSlike.substring(startPositionSlika, endPositionSlika);
htmlStringSlike=htmlStringSlike.substring(endPositionSlika);
arraylist.add(slikaUTekstu);// when i log values are here
} else {
break;
}
}
}
return arraylist;
}
please check the size of arrayList before returning value in doInBackground() method!
Ino provides result asynchronous. That means you need to pause/block current thread until Ino request will be finished.
But it's totally unnecessary to use AsyncTask in this case. You can just move your code from onPostExecute into callback handler.
In case If you want to parse HTML asynchronous (you don't do it right now) you need run asynctask from Ino callback handler.
Problem is "return arraylist" and you reqeust.
Your request is asynchronous:
Execute step :
First: request
Ion.with(getActivity().getApplicationContext())
.load(rezultat1)
.asString()
.setCallback(new FutureCallback<String>() {...}
Second:
return arraylist
Last step:
public void onCompleted(Exception e, String result) {...}
Because request is asynchronous:
setCallback(new FutureCallback<String>() {...}
will execute after return;
You can move return code to:
while(htmlStringSlike.length()>0){
...
}
return arraylist;
Hope to help you.

How to set the textview if condition is satisfied?

Here in my previous question How to Print Message when Json Response has no fileds? Toast is working fine but if my response is showing no fileds with array and what if I want to use textview instead of Toast? can anyone help me?
public class MessageSent extends ListActivity{
private ProgressDialog pDialog;
JSONArray msg=null;
private TextView nomsg;
private ListView listview;
private ArrayList<HashMap<String,String>> aList;
private static String MESSAGE_URL = "";
private static final String MESSAGE_ALL="msg";
private static final String MESSAGEUSER_ID="msg_user_id";
private static final String MESSAGE_NAME="name";
private static final String MESSAGE_PROFILE="profile_id";
private static final String MESSAGE_IMAGE="image";
private static final String MESSAGE_CAST="cast";
private static final String MESSAGE_AGE="age";
private static final String MESSAGE_LOCATION="location";
private CustomAdapterMessage adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view_msgsent);
nomsg=(TextView)findViewById(R.id.no_message);
String strtexts = getIntent().getStringExtra("id");
System.out.println("<<<<<<<< id : " + strtexts);
MESSAGE_URL = "xxxxx"+strtexts;
// listview=(ListView)findViewById(R.id.list);
//ListView listview = this.getListView();
ListView listview = (ListView)findViewById(android.R.id.list);
new LoadAlbums().execute();
}
});
}
class LoadAlbums extends AsyncTask>> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MessageSent.this);
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected ArrayList<HashMap<String,String>> doInBackground(String... args) {
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
ArrayList<HashMap<String,String>> data = new ArrayList<HashMap<String, String>>();
String jsonStr = sh.makeServiceCall(MESSAGE_URL, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null)
{
try
{
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
msg = jsonObj.getJSONArray(MESSAGE_ALL);
// looping through All Contacts
for (int i = 0; i < msg.length(); i++)
{
JSONObject c = msg.getJSONObject(i);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(MESSAGEUSER_ID ,c.getString(MESSAGEUSER_ID));
map.put(MESSAGE_NAME,c.getString(MESSAGE_NAME));
map.put(MESSAGE_PROFILE, c.getString(MESSAGE_PROFILE));
map.put(MESSAGE_IMAGE, c.getString(MESSAGE_IMAGE));
map.put(MESSAGE_CAST, c.getString(MESSAGE_CAST));
map.put(MESSAGE_AGE, c.getString(MESSAGE_AGE)+" years");
map.put(MESSAGE_LOCATION, c.getString(MESSAGE_LOCATION));
// adding HashList to ArrayList
data.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return data;
}
protected void onPostExecute(ArrayList<HashMap<String,String>> result) {
super.onPostExecute(result);
// dismiss the dialog after getting all albums
if (pDialog.isShowing())
pDialog.dismiss();
if(msg == null || msg.length() == 0) {
//Toast.makeText(getApplicationContext(), "No response", Toast.LENGTH_LONG).show
nomsg.setText("No Message Found");
//nomsg.setBackgroundDrawable(R.drawable.borders);
}
if(aList == null) {
aList = new ArrayList<HashMap<String, String>>();
aList.addAll(result);
adapter = new CustomAdapterMessage(getBaseContext(), result);
setListAdapter(adapter);
} else {
aList.addAll(result);
adapter.notifyDataSetChanged();
}
}
}
}
As it seems you have confusions in setting up the app. Let me explain few things and also provide you some sample code.
The use of an AsynTask?
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.
But there are some operations that you would have to do in the UI while working in the background thread. In that case you make use of the,
1. onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
2. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
In your specific case as you want to set the values after the operation you have to make use of the latter mathod of the AsynTask.
The same code referring to the example you follow,
//MainActivity.java
public class MainActivity extends ListActivity {
TextView yourTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.
.
//change the ID in this line from what you are using
yourTextView = (TextView) findViewByID(R.id.id_in_activity_main);
.
.
// Calling async task to get json
new GetContacts().execute();
}
/**
* Async task class to get json by making HTTP call
* */
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
.
.
}
#Override
protected Void doInBackground(Void... arg0) {
.
.
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
if(contacts == null || contacts.length() <= 0){
yourTextView.setText("No Data");
}
}
}
}
Try this way :
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
if(contacts == null || contacts.length() <= 0){
yourTextView.setText("No Data");
}
}

Passing arguments to AsyncTask, and returning results

I have an application that does some long calculations, and I would like to show a progress dialog while this is done. So far I have found that I could do this with threads/handlers, but didn't work, and then I found out about the AsyncTask.
In my application I use maps with markers on it, and I have implemented the onTap function to call a method that I have defined. The method creates a dialog with Yes/No buttons, and I would like to call an AsyncTask if Yes is clicked. My question is how to pass an ArrayList<String> to the AsyncTask (and work with it there), and how to get back a new ArrayList<String> like a result from the AsyncTask?
The code of the method looks like this:
String curloc = current.toString();
String itemdesc = item.mDescription;
ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);
ArrayList<String> result = new ArrayList<String>();
new calc_stanica().execute(passing,result);
String minim = result.get(0);
int min = Integer.parseInt(minim);
String glons = result.get(1);
String glats = result.get(2);
double glon = Double.parseDouble(glons);
double glat = Double.parseDouble(glats);
GeoPoint g = new GeoPoint(glon, glat);
String korisni_linii = result.get(3);
So, as you see, I would like to send the string array list "passing" to the AsyncTask, and to get the "result" string array list back from it. And the calc_stanica AssycTask class looks like this:
public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(baraj_mapa.this);
dialog.setTitle("Calculating...");
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
protected ArrayList<String> doInBackground(ArrayList<String>... passing) {
//Some calculations...
return something; //???
}
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
So my question is how to get the elements of the "passing" array list in the AsyncTask doInBackground method (and use them there), and how to return an array list to use in the main method (the "result" array list)?
Change your method to look like this:
String curloc = current.toString();
String itemdesc = item.mDescription;
ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);
new calc_stanica().execute(passing); //no need to pass in result list
And change your async task implementation
public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(baraj_mapa.this);
dialog.setTitle("Calculating...");
dialog.setMessage("Please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
protected ArrayList<String> doInBackground(ArrayList<String>... passing) {
ArrayList<String> result = new ArrayList<String>();
ArrayList<String> passed = passing[0]; //get passed arraylist
//Some calculations...
return result; //return result
}
protected void onPostExecute(ArrayList<String> result) {
dialog.dismiss();
String minim = result.get(0);
int min = Integer.parseInt(minim);
String glons = result.get(1);
String glats = result.get(2);
double glon = Double.parseDouble(glons);
double glat = Double.parseDouble(glats);
GeoPoint g = new GeoPoint(glon, glat);
String korisni_linii = result.get(3);
}
UPD:
If you want to have access to the task starting context, the easiest way would be to override onPostExecute in place:
new calc_stanica() {
protected void onPostExecute(ArrayList<String> result) {
// here you have access to the context in which execute was called in first place.
// You'll have to mark all the local variables final though..
}
}.execute(passing);
Why would you pass an ArrayList??
It should be possible to just call execute with the params directly:
String curloc = current.toString();
String itemdesc = item.mDescription;
new calc_stanica().execute(itemdesc, curloc)
That how varrargs work, right?
Making an ArrayList to pass the variable is double work.
I sort of agree with leander on this one.
call:
new calc_stanica().execute(stringList.toArray(new String[stringList.size()]));
task:
public class calc_stanica extends AsyncTask<String, Void, ArrayList<String>> {
#Override
protected ArrayList<String> doInBackground(String... args) {
...
}
#Override
protected void onPostExecute(ArrayList<String> result) {
... //do something with the result list here
}
}
Or you could just make the result list a class parameter and replace the ArrayList with a boolean (success/failure);
public class calc_stanica extends AsyncTask<String, Void, Boolean> {
private List<String> resultList;
#Override
protected boolean doInBackground(String... args) {
...
}
#Override
protected void onPostExecute(boolean success) {
... //if successfull, do something with the result list here
}
}
I dont do it like this. I find it easier to overload the constructor of the asychtask class ..
public class calc_stanica extends AsyncTask>
String String mWhateveryouwantToPass;
public calc_stanica( String whateveryouwantToPass)
{
this.String mWhateveryouwantToPass = String whateveryouwantToPass;
}
/*Now you can use whateveryouwantToPass in the entire asynchTask ... you could pass in a context to your activity and try that too.*/ ... ...
You can receive returning results like that:
AsyncTask class
#Override
protected Boolean doInBackground(Void... params) {
if (host.isEmpty() || dbName.isEmpty() || user.isEmpty() || pass.isEmpty() || port.isEmpty()) {
try {
throw new SQLException("Database credentials missing");
} catch (SQLException e) {
e.printStackTrace();
}
}
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
this.conn = DriverManager.getConnection(this.host + ':' + this.port + '/' + this.dbName, this.user, this.pass);
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
receiving class:
_store.execute();
boolean result =_store.get();
Hoping it will help.

Categories

Resources