So the title says it all. I'm getting a compilation error inside of my JsonObjectRequest
I'm sure this is a really simple fix, but I'm not exactly sure how to write it. I'm still in the early stages of android development, so pardon my noob-ness. :)
Here's the code.
public class Api {
public static final String SEARCH_URL = "http://api.worldoftanks.ru/2.0/account/list/?application_id=171745d21f7f98fd8878771da1000a31&search=";
private RequestQueue mQueue;
private ArrayList<String> mNames;
public Api(Context context) {
mQueue = Volley.newRequestQueue(context);
}
public ArrayList<String> searchPlayer(String name) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, SEARCH_URL + name, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject json) {
try {
JSONArray data = json.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject c = data.getJSONObject(i);
String n = name.getString("nickname");
mNames.add(n);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error", error.getMessage());
}
}
);
mQueue.add(jsonObjectRequest);
return mNames;
}
}
As the error says, replace
public ArrayList<String> searchPlayer(String name)
with
public ArrayList<String> searchPlayer(final String name)
The argument must be declared final to ensure that it never gets changed by the code inside the method, and thus can be safely used inside the response listener.
Add final to the argument declaration:
public ArrayList<String> searchPlayer(final String name)
Related
I have a variable inside an interface method and I want it outside the interface:
String responseString;
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// i want this value out!
responseString = response.toString();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error.toString());
}
});
Of course I can't just assign responseString = response.toString() because they have different scopes. So how can I do this?
Probably this question has already been answered but I couldn't find anything similar online.
Try this once as per your JSON structure Either JSONArray or JSONObject.
//JSON Array
private JSONArray result;
//Creating a string request
StringRequest stringRequest = new StringRequest(URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONObject j = null;
try {
//Parsing the fetched Json String to JSON Object
j = new JSONObject(response);
//Storing the Array of JSON String to our JSON Array
result = j.getJSONArray("your key");
//OPTIONAL function
functionName(result);//If using function
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
The new Response.Listener<String>() {...} that you're doing in that method is called "anonymous" implementation. Indeed you are implementing the interface, but you don't hold any static reference to it in the code.
What you should do, is to have a normal implementation of the interface which of course implements the method required, but also holds a field and a special getter for your field:
public class YourStringListener implements Response.Listener<String> {
private String responseString; //<-- declare a field
#Override
public void onResponse(String response) {
this.responseString = response.toString(); //<-- set the field
}
public String getResponseString() {
return this.responseString; //<-- get the field from outside
}
}
Now, you should be able to do this:
String responseString;
YourStringListener listener = new YourStringListener(); //<-- don't implement anonimously, use the concrete implementation
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, listener, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error.toString());
}
});
System.out.println(listener.getResponseString()); //<-- access the value of response string from the concrete implementation instance
Of course, be careful you're into a listener. The value will be null until when the method onResponse will have asynchronously been called back.
i have an entry level question:
if there is external java class let's say 'Class1' inside this class there is a method called 'method1' inside this method there is Override method 'onResponse' inside this method two variables is being set 'a' and 'b'.
in the android mainActivity i called the method from the class like this:
Class1.method1();
after calling the method how i can retrieve these variables to be used in mainActivity...
thanks..
public abstract class Class1 extends Context {
final Context mcontext;
public static void method1(final Context mcontext, final String x){
StringRequest stringRequest = new StringRequest(Request.Method.POST, constants.URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject parentObject = new JSONObject(response);
JSONObject userDetails = parentObject.getJSONObject("data");
//read attributes
String a = userDetails.getString("a");
String b = userDetails.getString("b");
} catch (JSONException e) {
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mcontext, error.getMessage() ,Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("x", x);
return params;
}
};
requestHandler.getInstance(mcontext).addToRequestQueue(stringRequest);
}
Why not create a wrapper class for a and b
public class Details {
public string a;
public string b;
}
and then read/return it in the method1
public abstract class Class1 extends Context {
final Context mcontext;
public static Details method1(final Context mcontext, final String x){
Details data = new Details;
StringRequest stringRequest = new StringRequest(Request.Method.POST, constants.URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject parentObject = new JSONObject(response);
JSONObject userDetails = parentObject.getJSONObject("data");
//read attributes
data.a = userDetails.getString("a");
data.b = userDetails.getString("b");
} catch (JSONException e) {
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mcontext, error.getMessage() ,Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("x", x);
return params;
}
};
requestHandler.getInstance(mcontext).addToRequestQueue(stringRequest);
return data;
}
if you want to return more than one value you should use Android ways called Intent
but if you insist
you can use Array or ArrayList return type for the inner inner method
class Class1{
public static ArrayList<Object> method1(){
return onResponse();
}
public static ArrayList<Object> onResponse(){
return arrayList<Object>;
}
}
but still i see no reason to not use Intent
I use "token", instance of the ValueContainer class declared as final, in order to save data received from a JSON request. Inside the anonymous function, Response.Listener(), I set the value of token and it works.
Log.d("myTag", "token value1:" + token.getValue());
This line displays a correct value (non null). However, when I check the value of token.getValue() again (this time outside the anonymous function)
Log.d("myTag", "token value2:" + token.getValue());
I get token.getValue() = null. I don't understand why token's value seems to be reset to null. Am I missing something?
The full code:
public class MainActivity extends AppCompatActivity {
class ValueContainer<T> {
private T value;
public ValueContainer() { }
public ValueContainer(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ValueContainer<String> token = new ValueContainer<String>();
String getTokenUrl = "http://www.someurl.com/?somekey=somevalue";
JsonObjectRequest getTokenRequest = new JsonObjectRequest(
Request.Method.GET, getTokenUrl, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
token.setValue(response.getString("token"));
Log.d("myTag", "token value1:" + token.getValue());
mainTextView.append("Response: JsonObjectRequest successful: get_token: " + token.getValue() + "\n");
} catch (JSONException e) {
mainTextView.append("Response: JSONException: getString():" + e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mainTextView.append("Response: JsonObjectRequest failed: " + error + "\n");
}
});
Log.d("myTag", "token value2:" + token.getValue());
}
You can change the "real content" of a "final" Object, but you can't change it's address, as the example said blew.
String stringTest = "test String";
StringBuffer normalTest = new StringBuffer(stringTest);
normalTest = normalTest.append(" end");
normalTest.delete(0, 5);
System.out.println(normalTest);
final StringBuffer finalTest = new StringBuffer(stringTest);
// finalTest = finalTest.append(" end"); // can't work;
finalTest.delete(0, 5);
System.out.println(finalTest);
you can test by your code as
//token = new Token("...")// can't work
token.changeTheToken("...")// work ok
Im trying to download data from a server in the form of a JSON object, parse that object then use the data elsewhere in my app.
Ive created a class which downloads the data (confirmed with a Log.v statement)
The trouble is that i want to display the results in a RecyclerView and the List of objects that i generate after parsing the JSON response does not get generated until after the adapter method is called from my main class.
So my question is, given the code below, how can i ensure that the on response method only exits once the parseResponse method has finished. Currently i am returning the (Null) _releaseList from my requestAndPareseReleaseList method.
public class ParseReleaseJSON extends JSONObject {
String _url;
List<ReleaseInfo> _releaseList = Collections.emptyList();
ParseReleaseJSON(String url) {
super();
_url = url;
}
public List<ReleaseInfo> requestAndParseReleaseList(Context _context){
JsonObjectRequest jsObReq = new JsonObjectRequest(Request.Method.GET, _url, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
releaseList = parseResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.v("err", "nosuccess");
}
});
MySingleton.getInstance(_context).addToRequestQueue(jsObReq);
return _releaseList;
}
private List parseResponse(JSONObject response) {
List<ReleaseInfo> list = new ArrayList<>();
if(response == null || response.length() == 0){
return list;
}
try {
if(response.has("results")){
JSONArray resultsArray = response.getJSONArray("results");
for(int i = 0, j = 6; i < j; i++){
ReleaseInfo release = new ReleaseInfo();
JSONObject tempObj = resultsArray.getJSONObject(i);
release.title = tempObj.getString("title");
release.date = tempObj.getString("date");
list.add(release);
}
return list;
}
} catch (JSONException e) {
e.printStackTrace();
}
return list;
}
}
I'm currently creating an app utilizing Facebook's Android SDK. Below is the attached code:
private void checkIfPostLiked(final String post_id) {
String isLiked = null;
new Request(Session.getActiveSession(), post_id + "/likes/", null,
HttpMethod.GET, new Request.Callback() {
#Override
public void onCompleted(Response response) {
try {
JSONObject json;
json = new JSONObject(response.getRawResponse());
JSONArray jArray = json.getJSONArray("data");
for (int i = 0; i < jArray.length(); i++) {
user_like_name = jArray.getJSONObject(i)
.get("name").toString();
if (user_like_name.equals(user_me.getName())) {
isLiked= "true";
}
else{
isLiked = "false";
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Get message data
}
}).executeAsync();
}
I would like to return the string isLiked, and return it, but the issue is that I keep on getting Cannot refer to a non-final variable isLiked inside an inner class defined in a different method. I have to use this method (checkifPostLiked) as a function in another iteration within a loop, therefore putting the variable isLiked as member variable would not work as well. I really hope that anyone could help me on this!
You need to initialize isLiked and finalize it:
final String isLiked = new String();
/* Rest of the code remains the same. */
new Request(Session.getActiveSession(), post_id + "/likes/", null,
HttpMethod.GET, new Request.Callback() {
....
....
}