null value when fetch image from json data using picasso - java
I'v tried to create a movies app so I create recycleview to display the poster in gridlayout using networking with api json data
now the app fetch the name of movies and it's popularity without problems but can't fetch the poster and when I debug the app I found the value of poster null when it comes to onbindviewholder why that?
this is the adapter of recycleview:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
ArrayList<MovieItem> mMoviesItems;
private Context context;
public RecyclerViewAdapter() {
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
public final TextView MoviePopularity;
public final ImageView MoviePoster;
public final TextView MovieName;
public RecyclerViewHolder(View view) {
super(view);
MoviePopularity = (TextView)itemView.findViewById(R.id.movie_popularity);
MoviePoster = (ImageView)itemView.findViewById(R.id.iv_item_movie);
MovieName = (TextView)itemView.findViewById(R.id.movie_name);
}
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
context = viewGroup.getContext();
int layoutIdForListItem = R.layout.movie_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
return new RecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.MoviePopularity.setText(String.valueOf(mMoviesItems.get(position).getPopularity()));
Picasso.with(this.context).load(mMoviesItems.get(position).getPhoto()).into(holder.MoviePoster);
holder.MovieName.setText(String.valueOf(mMoviesItems.get(position).getName()));
}
#Override
public int getItemCount() {
if (null == mMoviesItems)
return 0;
else {
return mMoviesItems.size();
}
}
public void setMovieData(ArrayList<MovieItem> movieData) {
mMoviesItems = movieData;
notifyDataSetChanged();
}
}
and this is the custom class:
public class MovieItem {
private double popularity;
private String photo;
private String name;
public MovieItem(double popularity, String poster_path, String original_title) {
this.popularity = popularity;
this.photo = poster_path;
this.name = original_title;
}
public double getPopularity() { return popularity; }
public String getPhoto() { return photo; }
public String getName() { return name; }
}
and this is the json class:
public final class OpenMovieJsonUtils {
public static ArrayList<MovieItem> getSimpleMovieStringsFromJson(Context context, String moviesJsonString)
throws JSONException {
final String RESULTS = "results";
final String POPULARITY = "popularity";
final String POSTER_PATH = "poster_path";
final String ORIGINAL_TITLE = "original_title";
ArrayList<MovieItem> parsedMovieData = new ArrayList<MovieItem>();
JSONObject moviesObject = new JSONObject(moviesJsonString);
JSONArray moviesArray = moviesObject.getJSONArray(RESULTS);
for (int i = 0; i < moviesArray.length(); i++) {
double popularity;
String poster_path;
String original_title;
moviesObject = moviesArray.getJSONObject(i);
popularity = moviesObject.getDouble(POPULARITY);
poster_path = moviesObject.getString(POSTER_PATH);
original_title = moviesObject.getString(ORIGINAL_TITLE);
parsedMovieData.add(new MovieItem(popularity, poster_path, original_title));
}
return parsedMovieData;
}
}
this is the networking class:
public final class NetworkUtils {
private static final String TAG = NetworkUtils.class.getSimpleName();
private static final String MOVIES_BASE_URL = "https://api.themoviedb.org/3/movie/";
private static final String MOVIES_URL = MOVIES_BASE_URL;
private static final String apiKey = "36666cbb5d7e20041e705d1b2c4e7a79";
final static String API_PARAM = "api_key";
public static URL buildUrl(String MoviesQuery) {
Uri builtUri = Uri.parse(MOVIES_URL).buildUpon()
.appendPath(MoviesQuery)
.appendQueryParameter(API_PARAM, apiKey)
.build();
URL url = null;
try {
url = new URL(builtUri.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
Log.v(TAG, "Built URI " + url);
return url;
}
public static String getResponseFromHttpUrl(URL url) throws IOException {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = urlConnection.getInputStream();
Scanner scanner = new Scanner(in);
scanner.useDelimiter("\\A");
boolean hasInput = scanner.hasNext();
if (hasInput) {
return scanner.next();
} else {
return null;
}
} finally {
urlConnection.disconnect();
}
}
}
what's wrong with images so I get their values null instead of the popularity and name of movies works and not null
Your question is incomplete, doesn't specify the complete details about from where you are getting API response.
I could answer this question because I have just done this project in my ongoing Android Developer Nanodegree by Udacity.
Hopefully you are fetching the movie details from TMDB.
You should read the Project implementation guide thoroughly which says
You will need to append a base path ahead of this relative path to build the complete url you will need to fetch the image using Picasso
Following code will help you -
public class MovieItem {
private double popularity;
private String photo;
private String name;
public MovieItem(double popularity, String poster_path, String original_title) {
this.popularity = popularity;
this.photo = poster_path;
this.name = original_title;
}
public double getPopularity() { return popularity; }
public String getPhoto() { return photo; }
public String getName() { return name; }
public Uri getFullPosterPath() {
return Uri.parse("http://image.tmdb.org/t/p/")
.buildUpon()
.appendPath("w185")
.appendEncodedPath(getPhoto())
.build();
}
}
And in Adapter make this change -
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.MoviePopularity.setText(String.valueOf(mMoviesItems.get(position).getPopularity()));
Picasso.with(this.context).load(mMoviesItems.get(position).getFullPosterPath()).into(holder.MoviePoster);
holder.MovieName.setText(String.valueOf(mMoviesItems.get(position).getName()));
}
Related
not able to show data in Recycler View
I am getting some data from server in json format. I have a model class where I got all data from server and I put all data in a Array List. Now I am not able to get data in recyclerView. MainActivity public CopyOnWriteArrayList<PrisonerModel> inside1 #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerViewInside = findViewById(R.id.rv); signature_calculation_prisonerList(); new PrisonerListAsyncTask().execute(NetworkUtils.PRISONER_LIST, ctimestamp, cnonce, cappkey, csign); inside1 = new CopyOnWriteArrayList<>(); MyAdapter myAdapter = new MyAdapter(inside1, this, this); recyclerViewInside.setAdapter(myAdapter); } Model.java file public class PrisonerModel { private String name; private int image; private int total_prisoner; private int outside; private int inside; private String imageUri; private String device; public PrisonerModel() { } public PrisonerModel(String name, int image) { this.name = name; this.image = image; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImage() { return image; } public void setImage(int image) { this.image = image; } public int getTotal_prisoner() { return total_prisoner; } public int getOutside() { return outside; } public int getInside() { return inside; } public String getImageUri() { return imageUri; } public String getDevice() { return device; } public static PrisonerModel fromJson(JSONObject jsonObject) { PrisonerModel pm1 = new PrisonerModel(); MainActivity ma = new MainActivity(); try { pm1.total_prisoner = jsonObject.getInt("total"); Log.e("total: ", String.valueOf(pm1.getTotal_prisoner())); JSONArray jsonArray = jsonObject.getJSONArray("list"); ma.inside1 = pm1.fromJson(jsonArray); Log.e("inside: ", String.valueOf(ma.inside1.get(0).getName())); pm1.inside = pm1.x; pm1.outside = pm1.getTotal_prisoner() - pm1.x; } catch (JSONException e) { e.printStackTrace(); return null; } return pm1; } I am getting data of inside1 in this model class but when I use Log.e("") in Main Activity it throw error "ArrayOutOfBoundIndex" could you help me where am i doing mistake?
How to create a retrofit2 array in android studio?
I took this information out of a JSON and initialized it, but I don't understand how I can get the data out of the form to pass them to the cardView afterward. Or is there an easier way? MainActivity public class MainActivity extends AppCompatActivity { Context context; Example example; Response responses; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView rv = (RecyclerView)findViewById(R.id.cartView); LinearLayoutManager llm = new LinearLayoutManager(context); Retrofit retrofit = new Retrofit.Builder() .baseUrl("Secret Url") // For some reason I cannot show the url .addConverterFactory(GsonConverterFactory.create()) .build(); Api api = retrofit.create(Api.class); ArrayList arrayList = new ArrayList(); Call<Example> call = api.getRespon(); call.enqueue(new Callback<Example>() { #Override public void onResponse(Call<Example> call, Response<Example> response) { if(response.code() != 200){ Toast.makeText(MainActivity.this, "Connect",Toast.LENGTH_SHORT).show(); return; } Example examples = response.body(); for(int i=0; i<examples.getResponse().size(); i++){ String f_name = response.body().getResponse().iterator().next().getfName(); String l_name = response.body().getResponse().iterator().next().getlName(); String birthday = response.body().getResponse().iterator().next().getBirthday(); String SpecName = response.body().getResponse().iterator().next().getSpecialty() .iterator().next().getName(); int SpecId = response.body().getResponse().iterator().next().getSpecialty() .iterator().next().getSpecialtyId(); } } #Override public void onFailure(Call<Example> call, Throwable t) { Toast.makeText(MainActivity.this, "Fail",Toast.LENGTH_SHORT).show(); } }); } } At the moment I have not finished the class because I can not specify the data that have been implemented PersonaAdapter public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.PersonViewHolder> { Context context; Example example; MainActivity mainActivity; public static class PersonViewHolder extends RecyclerView.ViewHolder{ CardView cv; TextView l_name, f_name, birthday, SpecName, Age; ImageView avatar; public PersonViewHolder(View itemView) { super(itemView); cv = itemView.findViewById(R.id.cartView); l_name = itemView.findViewById(R.id.textLName); f_name = itemView.findViewById(R.id.textFName); birthday = itemView.findViewById(R.id.textBirthday); SpecName = itemView.findViewById(R.id.textSpecName); Age = itemView.findViewById(R.id.textAge); } } // иницилизация #Override public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout,viewGroup,false); PersonViewHolder phv = new PersonViewHolder(v); return phv; } #Override public void onBindViewHolder(PersonViewHolder personViewHolder, int i) { //*** } #Override public int getItemCount() { return example.getResponse().size(); } #Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } } Handler itself Response public class Response { #SerializedName("f_name") #Expose private String fName; #SerializedName("l_name") #Expose private String lName; #SerializedName("birthday") #Expose private String birthday; #SerializedName("avatr_url") #Expose private String avatrUrl; #SerializedName("specialty") #Expose private List<Specialty> specialty = null; public String getfName() { return fName; } public void setfName(String fName) { this.fName = fName; } public Response withfName(String fName) { this.fName = fName; return this; } public String getlName() { return lName; } public void setlName(String lName) { this.lName = lName; } public Response withlName(String lName) { this.lName = lName; return this; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public Response withBirthday(String birthday) { this.birthday = birthday; return this; } public String getAvatrUrl() { return avatrUrl; } public void setAvatrUrl(String avatrUrl) { this.avatrUrl = avatrUrl; } public Response withAvatrUrl(String avatrUrl) { this.avatrUrl = avatrUrl; return this; } public List<Specialty> getSpecialty() { return specialty; } public void setSpecialty(List<Specialty> specialty) { this.specialty = specialty; } public Response withSpecialty(List<Specialty> specialty) { this.specialty = specialty; return this; } } Specialty public class Specialty { #SerializedName("specialty_id") #Expose private Integer specialtyId; #SerializedName("name") #Expose private String name; public Integer getSpecialtyId() { return specialtyId; } public void setSpecialtyId(Integer specialtyId) { this.specialtyId = specialtyId; } public Specialty withSpecialtyId(Integer specialtyId) { this.specialtyId = specialtyId; return this; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Specialty withName(String name) { this.name = name; return this; } }
I solved the problem by creating a list and putting the data into an array List<Worker> workerList = new ArrayList<>(); for(int i = 0; i < examples.getResponse().size(); i++){ String f_name = response.body().getResponse().get(i).getfName(); String l_name = response.body().getResponse().get(i).getlName(); String birthday = response.body().getResponse().get(i).getBirthday(); String SpecName = response.body().getResponse().get(i).getSpecialty() .iterator().next().getName(); String SpecId = response.body().getResponse().iterator().next().getSpecialty() .iterator().next().getSpecialtyId().toString(); String AvatarUrl = response.body().getResponse().get(i).getAvatrUrl(); workerList.add(new Worker(f_name, l_name, birthday, SpecName, SpecId, AvatarUrl)); In Worker has a constructor and getter
ListView is not showing all JSON data using Retrofit
I'm trying to get all the JSON result into my listview. I have successfully retrieved the data but it keeps only shows one data (example if JNE, only showing OKE result). I'm using Retrofit. Below is the example JSON data from the documentation that I want to show all in my listview. Please help me why it is not showing all the result. Thank you. { "rajaongkir":{ "query":{ "origin":"501", "destination":"114", "weight":1700, "courier":"jne" }, "status":{ "code":200, "description":"OK" }, "origin_details":{ "city_id":"501", "province_id":"5", "province":"DI Yogyakarta", "type":"Kota", "city_name":"Yogyakarta", "postal_code":"55000" }, "destination_details":{ "city_id":"114", "province_id":"1", "province":"Bali", "type":"Kota", "city_name":"Denpasar", "postal_code":"80000" }, "results":[ { "code":"jne", "name":"Jalur Nugraha Ekakurir (JNE)", "costs":[ { "service":"OKE", "description":"Ongkos Kirim Ekonomis", "cost":[ { "value":38000, "etd":"4-5", "note":"" } ] }, { "service":"REG", "description":"Layanan Reguler", "cost":[ { "value":44000, "etd":"2-3", "note":"" } ] }, { "service":"SPS", "description":"Super Speed", "cost":[ { "value":349000, "etd":"", "note":"" } ] }, { "service":"YES", "description":"Yakin Esok Sampai", "cost":[ { "value":98000, "etd":"1-1", "note":"" } ] } ] } ] } } My Call public void getCoast(String origin, String destination, String weight, String courier) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiUrl.URL_ROOT_HTTPS) .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService service = retrofit.create(ApiService.class); Call<ItemCost> call = service.getCost( "c5333cdcc37b3511c909088d99587fd8", origin, destination, weight, courier ); call.enqueue(new Callback<ItemCost>() { #Override public void onResponse(Call<ItemCost> call, Response<ItemCost> response) { Log.v("wow", "json : " + new Gson().toJson(response)); progressDialog.dismiss(); if (response.isSuccessful()) { int statusCode = response.body().getRajaongkir().getStatus().getCode(); if (statusCode == 200) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View alertLayout = inflater.inflate(R.layout.custom_results, null); alert = new AlertDialog.Builder(MainActivity.this); alert.setTitle("Result Cost"); alert.setMessage("this result your search"); alert.setView(alertLayout); alert.setCancelable(true); ad = alert.show(); String originCity = response.body().getRajaongkir().getOriginDetails().getCityName(); String originPostalCode = response.body().getRajaongkir().getOriginDetails().getPostalCode(); String destinationCity = response.body().getRajaongkir().getDestinationDetails().getCityName(); String destinationPostalCode = response.body().getRajaongkir().getDestinationDetails().getPostalCode(); //results List<com.bagicode.cekongkir.model.cost.Result> ListResults = response.body().getRajaongkir().getResults(); //costs List<com.bagicode.cekongkir.model.cost.Cost> ListCosts = response.body().getRajaongkir().getResults().get(0).getCosts(); //cost List<com.bagicode.cekongkir.model.cost.Cost_> ListCost = response.body().getRajaongkir().getResults().get(0).getCosts().get(0).getCost(); mListView = (ListView) alertLayout.findViewById(R.id.listItem); adapter_results = new ResultsAdapter(MainActivity.this, originCity, originPostalCode, destinationCity, destinationPostalCode, ListResults, ListCosts, ListCost); mListView.setAdapter(adapter_results); mListView.setClickable(true); adapter_results.notifyDataSetChanged(); } else { String message = response.body().getRajaongkir().getStatus().getDescription(); Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); } } else { String error = "Error Retrive Data from Server !!!"; Toast.makeText(MainActivity.this, error, Toast.LENGTH_SHORT).show(); } } #Override public void onFailure(Call<ItemCost> call, Throwable t) { progressDialog.dismiss(); Toast.makeText(MainActivity.this, "Message : Error " + t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } Api Interface // Cost #FormUrlEncoded #POST("cost") Call<ItemCost> getCost (#Field("key") String Token, #Field("origin") String origin, #Field("destination") String destination, #Field("weight") String weight, #Field("courier") String courier); Pojo ItemCost public class ItemCost { #SerializedName("rajaongkir") #Expose private Rajaongkir rajaongkir; public Rajaongkir getRajaongkir() { return rajaongkir; } public void setRajaongkir(Rajaongkir rajaongkir) { this.rajaongkir = rajaongkir; } } rajaOngkir Pojo (List) public class Rajaongkir { #SerializedName("query") #Expose private Query query; #SerializedName("status") #Expose private Status status; #SerializedName("origin_details") #Expose private OriginDetails originDetails; #SerializedName("destination_details") #Expose private DestinationDetails destinationDetails; #SerializedName("results") #Expose private List<Result> results = null; public Query getQuery() { return query; } public void setQuery(Query query) { this.query = query; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public OriginDetails getOriginDetails() { return originDetails; } public void setOriginDetails(OriginDetails originDetails) { this.originDetails = originDetails; } public DestinationDetails getDestinationDetails() { return destinationDetails; } public void setDestinationDetails(DestinationDetails destinationDetails) { this.destinationDetails = destinationDetails; } public List<Result> getResults() { return results; } public void setResults(List<Result> results) { this.results = results; } } Results List Pojo public class Result { #SerializedName("code") #Expose private String code; #SerializedName("name") #Expose private String name; #SerializedName("costs") #Expose private List<Cost> costs = null; public Result(String code, String name, List<Cost> costs) { this.code = code; this.name = name; this.costs = costs; } public Result(String code, String name) { this.code = code; this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Cost> getCosts() { return costs; } public void setCosts(List<Cost> costs) { this.costs = costs; } } Costs List Pojo public class Cost { #SerializedName("service") #Expose private String service; #SerializedName("description") #Expose private String description; #SerializedName("cost") #Expose private List<Cost_> cost = null; public Cost(String service, String description) { this.service = service; this.description = description; } public String getService() { return service; } public void setService(String service) { this.service = service; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List<Cost_> getCost() { return cost; } public void setCost(List<Cost_> cost) { this.cost = cost; } } cost list Pojo public class Cost_ { #SerializedName("value") #Expose private Integer value; #SerializedName("etd") #Expose private String etd; #SerializedName("note") #Expose private String note; public Cost_(Integer value, String etd, String note) { this.value = value; this.etd = etd; this.note = note; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } public String getEtd() { return etd; } public void setEtd(String etd) { this.etd = etd; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } } ListView Adapter public class ResultsAdapter extends BaseAdapter { private Activity activity; private LayoutInflater inflater; private List<Result> resulsItems; private List<Cost> costsItems; private List<Cost_> costItems; TextView tv_origin, tv_destination, tv_expedisi, tv_coast, tv_time; private String originCity, destinationCity, originPostalCode, destinationPostalCode; public ResultsAdapter(MainActivity mainActivity, String originCity, String originPostalCode, String destinationCity, String destinationPostalCode, List<Result> listResults, List<Cost> listCosts, List<Cost_> listCost) { this.activity = mainActivity; this.originCity = originCity; this.originPostalCode = originPostalCode; this.destinationCity = destinationCity; this.destinationPostalCode = destinationPostalCode; this.resulsItems = listResults; this.costsItems = listCosts; this.costItems = listCost; } #Override public int getCount() { return resulsItems.size(); } #Override public Object getItem(int location) { return resulsItems.get(location); } #Override public long getItemId(int position) { return position; } #Override public View getView(int i, View convertView, ViewGroup parent) { if (inflater == null) inflater = (LayoutInflater) activity .getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (convertView == null) convertView = inflater.inflate(R.layout.item_results, null); tv_origin = (TextView) convertView.findViewById(R.id.tv_origin); tv_destination = (TextView) convertView.findViewById(R.id.tv_destination); tv_expedisi = convertView.findViewById(R.id.tv_expedisi); tv_coast = convertView.findViewById(R.id.tv_coast); tv_time = convertView.findViewById(R.id.tv_time); results = resulsItems.get(i); costs = costsItems.get(i); cost = costItems.get(i); tv_origin.setText(originCity); tv_destination.setText(destinationCity); tv_expedisi.setText(results.getName()); tv_coast.setText(String.valueOf(cost.getValue())); tv_time.setText(cost.getEtd()); return convertView; } } ACtual Response Log {"body":{"rajaongkir":{"destination_details":{"city_id":"114","city_name":"Denpasar","postal_code":"80227","province":"Bali","province_id":"1","type":"Kota"},"origin_details":{"city_id":"501","city_name":"Yogyakarta","postal_code":"55111","province":"DI Yogyakarta","province_id":"5","type":"Kota"},"query":{"courier":"jne","destination":"114","key":"c5333cdcc37b3511c909088d99587fd8","origin":"501","weight":1000},"results":[{"code":"jne","costs":[{"cost":[{"etd":"4-5","note":"","value":26000}],"description":"Ongkos Kirim Ekonomis","service":"OKE"},{"cost":[{"etd":"2-3","note":"","value":28000}],"description":"Layanan Reguler","service":"REG"},{"cost":[{"etd":"1-1","note":"","value":43000}],"description":"Yakin Esok Sampai","service":"YES"}],"name":"Jalur Nugraha Ekakurir (JNE)"}],"status":{"code":200,"description":"OK"}}},"rawResponse":{"body":{"contentLength":823,"contentType":{"mediaType":"application/json","subtype":"json","type":"application"}},"code":200,"handshake":{"cipherSuite":"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","localCertificates":[],"peerCertificates":[{"hash":-1,"type":"X.509"},{"hash":-1,"type":"X.509"}],"tlsVersion":"TLS_1_2"},"headers":{"namesAndValues":["Date","Thu, 02 May 2019 13:09:21 GMT","Server","Apache/2.4.7 (Ubuntu)","Content-Length","823","Keep-Alive","timeout\u003d15, max\u003d100","Connection","Keep-Alive","Content-Type","application/json"]},"message":"OK","networkResponse":{"code":200,"handshake":{"cipherSuite":"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","localCertificates":[],"peerCertificates":[{"hash":-1,"type":"X.509"},{"hash":-1,"type":"X.509"}],"tlsVersion":"TLS_1_2"},"headers":{"namesAndValues":["Date","Thu, 02 May 2019 13:09:21 GMT","Server","Apache/2.4.7 (Ubuntu)","Content-Length","823","Keep-Alive","timeout\u003d15, max\u003d100","Connection","Keep-Alive","Content-Type","application/json"]},"message":"OK","protocol":"HTTP_1_1","receivedResponseAtMillis":1556802600578,"request":{"body":{"encodedNames":["key","origin","destination","weight","courier"],"encodedValues":["c5333cdcc37b3511c909088d99587fd8","501","114","1000","jne"]},"cacheControl":{"isPrivate":false,"isPublic":false,"maxAgeSeconds":-1,"maxStaleSeconds":-1,"minFreshSeconds":-1,"mustRevalidate":false,"noCache":false,"noStore":false,"noTransform":false,"onlyIfCached":false,"sMaxAgeSeconds":-1},"headers":{"namesAndValues":["Content-Type","application/x-www-form-urlencoded","Content-Length","87","Host","api.rajaongkir.com","Connection","Keep-Alive","Accept-Encoding","gzip","User-Agent","okhttp/3.3.0"]},"method":"POST","tag":{"body":{"encodedNames":["key","origin","destination","weight","courier"],"encodedValues":["c5333cdcc37b3511c909088d99587fd8","501","114","1000","jne"]},"headers":{"namesAndValues":[]},"method":"POST","url":{"host":"api.rajaongkir.com","password":"","pathSegments":["starter","cost"],"port":443,"scheme":"https","url":"https://api.rajaongkir.com/starter/cost","username":""}},"url":{"host":"api.rajaongkir.com","password":"","pathSegments":["starter","cost"],"port":443,"scheme":"https","url":"https://api.rajaongkir.com/starter/cost","username":""}},"sentRequestAtMillis":1556802600415},"protocol":"HTTP_1_1","receivedResponseAtMillis":1556802600578,"request":{"body":{"encodedNames":["key","origin","destination","weight","courier"],"encodedValues":["c5333cdcc37b3511c909088d99587fd8","501","114","1000","jne"]},"headers":{"namesAndValues":["Content-Type","application/x-www-form-urlencoded","Content-Length","87"]},"method":"POST","tag":{"body":{"encodedNames":["key","origin","destination","weight","courier"],"encodedValues":["c5333cdcc37b3511c909088d99587fd8","501","114","1000","jne"]},"headers":{"namesAndValues":[]},"method":"POST","url":{"host":"api.rajaongkir.com","password":"","pathSegments":["starter","cost"],"port":443,"scheme":"https","url":"https://api.rajaongkir.com/starter/cost","username":""}},"url":{"host":"api.rajaongkir.com","password":"","pathSegments":["starter","cost"],"port":443,"scheme":"https","url":"https://api.rajaongkir.com/starter/cost","username":""}},"sentRequestAtMillis":1556802600415}}
public void getCoast(String origin, String destination, String weight, String courier) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiUrl.URL_ROOT_HTTPS) .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService service = retrofit.create(ApiService.class); Call<ItemCost> call = service.getCost( "c5333cdcc37b3511c909088d99587fd8", origin, destination, weight, courier ); call.enqueue(new Callback<ItemCost>() { #Override public void onResponse(Call<ItemCost> call, Response<ItemCost> response) { Log.v("wow", "json : " + new Gson().toJson(response)); progressDialog.dismiss(); if (response.isSuccessful()) { int statusCode = response.body().getRajaongkir().getStatus().getCode(); if (statusCode == 200) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View alertLayout = inflater.inflate(R.layout.custom_results, null); alert = new AlertDialog.Builder(MainActivity.this); alert.setTitle("Result Cost"); alert.setMessage("this result your search"); alert.setView(alertLayout); alert.setCancelable(true); ad = alert.show(); String originCity = response.body().getRajaongkir().getOriginDetails().getCityName(); String originPostalCode = response.body().getRajaongkir().getOriginDetails().getPostalCode(); String destinationCity = response.body().getRajaongkir().getDestinationDetails().getCityName(); String destinationPostalCode = response.body().getRajaongkir().getDestinationDetails().getPostalCode(); //results List<com.bagicode.cekongkir.model.cost.Result> ListResults = response.body().getRajaongkir().getResults(); //costs List<com.bagicode.cekongkir.model.cost.Cost> ListCosts = response.body().getRajaongkir().getResults().get(0).getCosts(); //cost List<com.bagicode.cekongkir.model.cost.Cost_> ListCost = response.body().getRajaongkir().getResults().get(0).getCosts().get(0).getCost(); mListView = (ListView) alertLayout.findViewById(R.id.listItem); adapter_results = new ResultsAdapter(MainActivity.this, originCity, originPostalCode, destinationCity, destinationPostalCode, ListResults, ListCosts, ListCost); mListView.setAdapter(adapter_results); mListView.setClickable(true); adapter_results.notifyDataSetChanged(); } else { String message = response.body().getRajaongkir().getStatus().getDescription(); Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); } } else { String error = "Error Retrive Data from Server !!!"; Toast.makeText(MainActivity.this, error, Toast.LENGTH_SHORT).show(); } } #Override public void onFailure(Call<ItemCost> call, Throwable t) { progressDialog.dismiss(); Toast.makeText(MainActivity.this, "Message : Error " + t.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
Issue with ArrayList from JSON using Retrofit and populating RecyclerView
I’ve been trying to get recycler view working with retrofit. I seem to be pulling in the JSON fine from within getRecipes() method, and my logs are showing me that the some data is there. However, when I call my getRecipes() method from onCreate(), something seems to be going wrong. When I check to see if my recipeList array contains my JSON results within onCreate, it is telling me it is empty. Why is it doing this if my logs within my getRecipes() method are showing me that data is there...? Not sure if it is an issue with my recycler view or what I am doing with retrofit, or something else. Been trying for days to figure out, so any advice would be greatly appreciated. JSON https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json public class ItemListActivity extends AppCompatActivity { private boolean mTwoPane; public static final String LOG_TAG = "myLogs"; public static List<Recipe> recipeList = new ArrayList<>(); #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getRecipes(); setContentView(R.layout.activity_item_list); getRecipes(); //Logging to check that recipeList contains data if(recipeList.isEmpty()){ Log.d(LOG_TAG, "Is empty"); }else { Log.d(LOG_TAG, "Is not empty"); } Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setTitle(getTitle()); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.item_list); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList); recyclerView.setAdapter(simpleItemRecyclerViewAdapter); if (findViewById(R.id.item_detail_container) != null) { mTwoPane = true; } } public void getRecipes(){ String ROOT_URL = "https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/"; Retrofit RETROFIT = new Retrofit.Builder() .baseUrl(ROOT_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); RecipeService service = RETROFIT.create(RecipeService.class); Call<List<Recipe>> call = service.getMyJson(); call.enqueue(new Callback<List<Recipe>>() { #Override public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) { Log.d(LOG_TAG, "Got here"); if (!response.isSuccessful()) { Log.d(LOG_TAG, "No Success"); } Log.d(LOG_TAG, "Got here"); recipeList = response.body(); //Logging to check data is there Log.v(LOG_TAG, "LOGS" + recipeList.size()); for (int i = 0; i < recipeList.size(); i++) { String newString = recipeList.get(i).getName(); Ingredients[] ingredients = recipeList.get(i).getIngredients(); for(int j = 0; j < ingredients.length; j++){ Log.d(LOG_TAG, ingredients[j].getIngredient()); } Steps[] steps = recipeList.get(i).getSteps(); for(int k = 0; k < steps.length; k++){ Log.d(LOG_TAG, steps[k].getDescription()); } Log.d(LOG_TAG, newString); } } #Override public void onFailure(Call<List<Recipe>> call, Throwable t) { Log.e("getRecipes throwable: ", t.getMessage()); t.printStackTrace(); } }); } public class SimpleItemRecyclerViewAdapter extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> { private final List<Recipe> mValues; public SimpleItemRecyclerViewAdapter(List<Recipe> items) { mValues = items; } #Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_list_content, parent, false); return new ViewHolder(view); } #Override public void onBindViewHolder(final ViewHolder holder, int position) { holder.mItem = mValues.get(position); holder.mContentView.setText(mValues.get(position).getName()); holder.mView.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { if (mTwoPane) { Bundle arguments = new Bundle(); arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId()); ItemDetailFragment fragment = new ItemDetailFragment(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() .replace(R.id.item_detail_container, fragment) .commit(); } else { Context context = v.getContext(); Intent intent = new Intent(context, ItemDetailActivity.class); intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId()); context.startActivity(intent); } } }); } #Override public int getItemCount() { return mValues.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public View mView; public TextView mContentView; public Recipe mItem; public ViewHolder(View view) { super(view); mView = view; mContentView = (TextView) view.findViewById(R.id.content); } #Override public String toString() { return super.toString() + " '" + mContentView.getText() + "'"; } } } RecipeService public interface RecipeService { #GET("baking.json") Call<List<Recipe>> getMyJson();} Models Recipe public class Recipe{ private Ingredients[] ingredients; private String id; private String servings; private String name; private String image; private Steps[] steps; public Ingredients[] getIngredients () { return ingredients; } public void setIngredients (Ingredients[] ingredients) { this.ingredients = ingredients; } public String getId () { return id; } public void setId (String id) { this.id = id; } public String getServings () { return servings; } public void setServings (String servings) { this.servings = servings; } public String getName () { return name; } public void setName (String name) { this.name = name; } public String getImage () { return image; } public void setImage (String image) { this.image = image; } public Steps[] getSteps () { return steps; } public void setSteps (Steps[] steps) { this.steps = steps; } #Override public String toString() { return "[ingredients = "+ingredients+", id = "+id+", servings = "+servings+", name = "+name+", image = "+image+", steps = "+steps+"]"; }} Ingredients public class Ingredients{ private String measure; private String ingredient; private String quantity; public String getMeasure () { return measure; } public void setMeasure (String measure) { this.measure = measure; } public String getIngredient () { return ingredient; } public void setIngredient (String ingredient) { this.ingredient = ingredient; } public String getQuantity () { return quantity; } public void setQuantity (String quantity) { this.quantity = quantity; } #Override public String toString() { return "[measure = "+measure+", ingredient = "+ingredient+", quantity = "+quantity+"]"; }} Steps public class Steps{ private String id; private String shortDescription; private String description; private String videoURL; private String thumbnailURL; public String getId () { return id; } public void setId (String id) { this.id = id; } public String getShortDescription () { return shortDescription; } public void setShortDescription (String shortDescription) { this.shortDescription = shortDescription; } public String getDescription () { return description; } public void setDescription (String description) { this.description = description; } public String getVideoURL () { return videoURL; } public void setVideoURL (String videoURL) { this.videoURL = videoURL; } public String getThumbnailURL () { return thumbnailURL; } public void setThumbnailURL (String thumbnailURL) { this.thumbnailURL = thumbnailURL; } #Override public String toString() { return "[id = "+id+", shortDescription = "+shortDescription+", description = "+description+", videoURL = "+videoURL+", thumbnailURL = "+thumbnailURL+"]"; }} Logs https://gist.github.com/2triggers/12b6eeb32ed8909ab50bbadd4742d7f7
this will be empty always because this line will execute before getting the response from a server. if(recipeList.isEmpty()){ Log.d(LOG_TAG, "Is empty"); }else { Log.d(LOG_TAG, "Is not empty"); } Better call this after this line recipeList = response.body(); SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList); recyclerView.setAdapter(simpleItemRecyclerViewAdapter); if (findViewById(R.id.item_detail_container) != null) { mTwoPane = true; }
it is because you are sending the recipelist into the adapter before even it is populated , after you are sending the recipelist into the adapter which is empty you are populating your recipelist from getRecipes method, you might be wondering you have declared the getRecipes method before even you are assigning the recipelist to adapter so how come it is empty, yea but the fact is your getRecipes work on background thread so even before your recipelist gets populated your adapter assignment takes place on the main thread so you are basically assigning the empty list, one thing you can do is notify when the adapter when the data changes or when the the recipelist is filled with data that is from within the getRecipe method. when you assign the recipelist = response.body right after this you can notify the adapter or move this two lines SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList); recyclerView.setAdapter(simpleItemRecyclerViewAdapter); right after the recipelist = response.body; in getRecipes method
Try create the Constructor with all atributes from your Recipe.class Like: public Ingredients(String measure, String ingredients, String quantity ){ this.measure = measure; this.ingredients = ingredients; this.quantity = quantity } Do same in all class where make up your object of list.
recycleview doesn't fetch json data
I have movie android app which contain recycleview with it's adapter and network it with api json data so when I run the app it installed and open but I get a white empty contain there is no data (images) in recycleview and don't now why this is my code: Main Activity: public class MainActivity extends AppCompatActivity { RecyclerViewAdapter mAdapter; RecyclerView mMoviesList; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mMoviesList = (RecyclerView) findViewById(R.id.rv_movies); GridLayoutManager LayoutManager = new GridLayoutManager(this, 2); mMoviesList.setLayoutManager(LayoutManager); mMoviesList.setHasFixedSize(true); mAdapter = new RecyclerViewAdapter(this); mMoviesList.setAdapter(mAdapter); loadMoviesData(); } private void loadMoviesData() { showMovieDataView(); new FetchMoviesTask().execute(); } private void showMovieDataView() { mMoviesList.setVisibility(View.VISIBLE); } public class FetchMoviesTask extends AsyncTask<String, Void, ArrayList<MovieItem>> { #Override protected ArrayList<MovieItem> doInBackground(String... params) { if (params.length == 0) { return null; } String movie = params[0]; URL moviesRequestUrl = NetworkUtils.buildUrl(movie); try { String jsonMovieResponse = NetworkUtils.getResponseFromHttpUrl(moviesRequestUrl); ArrayList<MovieItem> simpleJsonMovieData = OpenMovieJsonUtils.getSimpleMovieStringsFromJson(MainActivity.this, jsonMovieResponse); return simpleJsonMovieData; } catch (Exception e) { e.printStackTrace(); return null; } } protected void onPostExecute(ArrayList<MovieItem> movieData) { if (movieData != null) { showMovieDataView(); mAdapter.setMovieData(movieData); } } } #Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.sort, menu); return true; } #Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.most_popular) { loadMoviesData(); return true; } if (id == R.id.top_rated) { return true; } return super.onOptionsItemSelected(item); } } Adapter of RecycleView: public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> { private static final String TAG = RecyclerViewAdapter.class.getSimpleName(); ArrayList<MovieItem> mMoviesItems; private Context context; public RecyclerViewAdapter(MainActivity mainActivity) { } #Override public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { context = viewGroup.getContext(); int layoutIdForListItem = R.layout.movie_list_item; LayoutInflater inflater = LayoutInflater.from(context); boolean shouldAttachToParentImmediately = false; View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately); RecyclerViewHolder viewHolder = new RecyclerViewHolder(view); return viewHolder; } #Override public void onBindViewHolder(RecyclerViewHolder holder, int position) { holder.MoviePopularity.setText(String.valueOf(mMoviesItems.get(position).getPopularity())); Picasso.with(this.context).load(mMoviesItems.get(position).getPhoto()).into(holder.MoviePoster); holder.MovieName.setText(mMoviesItems.get(position).getName()); } #Override public int getItemCount() { if (null == mMoviesItems) return 0; return mMoviesItems.size(); } public void setMovieData(ArrayList<MovieItem> movieData) { mMoviesItems = movieData; notifyDataSetChanged(); } class RecyclerViewHolder extends RecyclerView.ViewHolder { TextView MoviePopularity; ImageView MoviePoster; TextView MovieName; public RecyclerViewHolder(View itemView) { super(itemView); MoviePopularity = (TextView)itemView.findViewById(R.id.movie_popularity); MoviePoster = (ImageView)itemView.findViewById(R.id.iv_item_movie); MovieName = (TextView)itemView.findViewById(R.id.movie_name); } } } Network: public final class NetworkUtils { private static final String TAG = NetworkUtils.class.getSimpleName(); private static final String MOVIES_BASE_URL = "https://api.themoviedb.org/3/movie/"; private static final String MOVIES_URL = MOVIES_BASE_URL; private static final String apiKey = "36666cbb5d7e20041e705d1b2c4e7a79"; final static String SORT_Order = "popular"; final static String API_PARAM = "api_key"; public static URL buildUrl(String MoviesQuery) { Uri builtUri = Uri.parse(MOVIES_URL).buildUpon() .appendPath(SORT_Order) .appendQueryParameter(API_PARAM, apiKey) .build(); URL url = null; try { url = new URL(builtUri.toString()); } catch (MalformedURLException e) { e.printStackTrace(); } Log.v(TAG, "Built URI " + url); return url; } public static String getResponseFromHttpUrl(URL url) throws IOException { HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); try { InputStream in = urlConnection.getInputStream(); Scanner scanner = new Scanner(in); scanner.useDelimiter("\\A"); boolean hasInput = scanner.hasNext(); if (hasInput) { return scanner.next(); } else { return null; } } finally { urlConnection.disconnect(); } } } JSON: public final class OpenMovieJsonUtils { public static ArrayList<MovieItem> getSimpleMovieStringsFromJson(Context context, String moviesJsonString) throws JSONException { final String RESULTS = "results"; final String POPULARITY = "popularity"; final String POSTER_PATH = "poster_path"; final String ORIGINAL_TITLE = "original_title"; ArrayList<MovieItem> parsedMovieData = new ArrayList<MovieItem>(); JSONObject moviesObject = new JSONObject(moviesJsonString); JSONArray moviesArray = moviesObject.getJSONArray(RESULTS); for (int i = 0; i < moviesArray.length(); i++) { double popularity; String poster_path; String original_title; moviesObject = moviesArray.getJSONObject(i); popularity = moviesObject.getDouble(POPULARITY); poster_path = moviesObject.getString(POSTER_PATH); original_title = moviesObject.getString(ORIGINAL_TITLE); parsedMovieData.add(new MovieItem(popularity, poster_path, original_title)); } return parsedMovieData; } } custom class: public class MovieItem { private double popularity; private String photo; private String name; public MovieItem(double popularity, String poster_path, String original_title) { this.popularity = popularity; this.photo = photo; this.name = name; } public double getPopularity() { return popularity; } public String getPhoto() { return photo; } public String getName() { return name; } } where is the problem ?