I have two functions fetchData() and setDataUI(), in fetchData() i'm sending a request and saving the response. In setDataUI() function i'm setting adapter to bind the data's.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_gallery);
recyclerView = (RecyclerView) findViewById(R.id.image_recycler_view);
data_list = new ArrayList<>();
fetchData2(1);
}
fetchData2() to fetch data from server.
public void fetchData2(final int next){
String url = Constants.URL+"image/gallery?page="+next;
Log.d(TAG,"Data2 Url-->"+url);
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
Log.d(TAG, "Response-->" + response);
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("media");
Log.d(TAG, "Media Array-->" + jsonArray);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
ImageGallery imageGallery = new ImageGallery(
jsonObject1.getString("file"),
jsonObject1.getString("description"),
jsonObject.getInt("next"));
data_list.add(imageGallery);
Log.d(TAG, "Data List in AsyncTask-->" + data_list);
setDataUI();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ActivityImageGallery.this, "Server Error!!!!", Toast.LENGTH_SHORT).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
then in setDataUI()
private void setDataToUI() {
gridLayoutManager = new GridLayoutManager(this,1);
recyclerView.setLayoutManager(gridLayoutManager);
Log.d(TAG,"Data_List-->"+data_list);
adapter = new AdapterImageGallery(this, data_list);
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (gridLayoutManager.findLastCompletelyVisibleItemPosition() == data_list.size()-1){
fetchData2(data_list.get(data_list.size()-1).getNext());
}
}
});
}
Expected Result:
function setDataUI() must only start when fetchData2() finishes execution completely. So, data_list in setDataUI() will have the values that are initialized in fetchData2().
Actual Result :
currently setDataUI() starts execution before fetchData2() completes its execution, resulting in data_list to be empty in setDataUI().
I do get the correct response from the server but after the setDataUI() is executed.
What you need to do is just change like below in your response method,
#Override
public void onResponse(String response) {
try {
if(response.isSuccessful){
Log.d(TAG, "Response-->" + response);
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("media");
Log.d(TAG, "Media Array-->" + jsonArray);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
ImageGallery imageGallery = new ImageGallery(
jsonObject1.getString("file"),
jsonObject1.getString("description"),
jsonObject.getInt("next"));
data_list.add(imageGallery);
Log.d(TAG, "Data List in AsyncTask-->" + data_list);
}
setDataToUI();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
-Put setDataToUI(); method call after completion of your for loop in onresponse.
-Also, your second method gets executed before your first method because, your first method is asynchronous (i.e., working on another thread. It's not executing in the Main Thread or UI thread).
Volleys' requests are aynchronous. So, you should call your setDataToUI from callback:
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// all your code
runOnUiThread(new Runnable() {
#Override
public void run() {
setDataToUI();
}
}
}
This is because in your fetchData() Async Task is running in background which you cannot predict how much time it will take. So rather than calling setDataToUI() after fetchData2() function you can just call it inside the response of the fetchData2() function. You can edit this in fetchData2 Function
data_list.add(imageGallery);
Log.d(TAG, "Data List in AsyncTask-->" + data_list);
setDataToUI()
Related
I am trying to get a single integer value with Volley.
In this example the number is 14
In the debugger I get the correct value 14 and assign it to vNumber while in the try/catch block but then when I try to return the vNumber I get value 0 as returned number.
This is the JSON result.
{"result":[{"version":"14"}]}
Here is the code for this function:
int vNumber;
public int getVersionNumber() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, GET_VERSION_NUMBER,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject object = new JSONObject(response);
JSONArray jsonArray = object.getJSONArray("result");
JSONObject jsonObject = jsonArray.getJSONObject(0);
vNumber = jsonObject.getInt("version");
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "JSONException: " + e);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "VolleyError: " + error);
}
});
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest);
return vNumber;
}
I already tried using sharedPreferences and putting the value inside a textView (the value is correct when I set it in a textView) and then getting it from it but it's still not working. I could create a new table inside my local DB and save the data but it is not necessary in this use case.
Do you have any suggestions on how the return the correct value, and what am I doing wrong here?
Cheers
public void fetchVersionNumber() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, GET_VERSION_NUMBER,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject object = new JSONObject(response);
JSONArray jsonArray = object.getJSONArray("result");
JSONObject jsonObject = jsonArray.getJSONObject(0);
vNumber = jsonObject.getInt("version");
compareAndUpdate(vNumber)
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "JSONException: " + e);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "VolleyError: " + error);
}
});
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest);
}
public void compareAndUpdate(int vNumber){
//compare and do your operation
// Get from sharedPref and compare
}
I have a function that should return a list with all the objects that I have in a webservice made in php, for this I am using php, but it is the first time I use webservices, and I am a bit lost, the fact is that I am doing the consultation with Volley, I saw some examples, I read the documentation, but this code still does not return anything, I thought it could be the list with the final prefix, but it returns the empty list, this is the code of the function:
public List<Artist> getArtist() {
final List<Artist> artistList= new ArrayList<>();
String ip= "http://192.168.58.2:8089/ArtistBCV/consultArtists.php";
Log.v("url",ip);
StringRequest stringRequest = new StringRequest(Request.Method.GET, ip,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//hiding the progressbar after completion
try {
Artist artist=null;
//getting the whole json object from the response
JSONObject obj = new JSONObject(response);
//we have the array named hero inside the object
//so here we are getting that json array
JSONArray heroArray = obj.getJSONArray("artistas");
//now looping through all the elements of the json array
for (int i = 0; i < heroArray.length(); i++) {
artist= new Artist();
JSONObject jsonObject=heroArray.getJSONObject(i);
Log.v("TESTO",""+jsonObject.optInt("id_artist"));
artist.setId_artist(jsonObject.optInt("id_artist"));
artist.setName_artist(jsonObject.optString("name_artist"));
artist.setDeathDate_artist(jsonObject.optString("deathDate_artist"));
artist.setBirthDate_artist(jsonObject.optString("birthDate_artist"));
artist.setBiography_artist(jsonObject.optString("biography_artist"));
artist.setPortrait_artist(jsonObject.optString("portrait_artist"));
artist.setPortraitIndividual(jsonObject.optString("portrait_individual"));
artistList.add(artist);
}
} catch (JSONException e) {
Log.v("ERIRRIRIRIRIRI",""+e.toString());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//displaying the error in toast if occurrs
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
}
);
RequestQueue requestQueue = Volley.newRequestQueue(this);
//adding the string request to request queue
requestQueue.add(stringRequest);
Log.v("!!!!!!!SIZE!!!!!!!!!", ""+artistList.size());
return artistList;
}
I build an app, that it load markers in a map, the markers I get it for volley JSON file, but I need that first to load volley, and after continue executing the code, because the other way show me error with latLng null, this parameter is not loaded fast, and another method execute first and show me null.
My volley code for load markers
public void getMarkers(){
requestQueue = Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray saagTracker = response.getJSONArray("saagMRK");
for (int i = 0; i < saagTracker.length(); i++) {
JSONObject object = saagTracker.getJSONObject(i);
title = object.getString(TITLE);
snnipet = object.getString(SNNIP);
latLng = new LatLng(Double.parseDouble(object.getString(LAT)), Double.parseDouble(object.getString(LNG)));
coor = coor + "|" + object.getString(LAT) + "," + object.getString(LNG); // Menambah data marker untuk di tampilkan ke google map
addMarker(latLng, title, snnipet);
}
} catch (JSONException e) {
e.printStackTrace();
}
//JSONArray array = new JSONArray(response.body().string());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Ocurrio un error", Toast.LENGTH_LONG).show();
}
});
requestQueue.add(jsonObjectRequest);
}
onCreate it need latLng first for it to can load my geofire parameter
geoQuery = geofire.queryAtLocation(new GeoLocation(latLng.latitude, latLng.longitude),0.1f); // latLng it coming null
You would need to implement a call back for the volley response. A very simple way to do this would be the following.
Step 1: Create this interface
public interface VolleyCallBack {
void onSuccess();
}
Step 2: change your getMarkers() method to this:
public void getMarkers(final VolleyCallBack callBack){
requestQueue = Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray saagTracker = response.getJSONArray("saagMRK");
for (int i = 0; i < saagTracker.length(); i++) {
JSONObject object = saagTracker.getJSONObject(i);
title = object.getString(TITLE);
snnipet = object.getString(SNNIP);
latLng = new LatLng(Double.parseDouble(object.getString(LAT)), Double.parseDouble(object.getString(LNG)));
coor = coor + "|" + object.getString(LAT) + "," + object.getString(LNG); // Menambah data marker untuk di tampilkan ke google map
addMarker(latLng, title, snnipet);
callback.onSuccess();
}
} catch (JSONException e) {
e.printStackTrace();
}
//JSONArray array = new JSONArray(response.body().string());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Ocurrio un error", Toast.LENGTH_LONG).show();
}
});
requestQueue.add(jsonObjectRequest);
}
Step 3: Call your getMarkers() method like this:
getMarkers(new VolleyCallBack() {
#Override
public void onSuccess() {
// this is where you will call the geofire, here you have the response from the volley.
geoQuery = geofire.queryAtLocation(new GeoLocation(latLng.latitude, latLng.longitude),0.1f);
});
I am trying to parse JSON using Volley.
I am using a vector to store parsed data and calling adapter.notifyDataSetChanged() inside onCreate() after filling vector. But no changes are there.
If I am calling adapter.notifyDataSetChanged() inside try-catch block of getData() then it is working fine. Why?
public class MainActivity extends AppCompatActivity{
Vector<Data> ve;
private Adapter adapter;
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView)findViewById(R.id.main_recycler_view);
ve=new Vector<Data>();
adapter=new Adapter(ve);
RecyclerView.LayoutManager lm=new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(lm);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
getData(ve);
adapter.notifyDataSetChanged(); //not working
}
public void getData(final Vector<Data> ve)
{
String url = "https://api.androidhive.info/contacts/";
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String jsonString) {
try
{
JSONObject object = new JSONObject(jsonString);
JSONArray arr = object.getJSONArray("contacts");
int len=arr.length();
JSONObject obj;
for (int i = 0; i < len; i++)
{
obj = arr.getJSONObject(i);
ve.add(new Data(obj.getString("name"), obj.getString("email"));
}
//adapter.notifyDataSetChanged();working
}
catch (JSONException e)
{
Toast.makeText(getApplicationContext(),"JSON Parsing Exception",Toast.LENGTH_LONG);
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), "Some error occurred!!", Toast.LENGTH_SHORT).show();
}
});
RequestQueue rQueue = Volley.newRequestQueue(this);
rQueue.add(request);
}
}
you cannot do that reason nothing volley used network requests which are designed to be asynchronous in nature , so the network request is put in queue and code continues to execute the notifyadapter changed method . The response to the network call occurs afterwards and add data, you should call that method after data is received by calling it inside volley on response method
I am developing an application using android and i'm trying to get the jSon Array displayed in Listfragment using the loadInBackground() method below in my DataListLoader class:
class DataListLoader extends AsyncTaskLoader<List<Model>> {
List<Model> mModels;
String jsonString;
String name = "Daniel Nyerere", phone = "0652400670";
public DataListLoader(Context context) {
super(context);
loadInBackground();
}
public List<Model> loadInBackground() {
// You should perform the heavy task of getting data from
// Internet or database or other source
// Here, we are generating some Sample data
// Create corresponding array of entries and load with data.
final List<Model> entries = new ArrayList<Model>(50);
StringRequest stringRequest = new StringRequest(
Request.Method.GET, "http://10.0.2.2/webapp/json_get_data.php", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.trim().contains("server_response")) {
jsonString = response.toString();
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("server_response");
int count = 0;
while (count < jsonArray.length()) {
JSONObject jo = jsonArray.getJSONObject(count);
name = jo.getString("name");
phone = jo.getString("user_phone");
entries.add(new Model(name, phone));
System.out.println("DATA FROM JSON ARRAY: " + name + " " + phone);
count++;
return;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue requestQueue = VolleySingleton.getInstance().getRequestQueue();
requestQueue.add(stringRequest);
entries.add(new Model(name, phone));
return entries;
}
But when i try to run it the data from System.out.println("DATA ENTRIES: "+entries); comes as null list ,so no data get displayed in the fragment activity . Anyone who can help me to fix it so that i get data from json because it consume me a lot of time
//You can call it in UI thread
final List<Model> entries = new ArrayList<Model>(5);
StringRequest stringRequest = new StringRequest(
Request.Method.GET, "http://10.0.2.2/webapp/json_get_data.php", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//you need to update the `ListView` content here
//If you need you can create new thread here too e.g. using AsyncTask
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue requestQueue = VolleySingleton.getInstance().getRequestQueue();
requestQueue.add(stringRequest);