Here is my Code:
public class ServerCall {
Context context;
public int cartCount;
public ServerCall(Context context){
this.context=context;
}
public Integer addCartItem(RequestObject requestObject) {
new AddToCartList().execute(requestObject);
Log.d("count",String.valueOf(cartCount));
return cartCount;
}
public class AddToCartList extends AsyncTask<RequestObject, Void, JSONObject> {
#Override
protected JSONObject doInBackground(RequestObject... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(arg0[0], ServiceHandler.POST);
// List<Products> result = new ArrayList<Products>();
Log.d("Response: ", "> " + jsonStr);
JSONObject product = new JSONObject();
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
product = jsonObj.getJSONObject("rsBody");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return product;
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
try {
if (result != null) {
String status = result.getString("status");
int totalCartItem = result.getInt("totalCartItem");
/* cartHelper = new CartHelper();
cartHelper.setStatus(status);
cartHelper.setTotalCartItem(totalCartItem);*/
cartCount=totalCartItem;
Log.d("status",status);
Log.d("totalCartItem",String.valueOf(cartCount));
Toast.makeText(context, status, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
}
}
We didn't get value of global variable cartCount which I set inside AddToCartList class and try to get its value from addCartItem() function from where AddToCartList is called but we get null value.
I think that the main problem in your solution is the fact that you're trying to edit ServerCall variable from an Inner class, this would work only if cartCount is static, and I suggest you wait for your task to be finished as some people have already mentioned, using the get method new AddToCartList().execute().get()
The problem is, ServerCall and AddToCartList are not the same class, so you must first get a reference to the servercall in addtocartlit, then reference the cartCount using your reference to the servercall instance, like call.cartCount, instead of cartcount, unless its an inner class which it does not appear to be.
Secondly, you must save a reference to the addtocartlist asynctask inside addCartItem() ,then call its .get() method after starting it, this will ensure it finishes before you try to log the new value.
Related
I'm trying to access a string outside the parse query, it's not working outside query but it works inside the query.
I declared the global variable and and tried to access it but it's still not working, instead of string it returns null.
I'm new to Java and Android so please forgive me if it's stupid question.
Any help would be appreciated.
public class ActivityQuiz extends AppCompatActivity {
ArrayList<String> answerList = new ArrayList<>();
int c=0;
String Answer = "correct";
String selectedOption;
public static String checkAns;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
ParseQuery<ParseObject> query = ParseQuery.getQuery("Question");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> questions, ParseException e) {
if (e == null) {
for (ParseObject question : questions) {
answerList.add(question.getString(Answer));
checkAns = getanswerList.get(c);
Log.d("String check",""+checkAns); //here it's working
}
} else {
e.printStackTrace();
}
}
});
try{
String checkanswer = checkAns ; // here returns null instead of string
Log.d("String checkans",""+checkanswer);}
catch (Exception e)
{
e.printStackTrace();
Log.d("Error", "Error, Not Working");
}
}
There is very simple problem. In first instance you are getting the value of checkAns from the data after hitting the API (in background). So if data come from API it will be non-null.
In later part, since the API response takes time, try-catch block will be executed before it sets value in checkAns So checkAns is equal to initialised value which is null.
Ideally, you should use the value of checkAns only inside done() method.
add your try-catch code inside ParseQuery like this:
ParseQuery<ParseObject> query = ParseQuery.getQuery("Question");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> questions, ParseException e) {
if (e == null) {
for (ParseObject question : questions) {
answerList.add(question.getString(Answer));
checkAns = getanswerList.get(c);
Log.d("String check",""+checkAns); //here it's working
// ....Add your try catch code.....
try{
String checkanswer = checkAns ; // also working well
Log.d("String checkans",""+checkanswer);}
catch (Exception e)
{
e.printStackTrace();
Log.d("Error", "Error, Not Working");
}
}
} else {
e.printStackTrace();
}
}
});
That is normal behavior for asynchronous functions.
By the time your try/catch block is executed checkanswer is still null because your query takes time to execute. Once done() is executed you'll have your string.
If you must have your value in that block, you can sleep a second or two and check if checkanswer is no longer null. Be careful with sleeps as they will hang your program if you do use them in your main thread
The Problem is that your try catch block will execute befor your query is done means the overriden done method will call and set the checkAns after you execute the try catch block.
If you will use the findInBackground method than make a method in your done method in which you will do all your stuff like:
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> questions, ParseException e) {
if (e == null) {
successful(questions);
} else {
e.printStackTrace();
}
}
});
private void successful(List<ParseObject> questions){
for (ParseObject question : questions) {
answerList.add(question.getString(Answer));
Log.d("String checkans",""+checkanswer);
}
String checkanswer = getanswerList.get(c);
}
else you can use the find() method:
List<ParseObject> questions = query.find();
for (ParseObject question : questions) {
answerList.add(question.getString(Answer));
Log.d("String checkans",""+checkanswer);
}
String checkanswer = getanswerList.get(c);
I am trying to get information from my AsyncHttpClient in my Android app, and I need to use an interface to set the variable so I can use it in my main method. However, when I run System.out.println(PostResponse);, I am getting null.
I don't understand why, because if I put the line in my callback() method, I get the values.
From my main method:
try {
JSONArray PostResponse = PerformPostRequest(new OnJSONResponseCallback() {
#Override
public JSONArray onJSONResponse(boolean success, JSONArray response) {
System.out.println("Response: " + response); //This is returning the correct value
return response;
}
}, PostData);
System.out.println("Useable: " + PostResponse); //This is returning null.
} catch (Exception e) {
e.printStackTrace();
}
The interface:
public interface OnJSONResponseCallback {
public JSONArray onJSONResponse(boolean success, JSONArray response);
}
The AsyncHttpClient:
public JSONArray PerformPostRequest(final OnJSONResponseCallback callback, JSONObject PostData) {
//To authenticate against the API we need the user's credentials
String Email = getSharedPreferences(ctx).getString("Email","");
String Password = getSharedPreferences(ctx).getString("Password","");
final JSONArray[] ResponseStorage = new JSONArray[1];
//Add the credentials to post data
try{
PostData.put("email", Email);
PostData.put("password", Password);
} catch (Exception e){
e.printStackTrace();
}
//Then we need to put the post data into request parameters so we can send them in the call.
RequestParams RequestParameters = new RequestParams();
RequestParameters.put("data", PostData);
//This is the client we will use to make the request.
AsyncHttpClient client = new AsyncHttpClient();
client.post(AppHost + "MyMeetings.php", RequestParameters, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
String ResponseString = new String(responseBody);
ResponseStorage[0] = new JSONArray(ResponseString);
System.out.println(ResponseStorage[0] + "<============="); //Returns with the array
callback.onJSONResponse(true, ResponseStorage[0]);
} catch (Exception e) {
Log.e("Exception", "JSONException on success: " + e.toString());
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
try {
Toast.makeText(ctx, "Error: " + statusCode, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("Exception", "JSONException on failure: " + e.toString());
}
}
});
JSONArray ResponseArray = new JSONArray();
try{
System.out.println(ResponseStorage[0] + "<==============="); //Returning null?
ResponseArray = ResponseStorage[0];
} catch (Exception e){
e.printStackTrace();
}
System.out.println("ResponseArray" + ResponseArray); //Returns null
return ResponseArray;
}
Where am I going wrong? I think it is something to do with my call in the main method.
Edit:
1) I tried to return the ResponseArray (set in onsuccess) but I can't return it from onsuccess because it is public void. When I tried to change it to public JSONArray, I get an incompatible return type error.
2) I have updated the method so it returns something other than null, however, it still returns as null, even when I am printing it inside the AsyncHttp.
The general idea behind the asynchronous calls is that:
the asynchronous method call (in your case PerformPostRequest) returns immediately and does not return the expected result - instead it returns either just an accept confirmation or an object from which you can sometimes in the future get the result (such as an instance of a Future)
you provide the method a callback interface (in your case OnJSONResponseCallback) or the method returns an instance of a callback interface, and you check regularly if there is already a result ready.
You should not expect that the asynchronous method returns the result immediately, this is exactly the opposite of asynchronous call.
Here is the rough idea expressed by pictures. It is just an overall picture of the whole idea, so the implementation details may be quite different!
I was trying to set the variable from the PerformPostRequest(), which by default does not get called. At the top of my class, I set a
public JSONArray[] PostResponse = new JSONArray[1];
and updated the bit where I was calling the post request to the following:
//Make a post request
try {
JSONObject PostData = new JSONObject();
PostData.put("action","test");
PerformPostRequest(new OnJSONResponseCallback(){
#Override
public JSONArray onJSONResponse(boolean success, JSONArray response) {
PostResponse[0] = response;
System.out.println(PostResponse[0]); //This will be replaced by calling the method I want to call.
return PostResponse[0];
}
}, PostData);
System.out.println(PostResponse[0]);
} catch (Exception e){
e.printStackTrace();
}
In the AsyncTask android. When calling a method in another class gets an exception which equals to null in the doInBackGround() task.
Even the hard coded inside the rest.request(url, method, json) doesn't work
protected JSONArray doInBackground(Void... arg0) {
try {
return rest.request(url, method, json); // <-- returns json array
} catch (Exception e) {
this.e = e;
}
return null; // <--- returning this null
}
Other things are like this,
private class doRequest extends AsyncTask<Void, JSONArray, JSONArray>
protected void onPostExecute(JSONArray data)
/*rest client class*/
public class AndrestClient {
// The client to use for requests
DefaultHttpClient client = new DefaultHttpClient();
public JSONArray request(String url, String method, String json) throws RESTException {
if (method.matches("GET")) {
return get(url);
} else if (method.matches("POST")) {
return post(url, json);
} else if (method.matches("PUT")) {
//return put(url, data);
} else if (method.matches("DELETE")) {
//return delete(url);
}
throw new RESTException("Error! Incorrect method provided: " + method);
}
public JSONArray get(String url) throws RESTException {
String jsonjr = "['Chanuthi','Damsith','Dunili','Isath','Minuka','Uvin','Vidath']";
JSONArray jsonAraay = null;
try {
jsonAraay = new JSONArray(jsonjr);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonAraay;
}
}
The exception I got is e=null. All the other things work properly. When I am hard coding the result inside in the doInBackGround it works properly. Also the rest client get method returns the exact thing.
It appears you're using AsyncTask improperly. Firstly, you must subclass/nest your AsyncTask as per the Android documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
In addition, you should follow the fundamental rules for calling methods of an outter class from a nested class.
There are some alternatives, like:
Create the AndrestClient object in onPreExecute() of the AsyncTask
Pass the AndrestClient object to the doInBackground as a parameter, then call its methods by doing something like this in the outter class:
doRequest.execute(rest);
I'm new im Java, and im trying to return with a defined string variable at the end of the function, but eclipse keeps saying that it's cannot be resolved to a variable, and wants me to define it. Probably it's because im define the variable within the Try{} brackets, but how else could i do it?
public class readtextfile extends AsyncTask<String, Integer, String>{
private TextView description;
public readtextfile(TextView descriptionTextView){
this.description = descriptionTextView;
}
#Override
protected String doInBackground(String... params) {
try {
URL url = new URL("http://example.com/description1.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
String result = "";
while ((line = in.readLine()) != null) {
//get lines
result+=line;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate() {
//called when the background task makes any progress
}
protected void onPreExecute() {
//called before doInBackground() is started
}
#Override
protected void onPostExecute(String result) {
this.description.setText(result);
}
}
Move the local variable declaration
String result = "";
to before the try block. If you define a variable within a block it's not available outside that block.
Alternatively you could move return result; to the end of the try block, but then you'd have to add another return statement at the end of the method, for the cases where an exception was thrown and got caught.
Or you could get rid of the try-block, move the exception-handling to elsewhere, and let any exceptions get thrown.
URL url = null;
String result = "";
Then inside your try, catch block.
try {
url = ....;
.
.
result = ....;
Declare the variable outside the try block.
I have inner class which run code in UI thread and I need to pass variable to run() method.
I try to pass final res without array but I've got an error that it's necessary to use array res[0].
In this case I need to initialize res[] because it throws NullPointerException.
Are there any other way to pass variable into inner class?
private String sendRequest(String url, String... data) {
final Connection.Response[] res = {};
...
try {
final Connection connection = Jsoup.connect(url)
.method(Connection.Method.POST)
.cookies(cookies)
.timeout(30000)
.ignoreContentType(true);
if (data != null) {
connection.data(data);
}
((Activity) con).runOnUiThread(new Runnable() {
#Override
public void run() {
try {
res[0] = connection.execute();
} catch (IOException e) {
e.printStackTrace();
}
}
});
result = Jsoup.parse(res[0].parse().outerHtml(), "UTF-8").text();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
res[] is defined as an empty array (no locations), then you try to assign to something to location 0 in res[], there is no location 0 because it needs to be given a size...
final Connection.Response[] res = new Connection.Response[requiredArraySize];
In your case, requiredArraySize is probably 1.