I have generated dynamic forms according to type i.e String, int and spinner according to the json data provided by backend.
I have created a recylerview adapter and in pojo class I have added extra variable as answer and provided setter method to it.
Now, forms have generated according to type but I need to save data to server. To save data, i need to get each edittext value with respective id and type and I need to loop it but I couldnot do it so. I cannot define the edittext value with its ID and type. I hope you guys will help me.
There are three paramters to post to server,in method callRetrofitSaveForm() i. vendorId, ii. userid
iii. formData, I have problem with param iii because it has its format to pass. I have used retrofit to parse and problem is with third parameter formData.
the value format of third paramter is
[{"id":"24","label":"Customer ID","value":"102"},{"id":"25","label":"Amount","value":"2000"}]
My Adapter
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
HelpForm.FormSetting formSetting=formArrayList.get(position);
final String description = formArrayList.get(position).getLabel();
Log.d("cjjdnjcnjd",description);
if (formSetting.getType().equals("STRING")){
Log.d("dndjkd",String.valueOf(holder.getAdapterPosition()));
holder.textViewString = new TextView(activity);
holder.linearLayout.addView(holder.textViewString);
holder.textViewString.setText(formSetting.getLabel());
holder.textViewString.setPadding(24, 4, 24, 2);
holder.textViewString.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewString.setTextSize(15);
holder.editTextString = new EditText(activity);
holder.linearLayout.addView(holder.editTextString);
editTextListString.add(holder.editTextString);
}
if (formSetting.getType().equals("INT")){
holder.textViewInt = new TextView(activity);
holder.linearLayout.addView(holder.textViewInt);
holder.textViewInt.setText(formSetting.getLabel());
holder.textViewInt.setPadding(24, 4, 24, 2);
holder.textViewInt.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewInt.setTextSize(15);
holder.editTextINT = new EditText(activity);
holder.linearLayout.addView(holder.editTextINT);
}
if (formSetting.getType().equals("DATE")){
holder.textViewDate = new TextView(activity);
holder.linearLayout.addView(holder.textViewDate);
holder.textViewDate.setText(formSetting.getLabel());
holder.textViewDate.setPadding(24, 4, 24, 2);
holder.textViewDate.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewDate.setTextSize(15);
holder.editTextDate = new EditText(activity);
holder.linearLayout.addView(holder.editTextDate);
}
if(formSetting.getType().equals("DROPDOWN")){
holder.textViewSpinner = new TextView(context);
holder.linearLayout.addView(holder.textViewSpinner);
holder.textViewSpinner.setText(formSetting.getLabel());
holder.textViewSpinner.setPadding(16, 4, 8, 4);
holder.spinner = new Spinner(context);
holder.linearLayout.addView(holder.spinner);
ArrayList<String> err = new ArrayList<>();
err = formSetting.getOptions();
holder.spinner.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, err));
}
VendorFormActivity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callRetrofitSaveForm();
}
});
}
#Override
public int getItemCount() {
return formArrayList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView textViewString,textViewInt,textViewDate;
LinearLayout linearLayout;
EditText editTextString,editTextINT,editTextDate;
Spinner spinner;
TextView textViewSpinner;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout=itemView.findViewById(R.id.dynamiccontainer);
}
}
JSON Response
{
"status": "200",
"message": "success",
"formSetting": [
{
"label": "Customer ID",
"id": 24,
"type": "INT"
},
{
"label": "Amount",
"id": 25,
"type": "INT"
}
]
}
HelpForm
public class HelpForm {
#SerializedName("status")
#Expose
public String status;
#SerializedName("message")
#Expose
public String message;
#SerializedName("formSetting")
#Expose
public ArrayList<FormSetting> formSetting = null;
public ArrayList<FormSetting> getFormSetting() {
return formSetting;
}
public String getStatus() {
return status;
}
public String getMessage() {
return message;
}
public class FormSetting {
#SerializedName("options")
#Expose
public ArrayList<String> options = null;
#SerializedName("label")
#Expose
public String label;
#SerializedName("id")
#Expose
public String id;
#SerializedName("type")
#Expose
public String type;
#SerializedName("answer")
#Expose
public String answer;
public ArrayList<String> getOptions() {
return options;
}
public String getLabel() {
return label;
}
public String getId() {
return id;
}
public String getType() {
return type;
}
public void setAnswer(String answer) {
this.answer = answer;
}
}
}
public void callRetrofitSaveForm() {
RestClient.RetroInterfaceAPI mInterface = RestClient.getClient();
Call<SaveForm> call = mInterface.getSaveForm( vendorID, userID,formData);
call.enqueue(new Callback<SaveForm>() {
#Override
public void onResponse(Call<SaveForm> call, Response<SaveForm> response) {
if (response.body() != null) {
}
}
#Override
public void onFailure(Call<SaveForm> call, Throwable t) {
}
});
}
}
You can grab the parent view and loop through it and get all editText.
private HashSet<EditText> getTextViews(ViewGroup root){
HashSet<EditText> views=new HashSet<>();
for(int i=0;i<root.getChildCount();i++){
View v=root.getChildAt(i);
if(v instanceof EditText){
views.add((EditText)v);
}else if(v instanceof ViewGroup){
views.addAll(getTextViews((ViewGroup)v));
}
}
return views;
}
Related
I am trying to parse a Block of JSON into a RecyclerView. So far I was able to achieve this with a quite flat JSON Structure. But now I have an Array-Entry in my JSON File where I always want to get the first Entry.
The JSON looks like this:
[
{
"MatchID": 60989,
"Team1": {
"TeamName": "FC Bayern München",
"TeamIconUrl": "https://i.imgur.com/jJEsJrj.png"
},
"Team2": {
"TeamName": "VfL Wolfsburg",
"TeamIconUrl": "https://i.imgur.com/ucqKV4B.png"
},
"MatchResults": [
{
"PointsTeam1": 4,
"PointsTeam2": 0,
"ResultOrderID": 1
},
{
"PointsTeam1": 1,
"PointsTeam2": 0,
"ResultOrderID": 2
}
]
},
{
"MatchID": 60990,
"Team1": {
"TeamName": "VfL Bochum",
"TeamIconUrl": "https://i.imgur.com/5jy3Gfr.png"
},
"Team2": {
"TeamName": "1. FC Union Berlin",
"TeamIconUrl": "https://upload.wikimedia.org/wikipedia/commons/4/44/1._FC_Union_Berlin_Logo.svg"
},
"MatchResults": [
{
"PointsTeam1": 0,
"PointsTeam2": 1,
"ResultOrderID": 1
},
{
"PointsTeam1": 0,
"PointsTeam2": 1,
"ResultOrderID": 2
}
]
}
]
My Activity fetches this JSON from an API using Retrofit2
private void parseJson() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.openligadb.de/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface request = retrofit.create(RequestInterface.class);
Call<List<Match>> call=request.getMatchJson();
call.enqueue(new Callback<List<Match>>() {
#Override
public void onResponse(Call<List<Match>> call, Response<List<Match>> response) {
if (response.isSuccessful() && response.body() != null) {
matchList = new ArrayList<>(response.body());
matchAdapter = new MatchAdapter(matchList, ActivityMatch.this);
mRecyclerView.setAdapter(matchAdapter);
}
}
#Override
public void onFailure(Call<List<Match>> call, Throwable t) {
Log.println(Log.ERROR, "FAILED", String.valueOf(t));
Toast.makeText(ActivityMatch.this, "Oops! Somehting went wrong!", Toast.LENGTH_SHORT).show();
}
});
}
My MatchAdapter is then parsing this Data for the View. Here I want to display whatever is the first in MatchResults then using PointsTeam1 and PointsTeam2 to display something like "4 : 0"
Now in my ModelClass accessing direct Values like the TeamName and TeamIconUrl worked but I am struggeling to get to the first entry of the Array and am really stuck on even how to properly approach this issue.
The Adapter Class:
public class MatchAdapter extends RecyclerView.Adapter<MatchAdapter.MatchHolder>{
private ArrayList<Match> matchList;
private Context context;
public MatchAdapter(ArrayList<Match> matchList, Context context) {
this.context = context;
this.matchList = matchList;
}
#NonNull
#Override
public MatchAdapter.MatchHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.match_list_row_layout, viewGroup, false);
return new MatchHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MatchAdapter.MatchHolder holder, int position) {
holder.tvTeam1name.setText(matchList.get(position).Team1.TeamName);
holder.tvTeam2name.setText(matchList.get(position).Team2.TeamName);
Glide.with(context).load(matchList.get(position).Team1.TeamIconUrl).into(holder.ivTeam1Logo);
Glide.with(context).load(matchList.get(position).Team2.TeamIconUrl).into(holder.ivTeam2Logo);
//This is not working
holder.tvResult.setText(matchList.get(position).MatchResults.PointsTeam1 + " : " + matchList.get(position).MatchResults.PointsTeam2);
}
#Override
public int getItemCount() {
return matchList.size();
}
public class MatchHolder extends RecyclerView.ViewHolder {
private TextView tvTeam1name, tvTeam2name, tvResult;
private ImageView ivTeam1Logo, ivTeam2Logo;
public MatchHolder(#NonNull View itemView) {
super(itemView);
tvTeam1name = itemView.findViewById(R.id.tv_team1name);
tvTeam2name = itemView.findViewById(R.id.tv_team2name);
tvResult = itemView.findViewById(R.id.tv_result);
ivTeam1Logo = itemView.findViewById(R.id.iv_team1logo);
ivTeam2Logo = itemView.findViewById(R.id.iv_team2logo);
}
}
}
My ModelClass (Left out Getters/Setters for Readability)
package de.eahjena.app.wi.fussball;
public class Match {
Team Team1;
Team Team2;
MatchResults MatchResults;
public Match(Team Team1, Team Team2, MatchResults MatchResults) {
this.Team1 = Team1;
this.Team2 = Team2;
this.MatchResults = MatchResults;
}
}
class Team {
String TeamName;
String TeamIconUrl;
public Team (String TeamName, String TeamIconUrl) {
this.TeamName = TeamName;
this.TeamIconUrl = TeamIconUrl;
}
}
class MatchResults {
String PointsTeam1;
String PointsTeam2;
public MatchResults(String PointsTeam1, String PointsTeam2) {
this.PointsTeam1 = PointsTeam1;
this.PointsTeam2 = PointsTeam2;
}
}
As per the question you are suppose to use List<MatchResults> MatchResults since the API response contains a list of match results.
Further to use the first position from the matchResults array you cna use it like this in your adapter :
matchList.get(position).MatchResults.get(0).PointsTeam1
I am trying to get data from json that work for first portion but not for nested json object.I want to get the province and city from json object.
I am trying to get data from json that work for first portion but not for nested json object.I want to get the province and city from json object.
In province object i want province string and in city i want city string
........................MY JSON.................
{
"ads": [
{
"id": 8,
"title": "Software Engineering",
"description": "A book for software engineers",
"price": 100,
"user_id": 1,
"province_id": 4,
"city_id": 5,
"subject_id": 1,
"level_id": 3,
"active": 1,
"created_at": "2019-04-20 04:35:00",
"updated_at": "2019-04-20 04:35:00",
"province": {
"id": 4,
"province": "Blochistan",
"created_at": null,
"updated_at": null
},
"city": {
"id": 5,
"city": "Quetta",
"province_id": 4,
"created_at": null,
"updated_at": null
}
}
]
}
public class AdsAdapter extends RecyclerView.Adapter<AdsAdapter.CustomViewHolder> {
private List<Data> adsList;
private Context context;
public AdsAdapter(List<Data> dataList,Context context) {
this.adsList=dataList;
this.context=context;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.ads_list, viewGroup, false);
return new CustomViewHolder(itemView,adsList,context);
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder customViewHolder, int i) {
Data data = adsList.get(i);
customViewHolder.ad_title.setText(data.getTitle());
customViewHolder.ad_price.setText(data.getPrice().toString());
// customViewHolder.ad_city.setText(();
}
#Override
public int getItemCount() {
return adsList.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView ad_title,ad_price,ad_province,ad_city;
private List<Data> adsList;
private Context context;
public CustomViewHolder(#NonNull View itemView,List<Data> adsList,Context context) {
super(itemView);
this.adsList=adsList;
this.context=context;
itemView.setOnClickListener(this);
ad_title = (TextView)itemView.findViewById(R.id.current_page);
ad_price = itemView.findViewById(R.id.ad_price);
ad_province = itemView.findViewById(R.id.province);
ad_city = itemView.findViewById(R.id.city);
}
#Override
public void onClick(View v) {
int position=getAdapterPosition();
Data data = this.adsList.get(position);
Intent intent = new Intent(this.context,AdDetail.class);
intent.putExtra("title",data.getTitle());
intent.putExtra("discrip",data.getDescription());
intent.putExtra("price",data.getPrice().toString());
intent.putExtra("create",data.getCreatedAt().toString());
this.context.startActivity(intent);
}
}
}
my application terminated when i access province string.
Model Class
public class Province {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("province")
#Expose
private String province;
#SerializedName("created_at")
#Expose
private Object createdAt;
#SerializedName("updated_at")
#Expose
private Object updatedAt;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public Object getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Object createdAt) {
this.createdAt = createdAt;
}
public Object getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Object updatedAt) {
this.updatedAt = updatedAt;
}
}
Call call = api.getAds(parse_subject_id,parse_level_id);
/**
* Enqueue Callback will be call when get response...
*/
call.enqueue(new Callback<SubjectList>() {
#Override
public void onResponse(Call<SubjectList> call, Response<SubjectList> response) {
pDialog.dismiss();
if (response.isSuccessful()) {
/**
* Got Successfully
*/
adsList = response.body().getAds();
recyclerView = (RecyclerView) findViewById(R.id.recycler_view_Ads);
adsAdapter = new AdsAdapter(adsList,getApplicationContext());
RecyclerView.LayoutManager eLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(eLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adsAdapter);
/////////////////////////////////////
}
}
#Override
public void onFailure(Call<SubjectList> call, Throwable t) {
pDialog.dismiss();
}
});
hare i am calling the adapter and pass parameters
From city object you can directly get province_id
API File
METHOD : GET
OUTPUT:
{
"status": true,
"message": "Subjects found.",
"data": {
"subjects": [
{
"subj_id": "2",
"name": "Maths",
"img": "Math.jpg"
},
{
"subj_id": "1",
"name": "Physics",
"img": "physics.png"
}
],
"total": 2
}
}
Model Class
public class SubjectTopics
{
#SerializedName("status")
#Expose
private Boolean status;
#SerializedName("message")
#Expose
private String message;
#SerializedName("data")
#Expose
private Data data;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
public class Data {
#SerializedName("subjects")
#Expose
private List<Subjects> subjects = null;
#SerializedName("total")
#Expose
private Integer total;
public List<Subjects> getSubjects() {
return subjects;
}
public void setSubjects(List<Subjects> subjects) {
this.subjects = subjects;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
}
public class Subjects {
#SerializedName("subj_id")
#Expose
private String subjId;
#SerializedName("name")
#Expose
private String name;
#SerializedName("img")
#Expose
private String img;
public String getSubjId() {
return subjId;
}
public void setSubjId(String subjId) {
this.subjId = subjId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
}
My Adapter
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieViewHolder> {
private List<Subjects> movies;
private int rowLayout;
private Context context;
public static class MovieViewHolder extends RecyclerView.ViewHolder {
private TextView subjectName;
private TextView ID;
private ImageView ImageV;
private RelativeLayout relativeClick;
public MovieViewHolder(View v) {
super(v);
subjectName = (TextView) itemView.findViewById(R.id.textView);
relativeClick = (RelativeLayout) itemView.findViewById(R.id.relative_click);
ImageV = (ImageView) itemView.findViewById(R.id.imageView);
}
}
public MoviesAdapter(List<Subjects> movies, int rowLayout, Context context) {
this.movies = movies;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public MoviesAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new MoviesAdapter.MovieViewHolder(view);
}
#Override
public void onBindViewHolder(MoviesAdapter.MovieViewHolder holder, final int position) {
holder.subjectName.setText(movies.get(position).getName());
holder.relativeClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, SubjectTopicList.class);
intent.putExtra("subject_id", movies.get(position).getSubjId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
Picasso.with(context)
.load(movies.get(position).getImg())
.placeholder(R.drawable.load)
.into(holder.ImageV);
}
#Override
public int getItemCount() {
return movies.size();
}
}
Activity
private void getSubjects() {
progressBar.setVisibility(View.VISIBLE);
Call<SubjectTopics> getProductsModelClassCall = webService.getSubjects();
getProductsModelClassCall.enqueue(new Callback<SubjectTopics>() {
#Override
public void onResponse(Call<SubjectTopics> call, Response<SubjectTopics> response) {
if (response.isSuccessful()) {
List<Subjects> movies = response.body().getData().getSubjects();
MoviesAdapter newAd=new MoviesAdapter(movies, R.layout.unit_test_row, getApplicationContext());
recyclerView.setAdapter(newAd);
} else {
APIError apiError = ErrorUtils.parseError(response);
Toast.makeText(UnitTestSubjects.this, ""+apiError, Toast.LENGTH_SHORT).show();
}
if (progressBar.isEnabled())
progressBar.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<SubjectTopics> call, Throwable t) {
Toast.makeText(UnitTestSubjects.this, "Please Try Again", Toast.LENGTH_SHORT).show();
if (progressBar.isEnabled())
progressBar.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.GONE);
}
});
}
Retrofit Code
public class ServiceGenerator {
private final static String TAG = "ApiCall";
public static Retrofit getRetrofit(){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging); // <-- this is the important line!
httpClient.connectTimeout(10, TimeUnit.SECONDS).readTimeout(14, TimeUnit.SECONDS).writeTimeout(16, TimeUnit.SECONDS);
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
return new Retrofit.Builder()
.baseUrl(WebServices.BASE_URL)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
public static Api getApi(){
return getRetrofit().create(Api.class);
}
}
After calling API's using Retrofit 2.0, Unable to get any response and getting this error:
Failure:
retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall#5321
every-time after callback it directly coming out from the method
I have tried all possible ways to solve but not able to find any solution regarding this.
I think this is internal retrofit error or in the pojo class I guess. Please help!
I need to Show Registration Form With Spinner Using Fragments and get the data using Json
This is kind of register form. At the bottom we have change language button which will reset the form and will be shown in arabic / english.
[
{
"Id":1,
"TitleEN":"Kuwait",
"TitleAR":"الكويت",
"CurrencyId":1,
"CurrencyEN":"Kuwaiti Dinar",
"CurrencyAR":"دينار كويتى",
"CodeEN":"KWD",
"CodeAR":"د.ك",
"Code":"965"
},
{
"Id":2,
"TitleEN":"Emirates",
"TitleAR":"الإمارات",
"CurrencyId":2,
"CurrencyEN":"Emirati Dirham",
"CurrencyAR":"درهم إماراتي",
"CodeEN":"AED",
"CodeAR":"درهم",
"Code":"971"
},
{
"Id":3,
"TitleEN":"Saudi Arabia",
"TitleAR":"السعودية",
"CurrencyId":3,
"CurrencyEN":"Saudi Riyal",
"CurrencyAR":"ريال سعودى",
"CodeEN":"SAR",
"CodeAR":"ر.س",
"Code":"966"
}
]
Note.I assume you have followed the first 3 steps from this [question][1]
and will start from the following
Step 1
Add spinner in xml
<Spinner
android:id="#+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="#string/spinner_title" />
Step 2
In ApiInterface Class add the following code
#GET("/app/app.asmx/GetCountries")
Call<List<Country>> getCountry();
Step 3
Create new model class by name Country
public class Country {
#SerializedName("Id")
#Expose
private Integer id;
#SerializedName("TitleEN")
#Expose
private String titleEN;
#SerializedName("TitleAR")
#Expose
private String titleAR;
#SerializedName("CurrencyId")
#Expose
private Integer currencyId;
#SerializedName("CurrencyEN")
#Expose
private String currencyEN;
#SerializedName("CurrencyAR")
#Expose
private String currencyAR;
#SerializedName("CodeEN")
#Expose
private String codeEN;
#SerializedName("CodeAR")
#Expose
private String codeAR;
#SerializedName("Code")
#Expose
private String code;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitleEN() {
return titleEN;
}
public void setTitleEN(String titleEN) {
this.titleEN = titleEN;
}
public String getTitleAR() {
return titleAR;
}
public void setTitleAR(String titleAR) {
this.titleAR = titleAR;
}
public Integer getCurrencyId() {
return currencyId;
}
public void setCurrencyId(Integer currencyId) {
this.currencyId = currencyId;
}
public String getCurrencyEN() {
return currencyEN;
}
public void setCurrencyEN(String currencyEN) {
this.currencyEN = currencyEN;
}
public String getCurrencyAR() {
return currencyAR;
}
public void setCurrencyAR(String currencyAR) {
this.currencyAR = currencyAR;
}
public String getCodeEN() {
return codeEN;
}
public void setCodeEN(String codeEN) {
this.codeEN = codeEN;
}
public String getCodeAR() {
return codeAR;
}
public void setCodeAR(String codeAR) {
this.codeAR = codeAR;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
Step 4
find view in activity or fragment and add call the request and get response and add the response in spinner adapter.Initialize a string list out side the onCreate method
List<String> codes = new ArrayList<String>();
APIInterface apiInterfacePages;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spinner spinner = (Spinner) findViewById(R.id.spinner);
apiInterfacePages= PageApiClient.getRetrofit().create(APIInterface.class);
Call<List<Country>> getCountry = apiInterfacePages.getCountry();
getCountry.enqueue(new Callback<List<Country>>() {
#Override
public void onResponse(Call<List<Country>> call, Response<List<Country>> response) {
countryList = response.body();
for (int i = 0; i < countryList.size(); i++) {
codes.add(countryList.get(i).getCode());
}
ArrayAdapter<String> adapterTime = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_spinner_dropdown_item, codes);
spinner.setAdapter(adapterTime);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "" + countryList.get(i).getTitleEN(), Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
#Override
public void onFailure(Call<List<Country>> call, Throwable t) {
}
});
}
I have this JSON data and I'm trying to display "measurements" part, but it doesn't work.
(I'm getting this: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $).
I'm beginner at Android developing, this is my first app and I just don't know how to fix this.
Here JSON:
[{
"id":1,
"type":"TEMPERATURE",
"measurements":[
{
"value":"22.58",
"time":"2017-01-11T12:20:44.701"
}]
},{
"id":2,
"type":"HUMIDITY",
"measurements":[
{
"value":"52.366",
"time":"2017-01-11T12:20:44.731"
}]
},{
"id":3,
"type":"LUMINOSITY",
"measurements":[
{
"value":"1.0",
"time":"2017-01-11T12:20:44.742"
}]
}]
Adapter:
public class SenzoriAdapter extends RecyclerView.Adapter < SenzoriAdapter.ViewHolder > {
private ArrayList < Measurement > mSenzori;
public SenzoriAdapter(ArrayList < Measurement > senzori) {
this.mSenzori = senzori;
}
#Override
public SenzoriAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.main_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(SenzoriAdapter.ViewHolder viewHolder, int i) {
String datum = mSenzori.get(i).getTime().replace("T", " ");
viewHolder.senzoriLastAlive.setText(datum);
String stringdouble = Double.toString(mSenzori.get(i).getValue());
viewHolder.senzoriMeasurement.setText(stringdouble);
}
#Override
public int getItemCount() {
return mSenzori.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView senzoriLastAlive, senzoriMeasurement;
public ViewHolder(View itemView) {
super(itemView);
senzoriLastAlive = (TextView) itemView.findViewById(R.id.senzoriLastAlive);
senzoriMeasurement = (TextView) itemView.findViewById(R.id.senzoriMeasurement);
}
}
}
Model Senzori:
public class Senzori {
#Expose
private Integer id;
#Expose
private String type;
#Expose
private Measurement[] measurements;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Measurement[] getMeasurement() {
return measurements;
}
}
Model Measurement:
public class Measurement {
#Expose
private Double value;
#Expose
private String time;
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
and usage in Activity:
public void configViews() {
mRecyclerView = (RecyclerView) findViewById(recyclerView);
mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
loadJSON();
}
public void loadJSON() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(MainActivity.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
SenzoriInterface request = retrofit.create(SenzoriInterface.class);
Call < Senzori > call = request.getAllSenzori(MainActivity.BASE_URL + "/sensors/");
call.enqueue(new Callback < Senzori > () {
#Override
public void onResponse(Call < Senzori > call, Response < Senzori > response) {
Senzori jsonResponse = response.body();
senzori = new ArrayList < > (Arrays.asList(jsonResponse.getMeasurement()));
senzoriAdapter = new SenzoriAdapter(senzori);
mRecyclerView.setAdapter(senzoriAdapter);
}
#Override
public void onFailure(Call < Senzori > call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
You are expecting a single object, but response is giving you an array of objects.
Change
Call<Senzori> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");
To
Call<List<Senzori>> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");
And update your code accordingly.
call.enqueue(new Callback<List<Senzori>>() {
#Override
public void onResponse(Call<List<Senzori>> call, Response<List<Senzori>> response) {
senzori = response.body();
senzoriAdapter = new SenzoriAdapter(senzori.getMeasurement());
mRecyclerView.setAdapter(senzoriAdapter);
}
#Override
public void onFailure(Call<List<Senzori>> call, Throwable t) {
Log.d("Error",t.getMessage());
}
});