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
Related
I am making a simple app in which the user will able to search for books by its name, with google.com book api. For now, I wish to present a list of books with android in their name. I am doing it with Retrofit2 and RecycleView, but nothing is showing.
MainActivity:
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
KnjigaAdapter knjigaAdapter;
List<KnjigaModel> listaKnjiga;
public static final String BASE_URL = "https://www.googleapis.com/books/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uzmiKomentare();
}
public void uzmiKomentare() {
Gson gson = new GsonBuilder().serializeNulls().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
KnjigaApi knjigaApi = retrofit.create(KnjigaApi.class);
final Call<KnjigaModel> pozivZaListuKnjiga = knjigaApi.getKnjige("android");
pozivZaListuKnjiga.enqueue(new Callback<KnjigaModel>() {
#Override
public void onResponse(Call<KnjigaModel> call, Response<KnjigaModel> response) {
if (!response.isSuccessful()) {
return;
}
//generateRecycleView(WHAT TO PUT HERE!!!!);
}
#Override
public void onFailure(Call<KnjigaModel> call, Throwable t) {
Log.d("MainActivity:", t.getMessage());
}
});
}
private void generateRecycleView(List<KnjigaModel> knjige) {
listaKnjiga = new ArrayList<>();
recyclerView = findViewById(R.id.recycleview);
knjigaAdapter = new KnjigaAdapter(this, knjige);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(knjigaAdapter);
if (knjigaAdapter.getItemCount() == 0){
Log.i("List is empty: ","YES");
}
else {
Log.i("list is empty: ","No");
}
}
}
api inteface:
public interface KnjigaApi {
#GET("v1/volumes")
Call<KnjigaModel> getKnjige(#Query("q") String knjiga);
}
model class:
public class KnjigaModel {
#SerializedName("title")
#Expose
private String imeKnjige;
#SerializedName("authors")
#Expose
private String imeAutora;
#SerializedName("thumbnail")
#Expose
private String slikaKnjige;
public KnjigaModel(String imeKnjige, String imeAutora,String slikaKnjige) {
this.imeKnjige = imeKnjige;
this.imeAutora = imeAutora;
this.slikaKnjige = slikaKnjige;
}
public String getImeKnjige() {
return imeKnjige;
}
public String getImeAutora() {
return imeAutora;
}
public String getSlikaKnjige() {
return slikaKnjige;
}
}
and my adapter:
public class KnjigaAdapter extends RecyclerView.Adapter<KnjigaAdapter.KomentariViewHolder> {
private List<KnjigaModel> listaKnjiga;
private LayoutInflater inflater;
private Context context;
public KnjigaAdapter(Context context, List<KnjigaModel> listaKnjiga) {
this.listaKnjiga = listaKnjiga;
this.context = context;
}
#Override
public KomentariViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(context);
// Inflate the custom layout
View postView = inflater.inflate(R.layout.single_item, parent, false);
// Return a new holder instance
return new KomentariViewHolder(postView);
}
#Override
public void onBindViewHolder(KomentariViewHolder holder, int position) {
KnjigaModel knjige = listaKnjiga.get(position);
holder.naslovKnjige.setText(knjige.getImeKnjige());
holder.imeAutora.setText(knjige.getImeAutora());
Glide.with(context)
.load(knjige.getSlikaKnjige())
.into(holder.slikaKnjige);
}
#Override
public int getItemCount() {
return listaKnjiga.size();
}
public class KomentariViewHolder extends RecyclerView.ViewHolder {
private TextView naslovKnjige;
private TextView imeAutora;
private ImageView slikaKnjige;
public KomentariViewHolder(View itemView) {
super(itemView);
naslovKnjige = itemView.findViewById(R.id.ime_knjige);
imeAutora = itemView.findViewById(R.id.autor_knjige);
slikaKnjige = itemView.findViewById(R.id.sika_korica);
}
}
}
my JSON format:
https://www.googleapis.com/books/v1/volumes?q=android
First of all, I strongly recommend to use RxJava for asynchronous requests, though it's totally optional.
Your Problem:
Your "getKnjige" Method returns only ONE Model, though the endpoint is named volumes (plural), you need to wrap your KnjigaModel in a class like
data class KnjigaResponse(val items: List<KnjigaModel>)
(Kotlin for simplicity, you can also generate a Java class with a single member volumes member that holds a list of KnjigaModel)
In addition, your model is wrong. authors is not a string, but a List of Strings, and "thumbnail" is wrapped in an "imageLinks" Object, and title is wrapped in a volumeInfo Object.
Your retrofit interface then would look like this:
public interface KnjigaApi {
#GET("v1/volumes")
Call<KnjigaResponse> getKnjige(#Query("q") String knjiga);
Request:
final Call<KnjigaResponse> pozivZaListuKnjiga = knjigaApi.getKnjige("android");
pozivZaListuKnjiga.enqueue(new Callback<KnjigaResponse>() {
#Override
public void onResponse(Call<KnjigaResponse> call, Response<KnjigaResponse> response) {
if (!response.isSuccessful()) {
return;
}
generateRecycleView(response.items);
}
#Override
public void onFailure(Call<KnjigaResponse> call, Throwable t) {
Log.d("MainActivity:", t.getMessage());
}
});
im a newbie, i have a problem in my recyclerview. I cant fetch my data from my api. ive just took this tutorial since it is the same implementation form my app. http://shaoniiuc.com/android/fetch-json-api-data-recyclerview-using-retrofit-library/, Maybe my implementation is wrong here, can you please help me to solve, thank you :)
This is my api:
public interface Api {
#GET("api/Database/GetSchedule?serialNumber=1807200003")
Call<List<ScheduleDetails>> getSchedData();
}
My DetailObjects:
public class ScheduleDetails {
private String ID;
private String Location;
private String Latitude;
private String Longitude;
private String SequenceNumber;
private String Comment;
private String hasArrived;
private String ActualArrival;
private String hasDepart;
private String ActualDeparture;
private String Status;
private String ID_FleetSchedule;
private String ExpectedTimeOfTransaction;
private String EstimatedTimeOfDeparture;
private String ID_FleetCar;
private String Scheduler;
private String Car;
private String ID_FleetCompany;
private String FleetCompany;
private String ID_FleetDevice;
private String SerialNumber;
//Constructor....
//Getter.....
}
note: in my api, these are the string ive get but
ive only getting least of them... you can check
it on my adapterView.
my adapterview:
public class scheduleAdapter extends
RecyclerView.Adapter<scheduleAdapter.MyViewHolder> {
private List<ScheduleDetails> schedlist;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView location,schedule_status,dateTime,IDFleet,iid;
public MyViewHolder(View view) {
super(view);
location=view.findViewById(R.id.schedule_location);
dateTime=view.findViewById(R.id.schedule_dateTime);
schedule_status=view.findViewById(R.id.schedule_Status);
IDFleet=view.findViewById(R.id.schedule_FleetID);
iid=view.findViewById(R.id.schedule_ID);
}
}
public scheduleAdapter(List<ScheduleDetails> scheduleList) {
this.schedlist = scheduleList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.schedule_cardview, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int
position) {
ScheduleDetails sched = schedlist.get(position);
holder.location.setText(sched.getLocation());
holder.schedule_status.setText(sched.getStatus());
holder.dateTime.setText(sched.getExpectedTimeOfTransaction());
holder.IDFleet.setText(sched.getID_FleetSchedule());
holder.iid.setText(sched.getID());
}
#Override
public int getItemCount() {
return schedlist.size();
}
}
this is my API:
public class ApiClient {
private static final String BASE_URL = "http://www.example.com";
private static Retrofit retrofit = null;
public static Retrofit getRetrofit() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
this is my getList via recyclerview on my main activity:
public class ScheduleFleet extends Fragment {
View inflatedView = null;
private RecyclerView recyclerView;
private scheduleAdapter mAdapter;
private LinearLayoutManager layoutManager;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
inflatedView = inflater.inflate(R.layout.fragment_schedule_fleet, container, false);
return inflatedView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("Schedule");
final SwipeRefreshLayout refresh = inflatedView.findViewById(R.id.sched_refresh);
getUserList();
refresh.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
doYourUpdate();
}
private void doYourUpdate() {
recyclerView.setAdapter(mAdapter);
getUserList();
refresh.setRefreshing(false);
}
}
);
}
private void getUserList() {
try {
Api service = ApiClient.getRetrofit().create(Api.class);
Call<List<ScheduleDetails>> call = service.getSchedData();
call.enqueue(new Callback<List<ScheduleDetails>>() {
#Override
public void onResponse(Call<List<ScheduleDetails>> call, Response<List<ScheduleDetails>> response) {
List<ScheduleDetails> userList = response.body();
layoutManager = new LinearLayoutManager(getContext());
RecyclerView recyclerView =inflatedView.
findViewById(R.id.scheduleRecycler);
recyclerView.setLayoutManager(layoutManager);
scheduleAdapter recyclerViewAdapter =
new scheduleAdapter(userList);
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onFailure(Call<List<ScheduleDetails>> call, Throwable t) {
}
});
}catch (Exception e) {}
}
}
note: ive try to use the debug tool.. it says that my api is message:OK also the response= true... but i havnt display the data on my recyclerview...
ill hope, you understand my question.. feel free to comment if i i have wrong in my question.. thanks folks.
this is my sample api get using insomnia:
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 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()));
}