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()));
}
Related
I'm trying to display another list inside my custom listview like in the image below. I have successfully display the first three child(name, sport and town). But when i add the coverage child i got this error 'failed to convert value of type arraylist to string' in main activity.
Error message
Failed to convert value of type java.util.ArrayList to String
This is the display im trying to achieve
This is what im trying to achieve
This is my firebase database structure
db structure
I got this code below for my main activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView)findViewById(R.id.cusListView);
mTextView = (TextView)findViewById(R.id.textV);
mRef = FirebaseDatabase.getInstance().getReference().child("Person");
mRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
showData(dataSnapshot);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void showData(DataSnapshot dataSnapshot){
ArrayList<PeopleGetSet> array = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
PeopleGetSet arr = ds.getValue(PeopleGetSet.class);
array.add(arr);
ViewDatabase adapter = new ViewDatabase(this, R.layout.adapter_view_layout, array);
mListView.setAdapter(adapter);
}
}
This it my code for Adapter
public class ViewDatabase extends ArrayAdapter<PeopleGetSet> {
private static final String TAG="ViewDatabase";
private Context mContext;
int mResource;
public ViewDatabase(#NonNull Context context, int resource, #NonNull List<PeopleGetSet> objects) {
super(context, resource, objects);
this.mContext=context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
String name =getItem(position).getName();
String sport =getItem(position).getSport();
String town =getItem(position).getTown();
String Coverage =getItem(position).getCoverage();
PeopleGetSet person = new PeopleGetSet(name,sport, town, Coverage);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView=inflater.inflate(mResource, parent, false);
TextView tvName = (TextView)convertView.findViewById(R.id.textView);
TextView tvSport = (TextView)convertView.findViewById(R.id.textView2);
TextView tvTown = (TextView)convertView.findViewById(R.id.textView3);
TextView tvCoverage = (TextView)convertView.findViewById(R.id.textView4);
tvName.setText(name);
tvSport.setText(sport);
tvTown.setText(town);
tvCoverage.setText(Coverage);
return convertView;
}
}
And this is my code for Getter and setter
public class PeopleGetSet {
private String name;
private String sport;
private String town;
private String Coverage;
public PeopleGetSet() {
}
public PeopleGetSet(String name, String sport, String town, String Coverage) {
this.name = name;
this.sport = sport;
this.town = town;
this.Coverage = Coverage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSport() {
return sport;
}
public void setSport(String sport) {
this.sport = sport;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getCoverage() {
return Coverage;
}
public void setCoverage(String coverage) {
Coverage = coverage;
}
}
I mean like this:
public class PeopleGetSet {
private String name;
private String sport;
private String town;
private Coverage coverage;
... default code
}
public class Coverage {
private ArrayList<String> names;
... default code
}
Problem is in your Getter Setter class Add Coverage as Hashmap in your PeopleGetSet class. Coverage is not string its array so to read array from firebase you should use HashMap
public class PeopleGetSet {
private String name;
private String sport;
private String town;
private HashMap<String,String> Coverage ;
public PeopleGetSet() {
}
public PeopleGetSet(String name, String sport, String town, HashMap<String, String> Coverage) {
this.name = name;
this.sport = sport;
this.town = town;
this.Coverage = Coverage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSport() {
return sport;
}
public void setSport(String sport) {
this.sport = sport;
}
public String getTown() {
return town;
}
public HashMap<String,String> getCoverage() {
return Coverage;
}
There is a simple way to inflate multiple views inside one ListView. Here's my example code.
public class MyExampleCode extends ArrayAdapter<Object> {
private static final int TYPE_1 = 0;
private static final int TYPE_2 = 1;
private Context context;
private List<Object> objectList;
public MyExampleCode(Context context, List<Object> objectList) {
super(context,layout,objectList);
this.context = context;
this.objectList = objectList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if (getItemViewType(position) == TYPE_1) {
PeopleGetSet peopleGetSet = (PeopleGetSet)objectList.get(position);
//handle code for first object, inflate layout and fill it
} else {
Coverage coverage = (Coverage)objectList.get(position);
//handle code for second object, inflate layout and fill it
}
}
#Override
public int getItemViewType(int position) {
if (getItem(position) instanceof PeopleGetSet) {
return TYPE_1;
} else {
return TYPE_2;
}
}
#Nullable
#Override
public Object getItem(int position) {
return objectList.get(position);
}
#Override
public int getCount() {
return objectList.size();
}
}
#Edit
Let update your code
private void showData(DataSnapshot dataSnapshot){
List<Object> array = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
PeopleGetSet arr = ds.getValue(PeopleGetSet.class);
Coverage arr2 = arr.getCoverage();
array.add(arr);
array.add(arr2);
}
ViewDatabase adapter = new ViewDatabase(this, array);
mListView.setAdapter(adapter);
}
I am newbie to Android application development. I am developing a shopping cart application. I am trying to call a web-service in GET method using android. But how can I do that? What I tried is here. But it gives me an error PostResponseAsyncTask: 405 Method not allowed. How to fix that? Anybody can help me? Thanks in advance.
MainFragment Class
public class MainFragment extends Fragment implements AsyncResponse, AdapterView.OnItemClickListener{
public static final String PREFS = "prefFile";
final String LOG = "MainFragment";
final static String url = "http://10.0.3.2:8080/WebService/rest/get/products";
private ArrayList<Products> productList;
private ListView lv;
FunDapter<Products> adapter;
View view;
public MainFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
ImageLoader.getInstance().init(UILConfig.config(MainFragment.this.getActivity()));
PostResponseAsyncTask taskRead = new PostResponseAsyncTask(MainFragment.this.getActivity(), this);
taskRead.execute(url);
return view;
}
#Override
public void processFinish(String s) {
productList = new JsonConverter<Products>().toArrayList(s, Products.class);
BindDictionary dic = new BindDictionary();
dic.addStringField(R.id.tvName, new StringExtractor<Products>() {
#Override
public String getStringValue(Products item, int position) {
return item.name;
}
});
dic.addStringField(R.id.tvDesc, new StringExtractor<Products>() {
#Override
public String getStringValue(Products item, int position) {
return item.description;
}
}).visibilityIfNull(View.GONE);
dic.addStringField(R.id.tvPrice, new StringExtractor<Products>() {
#Override
public String getStringValue(Products item, int position) {
return ""+item.price;
}
});
dic.addDynamicImageField(R.id.ivImage, new StringExtractor<Products>() {
#Override
public String getStringValue(Products item, int position) {
return item.pic;
}
}, new DynamicImageLoader() {
#Override
public void loadImage(String url, ImageView img) {
//Set image
ImageLoader.getInstance().displayImage(url, img);
}
});
dic.addBaseField(R.id.btnCart).onClick(new ItemClickListener() {
});
adapter = new FunDapter<>(MainFragment.this.getActivity(), productList, R.layout.product_row, dic);
lv = (ListView)view.findViewById(R.id.lvProduct);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}
Try using some Libraries such as Retrofit, Volley, Loopj etc for Asynchrous GET or POST HTTP Requests.
For Implementing dynamic image from url or file path use Piccasso or Glide Library.
Here are some examples and documentation on these libraries
Loopj
Loopj official Documentation and Example
Retrofit
Retrofit official Documentation By SquareUp
Retrofit Tutorial from JournelDev
Volley
Volley official Documenation By Android Developers
Volley tutorial from Journeldev
DYNAMIC IMAGE HANDLING
Picasso
Android Picasso Library
Glide
Glide Library for Android
Hope these may help you
Example with Retrofit
build.gradle(app)
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
MainFragment
public class MainFragment extends Fragment {
public static final String PREFS = "prefFile";
final String LOG = "MainFragment";
private ArrayList<Product> productList;
private ListView lv;
FunDapter adapter;
private ApiInterface apiInterface;
View view;
public MainFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
lv = (ListView) view.findViewById(R.id.lvProduct);
apiInterface = ApiClient.getRetrofitApiClient().create(ApiInterface.class);
productList = new ArrayList<Product>();
adapter= new FunDapter (getContext(), 0, productList);
lv.setAdapter(adapter);
getProduct();
}
private void getProduct() {
Call<List<Product>> call = apiInterface.getProducts();
call.enqueue(new Callback<List<Product>>() {
#Override
public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
List<Product> products= response.body();
Log.d("TEST", "onResponse: "+response.body().size());
if(products.size()>0){
productList.addAll(products);
}
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<List<Product>> call, Throwable t) {
}
});
}
}
ApiClient
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by android on 3/10/17.
*/
class ApiClient {
public static final String BASE_URL = "http://10.0.2.2:8080/WebService/rest/";
public static Retrofit retrofit = null;
public static Retrofit getRetrofitApiClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
ApiInterface
import java.util.List;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
public interface ApiInterface {
#GET("get/products")
Call<List<Product>> getProducts();
}
Products
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
class Product {
#SerializedName("name")
#Expose
private String name;
#SerializedName("ram")
#Expose
private String ram;
#SerializedName("price")
#Expose
private String price;
#SerializedName("pic")
#Expose
private String pic;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRam() {
return ram;
}
public void setRam(String ram) {
this.ram = ram;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
}
FunDapter
class FunDapter extends ArrayAdapter<Product> {
private Context context;
private ArrayList<Product> objects;
private static LayoutInflater inflater = null;
public FunDapter(#NonNull Context context, int resource, #NonNull ArrayList<Product> objects) {
super(context, resource, objects);
try {
this.context = context;
this.objects = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} catch (Exception e) {
}
}
public int getCount() {
return objects.size();
}
public Product getItem(Product position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
public TextView display_name;
public TextView display_number;
public ImageView image;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
try {
if (convertView == null) {
vi = inflater.inflate(R.layout.singlerow_mylistview, null);
holder = new ViewHolder();
holder.display_name = (TextView) vi.findViewById(R.id.title_listview);
holder.display_number = (TextView) vi.findViewById(R.id.subtitle_listview);
holder.image = (ImageView) vi.findViewById(R.id.icon_listview);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
holder.display_name.setText(objects.get(position).getName());
holder.display_number.setText(objects.get(position).getPrice());
Picasso.with(context)
.load(objects.get(position).getPic())
.resize(50, 50)
.centerCrop()
.into(holder.image);
} catch (Exception e) {
}
return vi;
}
}
Dont forget to add <uses-permission android:name="android.permission.INTERNET" /> in Manifest
Your are performing a POST request by doing this PostResponseAsyncTask that's why you're getting 405 Method not allowed. If that endpoint accept GET then do a GET request. Better you should use Volley or Retrofit library for network communication.
Try using retrofit, first add the following dependencies
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
First of all try to find out what type of json response you are getting from the backend- It can be an array response/an object response.
Json array responses are of the form
[{"field1":"value1",..},{"field2":"value2",..}..] whereas object
responses are of the form {"field1":"value1",..}
You may check this tutorial to have an idea about parsing json responses
If you check the backend and figure out the response, then you can generate a model class using the same from http://www.jsonschema2pojo.org/
Case 1 : Suppose you have a json object response({"field1":"value1",..})
First create a model class using your response from jsonschema2pojo as mentioned above, then call it like following(suppose YourObjectModel is your model class)
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://10.0.3.2:8080/WebService/")
.addConverterFactory(GsonConverterFactory.create())
.build();
SampleInterface request = retrofit.create(SampleInterface.class);
Call<YourObjectModel> call1=request.getResponse();
call1.enqueue(new Callback<YourObjectModel>() {
#Override
public void onResponse(Call<YourObjectModel> call, Response<YourObjectModel> response) {
Toast.makeText(MainActivity.this,response.body().toString(),Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<YourObjectModel> call, Throwable t) {
Toast.makeText(MainActivity.this,t.toString(),Toast.LENGTH_SHORT).show();
}
});
SampleInterface.java
public interface SampleInterface {
#GET("rest/get/products")
Call<YourObjectModel> getResponse();
}
Case 2 : Suppose you have a json array response([{"field1":"value1",..},{"field2":"value2",..}..])
First create a model class like in above case and since it is an array response you might need to get the response as a list so change all the call method from Call<YourObjectModel> to Call<List<YourArrayModel>>
where YourArrayModel is your model class for json array response
try this examples it's very easy this examples must help you.
asynctask-callback
volley-callback
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);
I am try to parse this Json array from this site NewsApi and display it in a listView.When I run the app nothing is displaying.Here is my code.What am doing wrong?.I have tried to debug the problem to no avail.
public class NewsApiClient {
public static String API_BASE_URL = "https://newsapi.org/v1/";
public static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
public static Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create()
);
public static Retrofit retrofit = builder.client(httpClient.build()).build();
NewsApiClient client = retrofit.create(NewsApiClient.class);
}
calling the endpoint?
public interface NewsApiInterface {
//endpoint
#GET("sources")
Call <SourcesResponse> getTechSources(
#Query("language") String language,
#Query("category") String category)
}
I am only using the name,description and category attributes.
public class Source {
#SerializedName("id")
public String id;
#SerializedName("name")
public String name;
#SerializedName("description")
public String description;
#SerializedName("url")
public String url;
#SerializedName("category")
public String category;
#SerializedName("language")
public String language;
#SerializedName("country")
public String country;
}
public class SourcesAdapter extends BaseAdapter {
Context context;
List<Source> sourceList;
public SourcesAdapter( Context context,List<Source> sourceList){
this.context = context;
this.sourceList = sourceList;
}
#Override
public int getCount() {
return sourceList.size();
}
#Override
public Object getItem(int position) {
return sourceList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.sources_list,null);
Source currentsource = sourceList.get(position);
TextView sourcesName = (TextView) convertView.findViewById(R.id.sources_name);
TextView sourcesDescription = (TextView) convertView.findViewById(R.id.sources_description);
TextView sourcesCategory = (TextView) convertView.findViewById(R.id.sources_category);
sourcesName.setText(currentsource.name);
sourcesDescription.setText(currentsource.description);
sourcesCategory.setText(currentsource.category);
return convertView;
}
}
public class SourcesFragment extends Fragment {
ListView listView;
public SourcesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//
//instance of the adapter to this listview
View view = inflater.inflate(R.layout.fragment_sources, container, false);
listView = (ListView)view.findViewById(R.id.list_view_sources) ;
getSources();
return view;
}
public void getSources(){
Retrofit retrofit = NewsApiClient.builder.build();
NewsApiInterface newsApiInterface = retrofit.create(NewsApiInterface.class);
Call<SourcesResponse> sourcesCall = newsApiInterface.getTechSources("en", "technology");
sourcesCall.enqueue(new Callback<SourcesResponse>() {
#Override
public void onResponse(Call<SourcesResponse> call, Response<SourcesResponse> response) {
List<Source> sources = response.body().sources;
SourcesAdapter sourcesAdapter = new SourcesAdapter(getContext(),sources);
listView.setAdapter(sourcesAdapter);
}
#Override
public void onFailure(Call<SourcesResponse> call, Throwable t) {
}
});
}
}
public class SourcesResponse {
#SerializedName("status")
public String status;
#SerializedName("sources")
public List<Source> sources;
}
I have created 3 fragments,the sources fragment is one of them.On the sources fragment i only want to display sources with technology.
Thank you in advance!
In your retrofit's onResponse callback method, you are accessing sources list like response.body().sources. Instead of this in the SourcesResponse , add a getter and setter for sources like this
public List<SourcesResponse> getSources() {
return sources;
}
public void setSources(List<SourcesResponse> sources) {
this.sources = sources;
}
Now go to your onResponse callback of retrofit and change
response.body().sources
to
response.body().getSources()
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();