Accessing null ArrayList from JSON in Main Activity - android

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();

Related

How can i print arraylist from class AsyncTask?

I want to print an ArrayList. I have receive value arraylist from class AsyncTask, in MainActivity, I have value ArrayList, but when I print ArrayList, my app is not working. Please help me!
MainActivity
{
executeLoadProduct();
arraylistgroup = new ArrayList<String>();
arraylistgroup=TaskLoadProductGroup.getvaluearraylist();
String[] mStringArray = new String[arraylistgroup.size()];
mStringArray = arraylistgroup.toArray(mStringArray);
for (int i = 0; i < mStringArray.length; i++) {
System.out.println("string is2" + (String) mStringArray[i]);
}
executeLoadProduct
private void executeLoadProduct() {
// execute task load product
loadProductGroup = new TaskLoadProductGroup(MainActivity.this);
loadProductGroup.execute();
}
AsyncTask
public class TaskLoadProductGroup extends AsyncTask<String, Void, ArrayList<String>> {
private ActionBarActivity actionBarActivity;
private Context context;
private static ArrayList<String> arrayListgroup;
public TaskLoadProductGroup(ActionBarActivity actionBarActivity) {
this.actionBarActivity = actionBarActivity;
this.context = actionBarActivity.getApplicationContext();
}
#Override
protected void onPreExecute() {
///show progress loading
super.onPreExecute();
}
#Override
protected ArrayList<String> doInBackground(String... url) {
ArrayList<String> listProductgroup = null;
try {
Server server = new Server();
ResListProduct resListProduct = server.getListProducts(context);
//init list item for listview home product
listProductgroup = initItemProduct(resListProduct);
} catch (Exception e) {
}
return listProductgroup;
}
public static ArrayList<String> initItemProduct(ResListProduct rsProduct) {
List<GroupProduct> groups = rsProduct.getGroups();
arrayListgroup = new ArrayList<String>();
for (GroupProduct group : groups) {
// add header group
String s = group.getName();
arrayListgroup.add(s);
}
getvaluearraylist();
// getVarialty();
return arrayListgroup;
}
public static ArrayList<String> getvaluearraylist()
{
return arrayListgroup;
}
#Override
protected void onPostExecute(ArrayList<String> listProductgroup) {
super.onPostExecute(listProductgroup);
}
}
I couldn't identify why are you doing so complex code to print the ArrayList. You can just print that inside onPostExecute method like this,
#Override
protected void onPostExecute(ArrayList<String> listProductgroup) {
super.onPostExecute(listProductgroup);
for (String value : listProductgroup){
Log.d("myTag", value);
}
}
OR
Use loadProductGroup.execute().get() method, but remember this will freeze your UI.

"Can't create handler inside thread that has not called Looper.prepare()" in AsyncTask

I got a weird problem with an android activity : I re-used one of my previous activity that works well, but this time all I got is "Can't create handler inside thread that has not called Looper.prepare()"
I tried to debug, and everything in the async task is performing well but when I reach then end of onPostExecute() the error is raised.
So I tried to disable my process about the process dialog, the only change is that it's crashing on line upper.
Here is the code :
public class DateActivity extends ActionBarActivity{
ProgressDialog mProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_date);
ActionBar actionBar = this.getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(getResources().getString(R.string.actionbar_titre_date));
if (VerifConnexion.isOnline(this)) {
this.mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.loading),
getResources().getString(R.string.loading), true);
new QueryForDateTask().execute(this.mProgressDialog, this, this.getApplicationContext());
} else {
...
}
});
alertDialog.show();
}
}
private class QueryForDateTask extends
AsyncTask<Object, Void, ArrayList<String>> {
private ProgressDialog mProgressDialog;
private Activity act;
private Context context;
protected ArrayList<String> doInBackground(Object... o) {
this.mProgressDialog = (ProgressDialog) o[0];
this.act = (Activity) o[1];
this.context = (Context) o[2];
ArrayList<String> listeDate = this.parseJSON(this.startQuerying());
return listeDate;
}
public JSONObject startQuerying() {
JSONRequest jr = new JSONRequest();
String from = getResources().getString(R.string.api_param_from);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.FRANCE);
from += "=" + sdf.format(new Date());
String url = getResources().getString(
R.string.api_dates_json);
JSONObject jo = jr.getJSONFromUrl(url + "?" + from);
return jo;
}
public ArrayList<String> parseJSON(JSONObject jsonObject) {
ArrayList<String> l = new ArrayList<String>();
try {
JSONArray array = jsonObject.getJSONArray("dates");
if (array != null) {
for (int i = 0; i < array.length(); i++) {
String type = array.getString(i);
l.add(type);
} // fin parcours JSONArray
}
} catch (Exception _e) {
}
return l;
}
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(ArrayList<String> lDate) {
// Create items for the ListView
DateAdapter adapter = new DateAdapter(this.context, R.layout.searchitem_date, lDate, this.act);
// specify the list adaptor
((ListView)findViewById(R.id.list)).setAdapter(adapter);
this.mProgressDialog.dismiss();
}
} // fin async
}
I tried this to replace the call to the AsyncTask :
runOnUiThread(new Runnable() {
public void run() {
QueryForDateTask task = new QueryForDateTask();
task.execute(DateActivity.this.mProgressDialog, DateActivity.this, DateActivity.this.getApplicationContext());
}
});
(like explained in Asynctask causes exception 'Can't create handler inside thread that has not called Looper.prepare()' as far as I understood), but the result is exactly the same.
So I can't understand why it is not working in this activity despite all is ok for the other ones of the project.
Any clue ?
Thank a lot for all ideas :)
Just a post to mark the trouble as resolved :
the adapter i used was buggy in parsing parameters and throwed a NullPointerException.
I just fixed it, the AsyncTask is now running without problem.

