I have a method which returns an arraylist, and it is populated from jsonarray
jsonrequest works fine, but when i call the method the arraylist returns a size of 0 even it is populated.
Below is the code, what am i doing wrong
private ArrayList<String> queryRes(String url, String searchString) {
final ArrayList<String> mylist = new ArrayList<>();
AsyncHttpClient client = new AsyncHttpClient();
client.get(url + searchString,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray jsonArray) {
for(int i =0; i < jsonArray.length(); i++) {
mylist.add(i, jsonArray.optJSONObject(i).optString("id"));
//Check if it is added to the list
Log.d("Try: ", mylist.get(i));
}
}
#Override
public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
}
});
return mylist;
}
onSuccess() called when you get the response means AsynHttp call is done in another thread so your return statement call before onSucess thats why size is 0.
you can verify it on debugger
my suggestion is call a method from onSuccess() so you will get Arraylist
If you are doing everything in a single class
public void populateList(String url, String searchString)
{
final ArrayList<String> mylist = new ArrayList<>();
AsyncHttpClient client = new AsyncHttpClient();
client.get(url + searchString,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray jsonArray) {
for(int i =0; i < jsonArray.length(); i++) {
mylist.add(i, jsonArray.optJSONObject(i).optString("id"));
//Check if it is added to the list
Log.d("Try: ", mylist.get(i));
}
onListPopulated(myList);
}
#Override
public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
}
});
}
A method to do something with the list
public void onListPopulated(ArrayList<String> list)
{
//do something with the list
}
Related
MainActivity.java
public class MainActivity extends AppCompatActivity {
String server_ip = "192.168.252.100";
String url = "http://"+server_ip+"/lib/androidAPI.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] list = {"Action","Adventure", "Family"};
for(int x=0;x<list.length;x++){
int y = x;
movie_class test = new movie_class();
test.getJsonResponse("Get__Movies_By_Genre_Limit", list[x], getApplicationContext(), new VolleyCallback() {
#Override
public void onSuccess(JSONArray result2) {
try {
System.out.println("array list using y as index: ("+y+")="+list[y]);
System.out.println("-Database Query Results");
for (int j = 0; j < result2.length(); j++) {
JSONObject obj = result2.getJSONObject(j);
System.out.println("--(" + j + ")" + obj.getString("name"));
}
}catch (JSONException e){
}
}
#Override
public void onError(String result) {
System.out.println("(error) populate genres " + result);
}
});
}
}
public interface VolleyCallback {
void onSuccess(JSONArray result);
void onError(String result);
}
}
movie_class.java
public class movie_class extends MainActivity{
public void getJsonResponse(String getType, String parameters, Context mainContext, final VolleyCallback callback) {
StringRequest strReq = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
//JSONArray array = new JSONArray();
JSONArray array = jsonObject.getJSONArray("array");
callback.onSuccess(array);
}catch (JSONException e){
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
callback.onError(volleyError + "");
}
}){
#Override
public String getBodyContentType() {
// as we are passing data in the form of url encoded
// so we are passing the content type below
return "application/x-www-form-urlencoded; charset=UTF-8";
}
#Override
protected Map<String, String> getParams() {
// below line we are creating a map for storing our values in key and value pair.
Map<String, String> params = new HashMap<String, String>();
// on below line we are passing our key and value pair to our parameters.
params.put("getType", getType);
params.put("parameters", parameters);
// at last we are returning our params.
return params;
}
};
Volley.newRequestQueue(mainContext).add(strReq);
}
}
Output 1:
array list using y as index: (0)=Action
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (2)=Family
-Database Query Results
--(0)Cocomelon
--(1)Finding Dory
array list using y as index: (1)=Adventure
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
Output 2 without changing the codes:
array list using y as index: (1)=Adventure
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (0)=Action
-Database Query Results
--(0)Air Force One
--(1)Ant-Man
array list using y as index: (2)=Family
-Database Query Results
--(0)Cocomelon
--(1)Finding Dory
Question is why the for loop index (x) is not in order or randomly change order when using it inside the movie_class.getJsonResponse?
I'm using that technique many times in php but it was different in java.
I've solve the problem by manipulating the data in php file so that I will just call one request in client side android. :)
textView = findViewById(R.id.textVieww);
String url = "https://zenquotes.io/api/random";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
final String myResponse = response.body().string();
try {
JSONArray jsonarray = new JSONArray(myResponse);
for(int i=0; i<jsonarray.length(); i++) {
JSONObject obj = jsonarray.getJSONObject(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
Quote.this.runOnUiThread(() ->
textView.setText(myResponse));
}
}
});
}
This is the part im stuck on i think im on the right track but not sure where to go from here im trying to get the "q" information from the returned url and the "a" information but it just outputs everything any suggestions?
What was your problem
Even when you parsed JSON string, you were still using the myResponse string in your textView.setText() method.
Continuing your code snippet
your code snippet is quite short, but i do think i can quite understand what you mean.
So let's say that we have Activity, which is called MainActivity and in that activity we have two views, one TextView called that has an id of tv_author_and_quote and one Button which has a xml id btn_request_quote.
The button has an OnClickListener which calls method requestForQuote().
Our onCreate + the variables of Button and TextView looks like this:
TextView tvAuthorAndQuote;
Button btnRequestQuote;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvAuthorAndQuote = findViewById(R.id.tv_author_and_quote);
btnRequestQuote = findViewById(R.id.btn_request_quote);
btnRequestQuote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
requestForQuote();
}
});
}
And then we have a code itself for method requestForQuote():
public void requestForQuote() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
if (response.isSuccessful()) {
final String myResponse = Objects.requireNonNull(response.body()).string();
String myFormattedQuote = "";
try {
JSONArray jsonarray = new JSONArray(myResponse);
for(int i=0; i<jsonarray.length(); i++) {
JSONObject obj = jsonarray.getJSONObject(i);
String quote = obj.getString("q");
String author = obj.getString("a");
Log.d(TAG, "onResponse: quote:" + quote);
Log.d(TAG, "onResponse: author:" + author);
myFormattedQuote = author + ": " + quote;
}
} catch (JSONException e) {
e.printStackTrace();
}
final String myFinalQuote = myFormattedQuote;
MainActivity.this.runOnUiThread(() -> {
if (!myFinalQuote.equals("")) {
tvAuthorAndQuote.setText(myFinalQuote);
} else {
tvAuthorAndQuote.setText(myResponse);
}
});
}
}
});
}
The code above basically uses your existing solution, but instead of setting the text of textView with myResponse string, it parses the json array and gets a quote and an author from it. Then it just logs it (just for testing purposes), then it constructs the string which gets displayed to the if there is any, otherwise it prints the response. That it is.
Using Gson library
import it into your gradle dependecies
implementation 'com.google.code.gson:gson:2.8.7'
Write short "holder" class called Quote
public class Quote {
public Quote() {
}
String q;
String a;
String h;
public String getQ() {
return q;
}
public void setQ(String q) {
this.q = q;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getH() {
return h;
}
public void setH(String h) {
this.h = h;
}
#NonNull
#NotNull
#Override
public String toString() {
return a + ": " + q;
}
}
Then the requestForQuote() method could look something like this:
public void requestForQuoteWithGson() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
if (response.isSuccessful()) {
final String myResponse = Objects.requireNonNull(response.body()).string();
Type listType = new TypeToken<ArrayList<Quote>>(){}.getType();
List<Quote> yourClassList = new Gson().fromJson(myResponse, listType);
if (yourClassList != null && yourClassList.size() > 0) {
final Quote quote = yourClassList.get(0);
if (quote != null) {
myQuotes.add(quote);
MainActivity.this.runOnUiThread(() ->
tvAuthorAndQuote.setText(quote.toString())
);
}
}
}
}
});
}
I'm trying to convert a string array list to a JSONArray then send it to a remote server
I expect it to send my array in a JSONarray format
this is the error "'java.lang.String org.json.JSONObject.getString(java.lang.String)' on a null object reference"
My array got 2 elements,
when i try to fetch them in the log.d : list ja [null,null]
This is the code i'm using
public void sendCommande (){
bt_newCommande.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//----------------------------------
StringRequest stringRequest = new StringRequest(Request.Method.POST,url_ProdCommande, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG,"element envoie !");
//listProRest.clear();
//adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String,String>();
JSONArray ja = new JSONArray(db.afficherTousProduit());
Log.d(TAG,"list ja "+ja.toString());
for(int i =0;i<ja.length();i++){
JSONObject j = ja.optJSONObject(i);
/*
try {
params.put("idProduit",j.getString(db.afficherTousProduit().get(i).getIdProduct()));
params.put("qte",j.getString(String.valueOf(db.afficherTousProduit().get(i).getQtePro())));
params.put("heure",j.getString(db.afficherTousProduit().get(i).gethCollete()));
params.put("date",j.getString(db.afficherTousProduit().get(i).getDateCollete()));
} catch (JSONException e) {
e.printStackTrace();
}
*/
}
//params.put("id",arrayList.get(position).getIdProduct());
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
});
}
It looks like something is going wrong with
db.afficherTousProduit().get(i).getIdProduct()
I would set a breakpoint and check that the db is returning what you expect it to return.
From looking at your code, it seems like you are doing extra work converting to and from JSON several times. I could be wrong, but I think this could be cleaned up like so:
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String,String>();
JSONArray ja = new JSONArray(db.afficherTousProduit());
Log.d(TAG,"list ja "+ja.toString());
// Begin iterating through the JSON Array
for (int i=0; i < arr.length(); i++) {
// Get current JSON Object at index i
JSONObject j = arr.getJSONObject(i)
try {
// Return the specified value associated with the String for the current object
params.put("key",j.getJsonString("key");
} catch (JSONException e) {
e.printStackTrace();
}
}
//params.put("id",arrayList.get(position).getIdProduct());
return params;
}
It shouldn't require more than one db access to get the json array, and then it's a simple matter of iterating through each object and grabbing what you need from it. Check out the Java docs for more info.
i wrote the code to an activity it work perfect but when i writhing them to a java class and send the result to the activity is not show anything to text view.
public class TheaudiodbWebData {
private String result = "";
public String getResult() {
return result;
}
public TheaudiodbWebData() {
getBiographyData();
}
private void getBiographyData() {
String url = "https://www.theaudiodb.com/api/v1/json/1/search.php?s=coldplay";
AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new TextHttpResponseHandler() {
#Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
}
#Override
public void onSuccess(int statusCode, Header[] headers, String responseString) {
parseBiographyData(responseString);
}
});
}
private void parseBiographyData(String response) {
try {
Gson gson = new Gson();
TheaudiodbArtistBio bio = gson.fromJson(response, TheaudiodbArtistBio.class);
result = bio.getArtists().get(0).getStrArtist();
} catch (Exception e) {
}
}
}
and this is the Activity code :
public class BiographyActivity extends AppCompatActivity {
TextView test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_biography);
test=findViewById(R.id.test);
TheaudiodbWebData bio=new TheaudiodbWebData();
test.setText(bio.getResult());
}
}
If you are not passing data from one Activity to another Activity and you are getting the result than problem is clear. Part of code which you are executing in onCreate() method:
TheaudiodbWebData bio=new TheaudiodbWebData();
test.setText(bio.getResult());
is executed immediately but you are getting results over the Internet which means that data is not received immediately (connecting server -> getting result -> returning result = takes some time) that is why you have callback methods onFailure and onSuccess which are triggered after result is returned from the Internet depending was it successful or fail.
So solution is to create your own interface with method where you can pass the result than implement that interface and create your own callback methods.
Or more simpler solution move this part of code directly into your Activity and set the the result to the TextView in onSucces method for example:
private void getBiographyData() {
String url = "https://www.theaudiodb.com/api/v1/json/1/search.php?s=coldplay";
AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new TextHttpResponseHandler() {
#Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
}
#Override
public void onSuccess(int statusCode, Header[] headers, String responseString) {
test.setText(responseString);
}
});
}
After that simply call this method inside onCreate() like:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_biography);
test=findViewById(R.id.test);
getBiographyData();
}
Question1: How to get response value in onResponse function.
Question2: I create cauHoiArrayList. when I check and get cauHoiArrayList values in onResponse function => it worked. But if I check and get cauHoiArrayList values in GETDATA function ==> it did not work. How to I get cauHoiArrayList values.
Thanks you,
This is my code details:
public void GetCauHoi(String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray array = new JSONArray(response);
cauHoiArrayList = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
_id = object.getInt("_ID");
cauhoi = object.getString("CauHoi");
tenmh = object.getString("TenMH");
tenmonhoc = object.getString("TenMonHoc");
dapan_a = object.getString("DapAn_A");
dapan_b = object.getString("DapAn_B");
dapan_c = object.getString("DapAn_C");
dapan_d = object.getString("DapAn_D");
dapandung = object.getString("DapAnDung");
hinhanh = object.getString("HinhAnh");
dokho = object.getInt("DoKho");
cauHoiArrayList.add(new CauHoi(_id, cauhoi, tenmh, tenmonhoc, dapan_a, dapan_b, dapan_c, dapan_d, dapandung, hinhanh, dokho));
}
Log.d("tag",""+cauHoiArrayList.get(0).getCauHoi());
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ScreenSlideActivity.this, ""+error, Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("laytenmonhocc", "" + laytenmonhoc);
params.put("laydokhoc", "" + laydokho);
return params;
}
};
requestQueue.add(stringRequest);
}
public ArrayList<CauHoi> GETDATA (){
return cauHoiArrayList;
}
Volley requests are asynchronous. You must be calling GETDATA by time when response is not arrived yet. You need to sure call GETGATA when you have response. Only OnResponse method is guarantee that response is present.