I put on my json data in this URL= http://api.myjson.com/bins/1fblzn
it contains location data and has 5 fields, three of them are Strings and two of them are Doubles.
I want to show it in recyclerview.
but I keep getting this error.
I searched a lot but I couldn't get an answer.
Here's my code:
MainActivityRecyc
public class MainActivityRecyc extends AppCompatActivity {
private static final String TAG = MainActivityRecyc.class.getSimpleName();
private RecyclerView recyclerView;
private ArrayList<Locations> data;
private DataAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_recyc);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.card_recycler_view);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
RequestInterface requestInterface =
JsonClient.getClient().create(RequestInterface.class);
Call<JSONResponse> call = requestInterface.getJson();
call.enqueue(new Callback<JSONResponse>() {
#Override
public void onResponse(Call<JSONResponse> call,
Response<JSONResponse> response) {
int statusCode = response.code();
List<Locations> data = response.body().getData();
recyclerView.setAdapter(new DataAdapter(data, R.layout.card_row, getApplicationContext())); }
#Override
public void onFailure(Call<JSONResponse> call, Throwable t) {
} }); } }
Locations
public class Locations {
private String name;
private String pname;
private String bicycleno;
private Double lat;
private Double lang;
public Locations(String name, String pname, String bicycleno,
Double lat, Double lang){
this.name= name;
this.pname= pname;
this.bicycleno= bicycleno;
this.lat= lat;
this.lang= lang;
}
public String getName() {
return name;
}
public void setName (String name){
this.name=name;
}
public String getPname() {
return pname;
}
public void setPname(String pname){
this.pname=pname;
}
public String getBicycleno() {
return bicycleno;
}
public void setBicycleno (String bicycleno){
this.bicycleno=bicycleno;
}
public Double getLat() {
return lat;
}
public void setLat (Double lat){
this.lat=lat;
}
public Double getLang() {
return lang;
}
public void setLang (Double lang){
this.lang=lang;
} }
RequestInterface
public interface RequestInterface {
#Headers("Content-Type:application/json")
#GET("/bins/1fblzn/")
Call<JSONResponse> getJson();
}
DataAdapter
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder>{
private List<Locations> data=new ArrayList<>();
private int rowLayout;
private Context context;
public DataAdapter(List<Locations> data ,int rowLayout, Context context){
this.data = data;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
Locations locations= data.get(i);
viewHolder.name.setText(data.get(i).getName());
viewHolder.pname.setText(data.get(i).getPname());
viewHolder.bicycleno.setText(data.get(i).getBicycleno());
viewHolder.lat.setText(data.get(i).getLat().toString());
viewHolder.lang.setText(data.get(i).getLang().toString());
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView name,pname,bicycleno, lat, lang;
public ViewHolder(View view) {
super(view);
name = (TextView)view.findViewById(R.id.name);
pname = (TextView)view.findViewById(R.id.pname);
bicycleno = (TextView)view.findViewById(R.id.bicycleno);
lat = (TextView)view.findViewById(R.id.lat);
lang = (TextView)view.findViewById(R.id.lang);
} } }
JSONResponse
public class JSONResponse {
#SerializedName("data")
#Expose
private List<Locations> data =new ArrayList<>();
public List<Locations> getData() {
return data;
}
JsonClient
public class JsonClient {
public static final String BASE_URL = "https://api.myjson.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}}
You are missing LinearLayoutManager in your implementation, use this code instead
DataAdapter adapter = new DataAdapter(data, R.layout.card_row, getApplicationContext());
recyclerView.setLayoutManager(newLinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
Hope this helps, Happy codding!
The problem is in the fourth line of your onCreate:
recyclerView.setAdapter(adapter);
The adapter you're passing here is just null because you've never assigned a value to the field private DataAdapter adapter;. Right before the aforementioned 4th line, add code to instantiate the adapter. Since you don't have any data at that point, just pass empty data:
adapter = new DataAdapter(Collections.EMPTY_LIST, R.layout.card_row, getApplicationContext())
Then later when you get the data from the request, just update the data of the adapter and call notifyDataChanged();
Related
I am trying to make a call to this api and am having difficulty as the response.body() is returning null.
http://demo.museum.vebrary.vn/api/stuff/getall
I want to get stuff name of list and show to my recyclerview.
My model:
public class SOAnswersResponse {
#SerializedName("StuffModels")
#Expose
private List<StuffModel> stuffModels = null;
public List<StuffModel> getStuffModels() {
return stuffModels;
}
public void setStuffModels(List<StuffModel> stuffModels) {
this.stuffModels = stuffModels;
}
and
public class StuffModel {
#SerializedName("STUFFID")
#Expose
private Integer sTUFFID;
#SerializedName("STUFFCODE")
#Expose
private String sTUFFCODE;
#SerializedName("STUFFNAME")
#Expose
private String sTUFFNAME;
#SerializedName("STUFFNOTE")
#Expose
private String sTUFFNOTE;
#SerializedName("STUFFORDER")
#Expose
private Integer sTUFFORDER;
#SerializedName("CUSTOMERID")
#Expose
private String cUSTOMERID;
#SerializedName("EXHIBITS")
#Expose
private List<Object> eXHIBITS = null;
Json response
{
"StuffModels":[
{
"STUFFID":2,
"STUFFCODE":"Gi",
"STUFFNAME":"Giấy",
"STUFFNOTE":"",
"STUFFORDER":2,
"CUSTOMERID":"CAMAU",
"EXHIBITS":[
]
},
ApiUtils Class
public class ApiUtils {
private ApiUtils() {
}
public static final String BASE_URL = "http://demo.museum.vebrary.vn/api/";
public static SOService getSOService() {
return RetrofitClient.getClient(BASE_URL).create(SOService.class);
}
}
Service interface
public interface SOService {
#GET("/stuff/getall")
Call<SOAnswersResponse> getAnswers();
}
RetrofitClient Class
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
My RecyclerView adapter
public class CategogyNameRecyclerViewAdapter extends RecyclerView.Adapter<CategogyNameRecyclerViewAdapter.ViewHolder> {
private List<StuffModel> mItems;
private Context mContext;
private PostItemListener mItemListener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView titleTv;
PostItemListener mItemListener;
public ViewHolder(View itemView, PostItemListener postItemListener) {
super(itemView);
titleTv = itemView.findViewById(R.id.tvListMenuCategogy);
this.mItemListener = postItemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
StuffModel item = getItem(getAdapterPosition());
this.mItemListener.onPostClick(item.getSTUFFID());
notifyDataSetChanged();
}
}
public CategogyNameRecyclerViewAdapter(Context context, List<StuffModel> posts, PostItemListener itemListener) {
mItems = posts;
mContext = context;
mItemListener = itemListener;
}
#Override
public CategogyNameRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View postView = inflater.inflate(R.layout.item_list_text, parent, false);
ViewHolder viewHolder = new ViewHolder(postView, this.mItemListener);
return viewHolder;
}
#Override
public void onBindViewHolder(CategogyNameRecyclerViewAdapter.ViewHolder holder, int position) {
StuffModel item = mItems.get(position);
TextView textView = holder.titleTv;
textView.setText(item.getSTUFFNAME());
}
#Override
public int getItemCount() {
return mItems.size();
}
public void updateAnswers(List<StuffModel> items) {
mItems = items;
notifyDataSetChanged();
}
private StuffModel getItem(int adapterPosition) {
return mItems.get(adapterPosition);
}
public interface PostItemListener {
void onPostClick(long id);
}
}
And my main activity
public class Testttt extends AppCompatActivity {
private CategogyNameRecyclerViewAdapter mAdapter;
private RecyclerView mRecyclerView;
private SOService mService;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView(R.layout.test );
mService = ApiUtils.getSOService();
mRecyclerView = (RecyclerView) findViewById(R.id.rcvCategogyNameMenuTest);
mAdapter = new CategogyNameRecyclerViewAdapter(this, new ArrayList<StuffModel>(0), new CategogyNameRecyclerViewAdapter.PostItemListener() {
#Override
public void onPostClick(long id) {
Toast.makeText(Testttt.this, "Post id is" + id, Toast.LENGTH_SHORT).show();
}
});
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
mRecyclerView.addItemDecoration(itemDecoration);
loadAnswers();
}
public void loadAnswers() {
mService.getAnswers().enqueue(new Callback<SOAnswersResponse>() {
#Override
public void onResponse(Call<SOAnswersResponse> call, Response<SOAnswersResponse> response) {
Toast.makeText(Testttt.this, "333333333333333333"+response.body(), Toast.LENGTH_SHORT).show();
if(response.isSuccessful()) {
mAdapter.updateAnswers(response.body().getStuffModels());
Log.d("AnswersPresenter", "posts loaded from API");
}else {
int statusCode = response.code();
}
}
#Override
public void onFailure(Call<SOAnswersResponse> call, Throwable t) {
showErrorMessage();
Log.d("AnswersPresenter", "error loading from API");
}
});
}
public void showErrorMessage() {
Toast.makeText(this, "Error loading posts", Toast.LENGTH_SHORT).show();
}
}
The first thing that came in my mind:
Your
public static final String BASE_URL = "http://demo.museum.vebrary.vn/api/";
has a "/" at the the end and your
#GET("/stuff/getall")
Call<SOAnswersResponse> getAnswers();
starts with a "/". So there is a double backslash in the url that might leads to the 404 code. Does this solve the problem?
When i call your URL i receive XML. Maybe the API is not configured correctly?
Change your Service interface
public interface SOService {
#GET("stuff/getall")
Call<SOAnswersResponse> getAnswers();
}
it occurred because you have use start with backslash it already added in your base url
am trying to Fetch the movies data from Mysql DB and show it to Recycler view
but when i run the app nothing shows
here is code i am using Retrofite Library
but i can't parse the Data to the Recycler view
i've made Adapter and Model Class normally like the Json
MainActivity.class
public class MainActivity extends AppCompatActivity {
private static final String url="http://192.168.1.109/stu/";
RecyclerView recyclerViewMovies;
List<MovieListsModels> movies;
MoviesAdapter adapter;
TextView Errortxt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Errortxt = (TextView)findViewById(R.id.txterror);
recyclerViewMovies = (RecyclerView)findViewById(R.id.recyclerview);
recyclerViewMovies.setHasFixedSize(true);
recyclerViewMovies.setLayoutManager(new LinearLayoutManager(this));
movies = new ArrayList<>();
loadDatafromServer();
}
private void loadDatafromServer() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Call<MovieListsModels> call = api.ShowMoviesData();
call.enqueue(new Callback<MovieListsModels>() {
#Override
public void onResponse(Call<MovieListsModels> call, Response<MovieListsModels> response) {
try {
MovieListsModels movie = response.body();
adapter = new MoviesAdapter(MainActivity.this, (List<MovieListsModels>) movie);
recyclerViewMovies.setAdapter(adapter);
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<MovieListsModels> call, Throwable t) {
Errortxt.setText(t.getMessage().toString());
}
});
}
this is the interface of the methods
Api.class Interface
public interface Api {
#GET("config.php")
Call<MovieListsModels> ShowMoviesData();
}
MovieLists.class
public class MovieListsModels {
public MovieListsModels() {
}
int id;
String movie_name;
String movie_image;
String movie_genre;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMovie_name() {
return movie_name;
}
public void setMovie_name(String movie_name) {
this.movie_name = movie_name;
}
public String getMovie_image() {
return movie_image;
}
public void setMovie_image(String movie_image) {
this.movie_image = movie_image;
}
public String getMovie_genre() {
return movie_genre;
}
public void setMovie_genre(String movie_genre) {
this.movie_genre = movie_genre;
}
public MovieListsModels(int id, String movie_name, String movie_image, String movie_genre) {
this.id = id;
this.movie_name = movie_name;
this.movie_image = movie_image;
this.movie_genre = movie_genre;
}
}
MovieAdapter.class
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieHolderView> {
private Context mContext;
private List<MovieListsModels> MovieList = new ArrayList<>();
public MoviesAdapter(Context mContext, List<MovieListsModels> movieList) {
this.mContext = mContext;
MovieList = movieList;
}
#NonNull
#Override
public MovieHolderView onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
MovieHolderView holder = new MovieHolderView(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull MovieHolderView holder, int position) {
MovieListsModels list = MovieList.get(position);
holder.txtName.setText(list.getMovie_name());
holder.txtGenre.setText(list.getMovie_genre());
Picasso.get()
.load(list.getMovie_image())
.into(holder.imgMovie);
}
#Override
public int getItemCount() {
return MovieList.size();
}
public class MovieHolderView extends RecyclerView.ViewHolder {
TextView txtName,txtGenre;
ImageView imgMovie;
public MovieHolderView(View itemView) {
super(itemView);
txtName =(TextView)itemView.findViewById(R.id.movieName);
txtGenre =(TextView)itemView.findViewById(R.id.movieGenre);
imgMovie =(ImageView)itemView.findViewById(R.id.movieImg);
}
}
}
If you receive a list of movies is better because you expect a list, I suppose
public void onResponse(Call<MovieListsModels> call, Response<MovieListsModels> response) {
try {
List<MovieListsModels> movie = response.body();
adapter = new MoviesAdapter(MainActivity.this, movies);
And I believe that not executing the notifyDataSetChanged, you can added like that:
private Context mContext;
private List<MovieListsModels> MovieList = new ArrayList<>();
public MoviesAdapter(Context mContext, List<MovieListsModels> movieList) {
this.mContext = mContext;
MovieList = movieList;
notifiyDataSetChanged();
If you are having json response of the form {..}, you are having an object response and you should expect an object as you have done i.e, Call<YourObject>
If you are having json response of the form [..], you are having an array response and you should expect an array i.e, Call<List<YourObject>>
In your case, i hope its an array(second case), So make changes as per the above answer done by #Guillodacosta
First don't forget to add the internet permission in your manifest file
<uses-permission android:name="android.permission.INTERNET" />
Second try this
Picasso.with(mContext).load(list.getMovie_image()).into(holder.imgMovie);
Hi Im trying to show a list from retrofit onResponse and I am using recyclerview inside a fragment. The list shoud show chefs but I got an error from RecyclerView
Conexion Class
public class Conexion {
public static String BASE_URL = "http://10.30.0.133:8091/Service1.asmx/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
EndPoint Interface
public interface EndPointsInterface {
#GET("chef/{idUser}")
Call<ChefResponse> GetChefsCercanos(#Path("idUser") Integer id_usuario);
}
Entity Usuario
public class Usuario {
#SerializedName("id_usuario")
private Integer id_usuario;
#SerializedName("NombreUsuario")
private String NombreUsuario;
#SerializedName("ApellidoUsuario")
private String ApellidoUsuario;
#SerializedName("TelefonoUsuario")
private String TelefonoUsuario;
#SerializedName("Email")
private String Email;
#SerializedName("Contraseña")
private String Contraseña;
#SerializedName("pos_x")
private Double pos_x;
#SerializedName("pos_y")
private Double pos_y;
public Usuario(){}
public Usuario(Integer id_usuario,String NombreUsuario,String ApellidoUsuario,String TelefonoUsuario,String Email,String Contraseña,Double pos_x,Double pos_y){
this.id_usuario=id_usuario;
this.NombreUsuario=NombreUsuario;
this.ApellidoUsuario=ApellidoUsuario;
this.TelefonoUsuario=TelefonoUsuario;
this.Contraseña=Contraseña;
this.pos_x=pos_x;
this.pos_y=pos_y;
}
public Integer getId_usuario() {
return id_usuario;
}
public void setId_usuario(Integer id_usuario) {
this.id_usuario = id_usuario;
}
public String getNombreUsuario() {
return NombreUsuario;
}
public void setNombreUsuario(String nombreUsuario) {
NombreUsuario = nombreUsuario;
}
public String getApellidoUsuario() {
return ApellidoUsuario;
}
public void setApellidoUsuario(String apellidoUsuario) {
ApellidoUsuario = apellidoUsuario;
}
public String getTelefonoUsuario() {
return TelefonoUsuario;
}
public void setTelefonoUsuario(String telefonoUsuario) {
TelefonoUsuario = telefonoUsuario;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getContraseña() {
return Contraseña;
}
public void setContraseña(String contraseña) {
Contraseña = contraseña;
}
public Double getPos_x() {
return pos_x;
}
public void setPos_x(Double pos_x) {
this.pos_x = pos_x;
}
public Double getPos_y() {
return pos_y;
}
public void setPos_y(Double pos_y) {
this.pos_y = pos_y;
}
}
Entity Chef
public class Chef extends Usuario{
#SerializedName("id_chef")
private Integer id_chef;
#SerializedName("TipoServicio")
private String TipoServicio;
#SerializedName("Rating")
private Double Rating;
#SerializedName("EstadoChef")
private Boolean EstadoChef;
public Chef(){}
public Chef(Integer id_usuario,String NombreUsuario,String ApellidoUsuario,String TelefonoUsuario,String Email,String Contraseña,Double pos_x,Double pos_y,Integer id_chef,String TipoServicio,Double Rating,Boolean EstadoChef){
super(id_usuario,NombreUsuario,ApellidoUsuario,TelefonoUsuario,Email,Contraseña,pos_x,pos_y);
this.id_chef=id_chef;
this.TipoServicio=TipoServicio;
this.Rating=Rating;
this.EstadoChef=EstadoChef;
}
public Integer getId_chef() {
return id_chef;
}
public void setId_chef(Integer id_chef) {
this.id_chef = id_chef;
}
public String getTipoServicio() {
return TipoServicio;
}
public void setTipoServicio(String tipoServicio) {
TipoServicio = tipoServicio;
}
public Double getRating() {
return Rating;
}
public void setRating(Double rating) {
Rating = rating;
}
public Boolean getEstadoChef() {
return EstadoChef;
}
public void setEstadoChef(Boolean estadoChef) {
EstadoChef = estadoChef;
}
}
Chef Response
public class ChefResponse {
#SerializedName("results")
private Chef[] results;
public Chef[] getresults(){
return results;
}
}
RecyclerView Adapter
public class ListaChefsCercanos extends RecyclerView.Adapter<ListaChefsCercanos.ListaChefsCercanosViewHolder> {
private List<Chef> chefs;
private List<Usuario> usuarios;
private int rowLayout;
private Context context;
#Override
public ListaChefsCercanosViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new ListaChefsCercanosViewHolder(view);
}
#Override
public void onBindViewHolder(ListaChefsCercanosViewHolder holder, int position) {
holder.nombreschefscerca.setText(chefs.get(position).getNombreUsuario());
holder.ratingchef.setText(chefs.get(position).getRating().toString());
}
#Override
public int getItemCount() {
return chefs.size();
}
public static class ListaChefsCercanosViewHolder extends RecyclerView.ViewHolder{
LinearLayout chefslayout;
TextView nombreschefscerca;
TextView ratingchef;
public ListaChefsCercanosViewHolder(View v){
super(v);
chefslayout=(LinearLayout) v.findViewById(R.id.cheflayoutcerca);
nombreschefscerca=(TextView) v.findViewById(R.id.tv_NombreChefCercano);
ratingchef=(TextView) v.findViewById(R.id.tv_RatingChefCercano);
}
}
public ListaChefsCercanos(ArrayList <Chef> chefs){
this.chefs=chefs;
//this.rowLayout = rowLayout;
//this.context = context;
}
}
and the fragment
public class RecomendadosFragment extends Fragment {
private RatingBar ratingBar;
//ListAdapter adapter;
ArrayList<Chef> listachef;
ListView lvLista;
String tag_json_array="jarray req";
RecyclerView recyclerviewChefsCarnos;
ListaChefsCercanos mListaChefsCercanos;
private ArrayList<Chef> data;
private ListaChefsCercanos adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View x = inflater.inflate(R.layout.recomendados,null);
//ratingBar = (RatingBar) x.findViewById(R.id.rb_RatingChefCercano);
recyclerviewChefsCarnos=(RecyclerView) x.findViewById(R.id.rv_chefsCernaos);
recyclerviewChefsCarnos.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
EndPointsInterface apiService = Conexion.getClient().create(EndPointsInterface.class);
Call<ChefResponse> call = apiService.GetChefsCercanos(5);
call.enqueue(new Callback<ChefResponse>() {
#Override
public void onResponse(Call<ChefResponse> call, Response<ChefResponse> response) {
int statusCode = response.code();
if (response.isSuccessful()) {
ChefResponse jsonResponse = response.body();
if(jsonResponse != null) {
data = new ArrayList<>(Arrays.asList(jsonResponse.getresults()));
adapter= new ListaChefsCercanos(data);
recyclerviewChefsCarnos.setAdapter(adapter);
}
} else {
// Do whatever you want if API is unsuccessful.
}
// List<Chef> chefs= response.body().getResults();
// recyclerviewChefsCarnos.setAdapter(new ListaChefsCercanos( chefs,R.layout.itemchefscercanos,getActivity().getApplicationContext()));
}
#Override
public void onFailure(Call<ChefResponse> call, Throwable t) {
Log.d("Error",t.getMessage());
}
});
return x;
}
this is the error I found while Im debuging
E/RecyclerView: No adapter attached; skipping layout
Update: Use a empty adapter for the RecyclerView in the OncreateView()
recyclerView.setAdapter(new YourAdapter(getCurrentActivity()));
I am trying to make a service call with Retrofit and RxJava. I am using Picasso 2.5.2 to upload image from the API call. I am getting the image displayed, but i am getting single image only. When I debug, I get size as 20 but the displayed is single. Any help on that would be great.
The Adapter class:
public class PopularMoviesAdapter extends RecyclerView.Adapter<PopularMoviesAdapter.MoviesViewHolder> {
private final String TAG = PopularMoviesAdapter.class.getSimpleName();
private Context context;
private List<MoviesResponse> movieItems = new ArrayList<>();
public PopularMoviesAdapter(Context context, List<MoviesResponse> movieItems) {
this.context = context;
this.movieItems = movieItems;
}
#Override
public MoviesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movies_grid_item, parent, false);
return new MoviesViewHolder(view);
}
#Override
public void onBindViewHolder(MoviesViewHolder holder, int position) {
List<Movies> movies = movieItems.get(position).getResults();
String imageUrl = IntentKeys.MOVIES_POSTER_ENDPOINT + movies.get(position).getPosterPath();
Log.d(TAG, "Poster URL from the API call: " + imageUrl);
Picasso.with(context).load(imageUrl).into(holder.imageView);
Glide.with(context).load(imageUrl).into(holder.imageView);
}
#Override
public int getItemCount() {
return movieItems.size();
}
class MoviesViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public MoviesViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.movies_grid_item_image);
}
}}
The fragment class:
public class PopularMoviesFragment extends Fragment {
private static final int COLUMN_COUNT = 2;
private List<MoviesResponse> responses;
private RecyclerView recyclerView;
private PopularMoviesAdapter popularMoviesAdapter;
private Subscription subscription;
private MoviesService service = RetrofitManager.getMoviesClient().create(MoviesService.class);
public PopularMoviesFragment() {
responses = new ArrayList<>();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_popular_movies, container, false);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(
getActivity(),
COLUMN_COUNT,
LinearLayoutManager.VERTICAL,
false);
recyclerView = (RecyclerView) view.findViewById(R.id.popular_movies_recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(COLUMN_COUNT, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
return view;
}
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onStart() {
super.onStart();
getMoviesSubscription();
}
private void getMoviesSubscription() {
subscription = service.getPopularMovies(IntentKeys.POPULAR_MOVIES_API_KEY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Action1<MoviesResponse>() {
#Override
public void call(MoviesResponse movies) {
responses.add(movies);
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
}
}, new Action0() {
#Override
public void call() {
displayPosters();
}
}
);
}
private void displayPosters() {
popularMoviesAdapter = new PopularMoviesAdapter(getContext(), responses);
recyclerView.setAdapter(popularMoviesAdapter);
recyclerView.invalidate();
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (subscription != null && subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
}
Finally the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/movies_grid_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/movies_grid_item_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
</LinearLayout>
POJO:
public class Movies implements Serializable {
private String posterPath;
private Boolean adult;
private String overview;
private String releaseDate;
private List<Integer> genreIds = new ArrayList<Integer>();
private Integer id;
private String originalTitle;
private String originalLanguage;
private String title;
private String backdropPath;
private Float popularity;
private Integer voteCount;
private Boolean video;
private Float voteAverage;
// getters and setters ommitted and constructor
}
public class MoviesResponse implements Serializable {
private Integer page;
private List<Movies> results = new ArrayList<Movies>();
private Integer totalResults;
private Integer totalPages;
// getters and setters ommitted and constructor
}
Thanks!
Try
Context context = holder.itemView.getContext();
in your onBindViewHolder, so that you don't pass context around.
Also try adding popularMoviesAdapter.notifyDataSetChanged() in your fragment. Do you mind uploading your POJO?
in your adapter
public PopularMoviesAdapter(List<Movie> movies) {
this.movies = movies;
}
in your fragment
.subscribe(
new Action1<MoviesResponse>() {
#Override
public void call(MoviesResponse movies) {
responses.add(movies.getResults());
popularMoviesAdapter.notifyDataSetChanged()
}
}
Change
#Override
public void onBindViewHolder(MoviesViewHolder holder, int position) {
List<Movies> movies = movieItems.get(position);
String imageUrl = IntentKeys.MOVIES_POSTER_ENDPOINT + movies.get(position).getPosterPath();
Log.d(TAG, "Poster URL from the API call: " + imageUrl);
Picasso.with(context).load(imageUrl).into(holder.imageView);
Glide.with(context).load(imageUrl).into(holder.imageView);
}
This is your code to set adapter
popularMoviesAdapter = new PopularMoviesAdapter(getContext(), responses); recyclerView.setAdapter(popularMoviesAdapter);
your ArrayList responses = new ArrayList() // this is your arraylist which you are providing to adapter
debug and check size of responses that how many records will return i think it has on one object
i think your array is somewhat like this
responses [{
0,{
}
}];
so passs
popularMoviesAdapter = new PopularMoviesAdapter(getContext(), responses.get(0).getResults
); recyclerView.setAdapter(popularMoviesAdapter);
i want to find nearest bars and restoraunts from me on api google maps, and put it in listView and on map, i do it with retrofit, bit i have an error,, but i cant understand how i must to do, can you help me?
UPD all code:
UPD add adapter code
public class Retrofit {
private static final String ENDPOINT = "https://maps.googleapis.com/maps/api/place";
private static ApiInterface apiInterface;
interface ApiInterface {
#GET("/nearbysearch/json?location=49.9944422,36.2368201&radius=500&types=food&key=AIzaSyDQZoJKznf0uRkvJFqLYbZ7-1GeGudjmv0")
void getBars(Callback<PlaceResponse> callback);
}
static {
init();
}
private static void init() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
apiInterface = restAdapter.create(ApiInterface.class);
}
public static void getBars(Callback<PlaceResponse> callback) {
apiInterface.getBars(callback);
}
}
Class Result:
public class Result {
public Geometry geometry;
public String icon;
public String id;
public String name;
public OpeningHours openingHours;
public List<Photo> photos = new ArrayList<Photo>();
public String placeId;
public String scope;
public List<AltId> altIds = new ArrayList<AltId>();
public String reference;
public List<String> types = new ArrayList<String>();
public String vicinity;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVicinity() {
return vicinity;
}
public void setVicinity(String vicinity) {
this.vicinity = vicinity;
}
}
Class Place Response:
public class PlaceResponse {
public List<Object> htmlAttributions = new ArrayList<Object>();
public List<Result> results = new ArrayList<Result>();
public String status;
}
Call and set in adapter:
Retrofit.getBars(new Callback<PlaceResponse>() {
#Override
public void success(PlaceResponse placeResponse, Response response) {
listView.setAdapter(new MyAdapter(MainActivity.this, placeResponse // There is error));
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(MainActivity.this, "Something Wrong", Toast.LENGTH_SHORT).show();
}
});
Error:
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Adapter code:
class MyAdapter extends ArrayAdapter<Result> {
public MyAdapter(Context context, List<Result> objects) {
super(context, R.layout.list_item, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.textNameOfBar = (TextView) rowView.findViewById(R.id.name_id);
holder.textVicinity = (TextView) rowView.findViewById(R.id.vicinity_id);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
Result result = getItem(position);
holder.textNameOfBar.setText(result.getName());
holder.textVicinity.setText(result.getVicinity());
return rowView;
}
class ViewHolder {
public TextView textNameOfBar;
public TextView textVicinity;
}
}
You received the error because your expected result (List<Bars>) isn't what the server is returning (i.e you're excepting an json array but the server returns an json object).
The place search documentation shows that the response has a given format encapsulating the results. In this case, the model class should like this:
public class PlaceResponse {
public List<Object> htmlAttributions = new ArrayList<Object>();
public List<Result> results = new ArrayList<Result>();
public String status;
}
...
public class Result {
public Geometry geometry;
public String icon;
public String id;
public String name;
public OpeningHours openingHours;
public List<Photo> photos = new ArrayList<Photo>();
public String placeId;
public String scope;
public List<AltId> altIds = new ArrayList<AltId>();
public String reference;
public List<String> types = new ArrayList<String>();
public String vicinity;
}
with void getBars(Callback<PlaceResponse> callback); in your API interface.
You can use jsonschema2pojo to generate your model classes from a json schema.
Also, please note that the food type is deprecated (see Place Types).
then in your retrofit callback you can do to access the results:
#Override
public void success(PlaceResponse placeResponse, Response response) {
listView.setAdapter(new MyAdapter(MainActivity.this, placeResponse.getResults()));
}