Passing Aysnc Task Results to parent Calling Class

I need to pass the async task result to the calling class. I have created a separate ASync class which is called from other classes. I am passing the response from Async task in "Post Execute" method to calling class method but getting null point exception. Below is my calling method in
public boolean getCategories() {
serUri = "categories.json";
WebServiceAsyncTask webServiceTask = new WebServiceAsyncTask();
webServiceTask.execute(serUri,this);
return true;
}
The method to be executed with result from below aysnc task is
public void writeJSONArray(final JSONArray result)
{
try {
for (int i=0; i<result.length();i++){
JSONObject c = result.getJSONObject(i);
String name = c.getString("catname");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
WebServiceAsyncTask Class:
public class WebServiceAsyncTask extends AsyncTask<Object,Void,JSONArray> {
ROMSjson roms;
private static JSONArray json = null;
private Context context = null;
protected JSONArray doInBackground(Object... params) {
// TODO Auto-generated method stub
String serviceUrl = (String) params[0];
final HTTPHelper httph = new HTTPHelper(serviceUrl,context);
if(serviceUrl.equalsIgnoreCase("categories.json")) {
json = httph.fetch();
}else if(serviceUrl.equalsIgnoreCase("categories/create"))
{
}
return json;
}
#Override
protected void onPostExecute(JSONArray result) { // invoked on the ui thread
roms.writeJSONArray(result);
super.onPostExecute(result);
}
I am getting null point exception when roms.writeJSONArray(result) is called. The result is correctly received before this command. I checked with Log statement. Also if I write the writeJSONArray method in my Async class instead of calling class, all works fine.
I am not sure if I am missing something in passing the result or while calling methods. Please advise. Thanks.
null pointer exception
because roms is null
you are declaring ROMSjson roms; inside WebServiceAsyncTask but not initializing it !
and using it inside `onPostExecute(JSONArray result)
roms.writeJSONArray(result);` // here roms in null
so initialize roms before using it !
Here is the problem:
else if(serviceUrl.equalsIgnoreCase("categories/create"))
{
// if it falls to this condition then your json object appears to be null
}
Hope this helps.
Interface is the best way for passing data between classes.
create a public interface
public interface WebCallListener{
void onCallComplete(JSONArray result);
}
what to do in your class?
public class WebServiceAsyncTask extends AsyncTask<Object,Void,JSONArray> {
ROMSjson roms;
private static JSONArray json = null;
private Context context = null;
//update
private WebCallListener local;
public WebServiceAsyncTask(WebCallListener listener){
local=listener;
}
/////
protected JSONArray doInBackground(Object... params) {
// TODO Auto-generated method stub
String serviceUrl = (String) params[0];
final HTTPHelper httph = new HTTPHelper(serviceUrl,context);
if(serviceUrl.equalsIgnoreCase("categories.json")) {
json = httph.fetch();
}else if(serviceUrl.equalsIgnoreCase("categories/create"))
{
}
return json;
}
#Override
protected void onPostExecute(JSONArray result) { // invoked on the ui thread
//update
super.onPostExecute(result);
local.onCallComplete(result);
}
From Your Calling class.
public class CallingClass extends Activity{
protecte void oncreate(Bundle b){
new WebServiceAsyncTask(new WebCallListener() {
#Override
public void onCallComplete(JSONArray result) {
//play with your response
}
});
}
}

How to place while loop inside Asynctask - 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

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