I can parse json data to my recyclerview. but when i meet json that has array data in it, my app forceclose when i try to get that. How to solve this? or anyone has similar sample code with this case?
Api:
https://v1.nocodeapi.com/fariz/fit/FunuohzdbtxBkVtC/aggregatesDatasets?dataTypeName=steps_count,heart_minutes,weight,activity_summary
Activity_Stepcounter.java
Call<nodeApi> call = jsonPlaceHolderApi.getNode();
call.enqueue(new Callback<nodeApi>() {
#Override
public void onResponse(Call<nodeApi> call, Response<nodeApi> response) {
progressBar.setVisibility(View.GONE);
nodeApi resource = response.body();
List<nodeApi.steps_count> dataList = resource.steps_count;
Adapter_meeting rv_adapter = new Adapter_meeting(dataList, Activity_Stepcounter.this);
rv.setLayoutManager(new LinearLayoutManager(Activity_Stepcounter.this));
rv.setAdapter(rv_adapter);
rv.hasFixedSize();
rv_adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<nodeApi> call, Throwable t) {
call.cancel();
}
});
Adapter_meeting.java
public class Adapter_meeting extends RecyclerView.Adapter<Adapter_meeting.viewHolder> {
private final List<nodeApi.steps_count> mitem_meeting;
private final Context mContext;
public Adapter_meeting(List<nodeApi.steps_count> Item_meeting, Context mContext) {
this.mitem_meeting = Item_meeting;
this.mContext = mContext;
}
#NonNull
#Override
public viewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
final View view;
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_step_counter, parent, false);
final viewHolder vHolder = new viewHolder(view);
return vHolder;
}
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
holder.tv_namaEvent.setText(mitem_meeting.get(position).getValue());
holder.tv_lokasiEvent.setText(mitem_meeting.get(position).getStartTime());
holder.tv_waktuEvent.setText(mitem_meeting.get(position).getEndTime());
holder.tv_tanggalEvent.setText(mitem_meeting.get(position).getStartTimeMillis());
}
#Override
public int getItemCount() {
return mitem_meeting.size();
}
public class viewHolder extends RecyclerView.ViewHolder {
private final TextView tv_namaEvent;
private final TextView tv_lokasiEvent;
private final TextView tv_waktuEvent;
private final TextView tv_tanggalEvent;
public viewHolder(#NonNull View itemView) {
super(itemView);
tv_namaEvent = (TextView) itemView.findViewById(R.id.id_tv_namaEvent);
tv_lokasiEvent = (TextView) itemView.findViewById(R.id.id_tv_lokasiEvent);
tv_waktuEvent = (TextView) itemView.findViewById(R.id.id_tv_waktuEvent);
tv_tanggalEvent = (TextView) itemView.findViewById(R.id.id_tv_tanggalEvent);
}
}}
JsonPlaceHolderApi.java
public interface JsonPlaceHolderApi {
#GET("aggregatesDatasets?dataTypeName=steps_count,heart_minutes,weight,activity_summary")
Call<nodeApi> getNode();}
nodeApi.java
public class nodeApi {
#SerializedName("steps_count")
public List<steps_count> steps_count = null;
public class steps_count {
public Integer value;
public String startTimeMillis;
public String endTimeMillis;
public String startTime;
public String endTime;
public steps_count(Integer value, String startTimeMillis, String endTimeMillis, String startTime, String endTime) {
this.value = value;
this.startTimeMillis = startTimeMillis;
this.endTimeMillis = endTimeMillis;
this.startTime = startTime;
this.endTime = endTime;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public String getStartTimeMillis() {
return startTimeMillis;
}
public void setStartTimeMillis(String startTimeMillis) {
this.startTimeMillis = startTimeMillis;
}
public String getEndTimeMillis() {
return endTimeMillis;
}
public void setEndTimeMillis(String endTimeMillis) {
this.endTimeMillis = endTimeMillis;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
}
error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.iot.testapp, PID: 12849
android.content.res.Resources$NotFoundException: String resource ID #0x19
at android.content.res.Resources.getText(Resources.java:335)
at android.widget.TextView.setText(TextView.java:4555)
at com.iot.testapp.adapter.Adapter_meeting.onBindViewHolder(Adapter_meeting.java:47)
at com.iot.testapp.adapter.Adapter_meeting.onBindViewHolder(Adapter_meeting.java:26)
On these lines:
holder.tv_tanggalEvent.setText(mitem_meeting.get(position).getStartTimeMillis());
holder.tv_lokasiEvent.setText(mitem_meeting.get(position).getStartTime());
holder.tv_waktuEvent.setText(mitem_meeting.get(position).getEndTime());
Compilator thinks, that you are passing String resource, but you are actually passing simple String. Just add +"" and it should start working.
holder.tv_tanggalEvent.setText(mitem_meeting.get(position).getStartTimeMillis()+"");
holder.tv_namaEvent.setText(mitem_meeting.get(position).getStartTime()+"");
holder.tv_waktuEvent.setText(mitem_meeting.get(position).getEndTime()+"");
You should pass text to textviews in form of String resource with placeholders, but it doesn't really make sense, when you don't pass there anything except the changing value.
holder.tv_namaEvent.setText(mitem_meeting.get(position).getValue());
You are trying to set Int.
Try:
String value = String.valueOf(mitem_meeting.get(position).getValue());
holder.tv_namaEvent.setText(value);
Please check all fields for null and read about name convention in Android :)
Also time in milis should be stored in Long type.
You can also read about Kotlin language, mvvn pattern etc.
Thanks, i got help from discord
I have to make jsonresponse first and then convert it to arraylist using nodeApi.java.
public class JsonResponse {
private nodeApi[] steps_count;
public nodeApi[] getStep_count() {
return steps_count;
}
public void setnodeApi(nodeApi[] step_count) {
this.steps_count = step_count;
}
}
Activity_Stepcounter.java
Call<JsonResponse> call = jsonPlaceHolderApi.getStep();
call.enqueue(new Callback<JsonResponse>() {
#Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
progressBar.setVisibility(View.GONE);
JsonResponse jsonResponse = response.body();
listStep = new ArrayList<>(Arrays.asList(jsonResponse.getStep_count()));
Adapter_meeting rv_adapter = new Adapter_meeting(listStep, Activity_Stepcounter.this);
rv.setLayoutManager(new LinearLayoutManager(Activity_Stepcounter.this));
rv.setAdapter(rv_adapter);
rv.hasFixedSize();
rv_adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
call.cancel();
}
});
**there are some refactor/rename.
Related
I tried to make a covid-19 tracking app by watching Youtube tutorials.
My app shows the country list with flags and when you click on any country it opens an activity and shows the details of that country i.e total cases, deaths, recovered, etc. The video on Youtube uses ListView and I am using recyclerView
I fetched the country list successfully and set onClickListener on the view and it opens second activity which shows the case in detail. But I don't know how to show the data.
my adapter class:
class Countries_adapter extends RecyclerView.Adapter<Countries_adapter.MyViewHolder> {
Context ct;
List<Countries_data> list;
public Countries_adapter(Context context,List<Countries_data> country)
{
ct=context;
list=country;
}
#Override
public MyViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View v = LayoutInflater.from(ct).inflate(R.layout.countries_row,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tvCountryName.setText(list.get(position).getCountry());
holder.tvtotal.setText(list.get(position).getActive());
Glide.with(ct).load(list.get(position).getFlag()).into(holder.imageView);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(ct,CountriesDetails.class);
i.putExtra("Country",list.get(position).getCountry());
ct.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvCountryName,tvtotal;
ImageView imageView;
LinearLayout linearLayout;
public MyViewHolder( View itemView) {
super(itemView);
tvCountryName = itemView.findViewById(R.id.tvCountryName);
tvtotal=itemView.findViewById(R.id.tvCountrytotalcaese);
imageView = itemView.findViewById(R.id.imageFlag);
linearLayout=itemView.findViewById(R.id.linear_layout);
}
}
my AffectedCoutries class activity is as follows:
public class AffectedCountries extends AppCompatActivity {
EditText edtSearch;
RecyclerView recyclerView;
SimpleArcLoader simpleArcLoader;
public static ArrayList countryList = new ArrayList<>();
Countries_data countryData;
Countries_adapter CountriesAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_affected_countries);
edtSearch = findViewById(R.id.edtSearch);
recyclerView=findViewById(R.id.recyclerAffectedCountries);
simpleArcLoader = findViewById(R.id.loader);
fetchData();
}
private void fetchData() {
String url = "https://corona.lmao.ninja/v2/countries/";
simpleArcLoader.start();
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String countryName = jsonObject.getString("country");
String cases = jsonObject.getString("cases");
String todayCases = jsonObject.getString("todayCases");
String deaths = jsonObject.getString("deaths");
String todayDeaths = jsonObject.getString("todayDeaths");
String recovered = jsonObject.getString("recovered");
String active = jsonObject.getString("active");
String critical = jsonObject.getString("critical");
JSONObject object = jsonObject.getJSONObject("countryInfo");
String flagUrl = object.getString("flag");
countryData = new Countries_data(flagUrl,countryName,cases,todayCases,deaths,todayDeaths,recovered,active,critical);
countryList.add(countryData);
}
CountriesAdapter = new Countries_adapter(AffectedCountries.this,countryList);
recyclerView.setLayoutManager(new LinearLayoutManager(AffectedCountries.this));
recyclerView.setAdapter(CountriesAdapter);
simpleArcLoader.stop();
simpleArcLoader.setVisibility(View.GONE);
} catch (JSONException e) {
e.printStackTrace();
simpleArcLoader.start();
simpleArcLoader.setVisibility(View.GONE);
Toast.makeText(AffectedCountries.this,"catch response", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
simpleArcLoader.stop();
simpleArcLoader.setVisibility(View.GONE);
Toast.makeText(AffectedCountries.this,"error response", Toast.LENGTH_SHORT).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
}
my Countries_data class(model class)
public class Countries_data {
public String country;
public String cases;
public String todayCases;
public String deaths;
public String todayDeaths;
public String recovered;
public String active;
public String critical;
public String flag;
public Countries_data(String flag, String country, String cases, String
todayCases, String deaths, String todayDeaths, String recovered,
String active, String critical) {
this.country = country;
this.cases = cases;
this.todayCases = todayCases;
this.deaths = deaths;
this.todayDeaths = todayDeaths;
this.recovered = recovered;
this.active = active;
this.critical = critical;
this.flag = flag;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCases() {
return cases;
}
public void setCases(String cases) {
this.cases = cases;
}
public String getTodayCases() {
return todayCases;
}
public void setTodayCases(String todayCases) {
this.todayCases = todayCases;
}
public String getDeaths() {
return deaths;
}
public void setDeaths(String deaths) {
this.deaths = deaths;
}
public String getTodayDeaths() {
return todayDeaths;
}
public void setTodayDeaths(String todayDeaths) {
this.todayDeaths = todayDeaths;
}
public String getRecovered() {
return recovered;
}
public void setRecovered(String recovered) {
this.recovered = recovered;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getCritical() {
return critical;
}
public void setCritical(String critical) {
this.critical = critical;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
my Country_details class
public class CountriesDetails extends AppCompatActivity {
TextView tvCountry, tvCases, tvRecovered,tvdeaths;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_countries_details2);
tvCountry = findViewById(R.id.tvCountry);
tvCases = findViewById(R.id.tvCases);
tvRecovered = findViewById(R.id.tvRecovered);
tvdeaths=findViewById(R.id.tvTotalDeaths);
String positionCountry = getIntent().getStringExtra("Country");
Log.i("country name", positionCountry);
}
}
How to set the data in tvcases?
How can I show the data? Do I have to create a separate recycler view and then fetch the data from the API or can I use my main activity to show the data?
I have some sad information for you: Google Play policy restricts such apps from being published in store... especially when you are showing deaths count. Been there, done that, my app was blocked...
besides above:
you are passing country name in intent:
i.putExtra("Country",list.get(position).getCountry());
but trying to read "position" in details Activity - it will be always 0 (default)
edit due to comments:
pass position of clicked View
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(ct,CountriesDetails.class);
i.putExtra("position", position);
ct.startActivity(i);
}
});
in CountriesDetailss onCreate method receive this position and restore proper Countries_data object from your static countryList array in AffectedCountries
int position = getIntent().getIntExtra("position", 0);
Countries_data country = AffectedCountries.countryList.get(position);
tvCountry.setText(country.getCountry());
that should work, but this isn't best way to store data, in fact its very weak... after downloading data (list of countries) you should store it somehow, e.g. SQLite/Room lib or at least SharedPreferences... then in details activity you should restore int position and using it take proper object from database or preferences, instead of stright from static array
it may be also useful to implement Parcelable inteface to your Countries_data - this will allow to put whole Countries_data object into Intents extras, not only primitive int with position in array. in this case details activity won't even need access to whole array or sql database/preferences, it will get whole object straight from Intents extras
I'm having a problem retrieving the payments data. It always says I can't convert object type to:
com.google.firebase.database.DatabaseException: Can't convert object
of type java.lang.String to type
com.pasarkaget.fajar.pasarkaget.Model.Payments
I'm think this error from my model payments but I don't know my mistake. Anyone can help me?
This My AdminUserPaymentsActivity where I must display the payments data certain user.
public class AdminUserPaymentActivity extends AppCompatActivity
{
private RecyclerView paymentsList;
RecyclerView.LayoutManager layoutManager;
private DatabaseReference paymentsRef;
private String userID = "";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_user_payments);
userID = getIntent().getStringExtra("uid");
paymentsList = findViewById(R.id.payments_list);
paymentsList.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
paymentsList.setLayoutManager(layoutManager);
paymentsRef = FirebaseDatabase.getInstance().getReference()
.child("Cart List").child("Admin View").child(userID).child("Payments");
}
#Override
protected void onStart()
{
super.onStart();
FirebaseRecyclerOptions<Payments> options =
new FirebaseRecyclerOptions.Builder<Payments>()
.setQuery(paymentsRef, Payments.class)
.build();
FirebaseRecyclerAdapter<Payments, PaymentsViewHolder> adapter = new FirebaseRecyclerAdapter<Payments, PaymentsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull PaymentsViewHolder holder, int position, #NonNull Payments model)
{
holder.txtMyBankName.setText(model.getBuyerBank());
holder.txtBankAccountName.setText(model.getBuyerAccount());
holder.txtBankName.setText(model.getBank());
holder.txtMetods.setText(model.getMetods());
holder.txtTotalTransfer.setText("Rp " + model.getNominal());
holder.txtState.setText(model.getState());
holder.txtDate.setText("Pada Tanggal : " + model.getDate());
}
#NonNull
#Override
public PaymentsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.payments_items_layout, parent, false);
PaymentsViewHolder holder = new PaymentsViewHolder(view);
return holder;
}
};
paymentsList.setAdapter(adapter);
adapter.startListening();
}
}
My Viewholder Class
public class PaymentsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
public TextView txtBankName, txtMyBankName, txtBankAccountName, txtTotalTransfer, txtMetods, txtState, txtDate;
private ItemClickListener itemClickListener;
public PaymentsViewHolder(View itemView)
{
super(itemView);
txtBankName = itemView.findViewById(R.id.payments_bank_destination);
txtMyBankName = itemView.findViewById(R.id.payments_bank_name);
txtBankAccountName = itemView.findViewById(R.id.payments_bank_account);
txtTotalTransfer = itemView.findViewById(R.id.payments_total_transfer);
txtMetods = itemView.findViewById(R.id.payments_bank_metods);
txtState = itemView.findViewById(R.id.payments_state);
txtDate = itemView.findViewById(R.id.payments_date);
}
#Override
public void onClick(View view)
{
itemClickListener.onClick(view, getAdapterPosition(), false);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
}
And Lastly, My Model Payments class
public class Payments
{
private String bank, buyerBank, buyerAccount, nominal, metods, state, date, time;
public Payments()
{
}
public Payments(String bank, String buyerBank, String buyerAccount, String nominal, String metods, String state, String date, String time)
{
this.bank = bank;
this.buyerBank = buyerBank;
this.buyerAccount = buyerAccount;
this.nominal = nominal;
this.metods = metods;
this.state= state;
this.date = date;
this.time = time;
}
public String getBank() {
return bank;
}
public void setBank(String bank) {
this.bank = bank;
}
public String getBuyerBank() {
return buyerBank;
}
public void setBuyerBank(String buyerBank) {
this.buyerBank = buyerBank;
}
public String getBuyerAccount() {
return buyerAccount;
}
public void setBuyerAccount(String buyerAccount) {
this.buyerAccount = buyerAccount;
}
public String getNominal() {
return nominal;
}
public void setNominal(String nominal) {
this.nominal = nominal;
}
public String getMetods() {
return metods;
}
public void setMetods(String metods) {
this.metods = metods;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
My Firebase database structured:
my structured firebase
When you are passing your paymentsRef to the FirebaseRecyclerOptions<Payments> object it means that you are looking for Payments objects but within your reference, there are only objects of type String and not Payments, and that's why you get that error. To solve this, simply remove the call to .child("Payments"):
paymentsRef = FirebaseDatabase.getInstance().getReference()
.child("Cart List").child("Admin View").child(userID);
And you'll be able to get all Payments objects that exist within your userID node.
I have a FirebaseRecyclerAdapter fetching data from the firebase database but when I am trying to access firebase data the getter method of the POJO returns null. I am able to get the database reference key.
final Query beveragesQuery = mDatabaseReference.child(FirebaseValues.PRODUCTS)
.child(FirebaseValues.BEVERAGES);
FirebaseRecyclerOptions<GenericProductModel> beveragesOptions =
new FirebaseRecyclerOptions.Builder<GenericProductModel>()
.setQuery(beveragesQuery, GenericProductModel.class)
.build();
adapter = new FirebaseRecyclerAdapter<GenericProductModel, Combos.MovieViewHolder>(
beveragesOptions
) {
#NonNull
#Override
public Combos.MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_cardview_layout, parent, false);
return new Combos.MovieViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull Combos.MovieViewHolder viewHolder, int position, #NonNull GenericProductModel model) {
Log.d(TAG, "Item received:"+getRef(position).getKey());
String json = new Gson().toJson(model);
Log.d(TAG, "Item received:"+ json);
Log.d(TAG, "Item received:"+ model.toString());
if (tv_no_item.getVisibility() == View.VISIBLE) {
tv_no_item.setVisibility(View.GONE);
}
Log.d(TAG, "card name:"+model.getCardname());
viewHolder.cardname.setText(model.getCardname());
viewHolder.cardprice.setText("₹ " + Float.toString(model.getCardprice()));
Picasso.get().load(model.getCardimage()).into(viewHolder.cardimage);
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Beverages.this, IndividualProduct.class);
intent.putExtra("product", getItem(position));
startActivity(intent);
}
});
}
#Override
public void onError(DatabaseError e) {
Log.e(TAG, "RV Adapter, Error occurred: " + e.getMessage());
}
};
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
adapter.startListening();
mRecyclerView.setAdapter(adapter);
}
My POJO or model class is
public class GenericProductModel implements Serializable {
public int cardid;
public String cardname;
public String cardimage;
public String carddescription;
public float cardprice;
public GenericProductModel() {
}
public GenericProductModel(int cardid, String cardname, String cardimage, String carddescription, float cardprice) {
this.cardid = cardid;
this.cardname = cardname;
this.cardimage = cardimage;
this.carddescription = carddescription;
this.cardprice = cardprice;
}
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
public void setCardid(int cardid) {
this.cardid = cardid;
}
public void setCardname(String cardname) {
this.cardname = cardname;
}
public void setCardimage(String cardimage) {
this.cardimage = cardimage;
}
public void setCarddescription(String carddescription) {
this.carddescription = carddescription;
}
public void setCardprice(float cardprice) {
this.cardprice = cardprice;
}
}
I am implementing Serializable because I am sending this data as an intent to other activity.
Added some more log options for clearity
When I run the app the log output I am getting is:
03-17 15:05:55.200 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received, received:1
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received:{"a":0,"e":0.0}
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received:com.vdeveloper.chaisutta.b.a#63d3fc
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: card name:null
Database Screenshot:
I have found a solution myself. The problem was with my POJO. As this project was on androidx I need to add the annotation "#Keep" to stop the compiler from removing methods which it thinks are redundant.
import java.io.Serializable;
import androidx.annotation.Keep;
#Keep
public class GenericProductModel implements Serializable {
public int cardid;
public String cardname;
public String cardimage;
public String carddescription;
public float cardprice;
public GenericProductModel() {
}
public GenericProductModel(int cardid, String cardname, String cardimage, String carddescription, float cardprice) {
this.cardid = cardid;
this.cardname = cardname;
this.cardimage = cardimage;
this.carddescription = carddescription;
this.cardprice = cardprice;
}
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
public void setCardid(int cardid) {
this.cardid = cardid;
}
public void setCardname(String cardname) {
this.cardname = cardname;
}
public void setCardimage(String cardimage) {
this.cardimage = cardimage;
}
public void setCarddescription(String carddescription) {
this.carddescription = carddescription;
}
public void setCardprice(float cardprice) {
this.cardprice = cardprice;
}
}
Thanks, everyone for helping
You are getting null because all your values are null since you are returning in each getter this.fieldName instead of the fieldName. To solve this, please change your getters to:
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
See, there is no this anymore.
I’ve been trying to get recycler view working with retrofit. I seem to be pulling in the JSON fine from within getRecipes() method, and my logs are showing me that the some data is there.
However, when I call my getRecipes() method from onCreate(), something seems to be going wrong. When I check to see if my recipeList array contains my JSON results within onCreate, it is telling me it is empty. Why is it doing this if my logs within my getRecipes() method are showing me that data is there...?
Not sure if it is an issue with my recycler view or what I am doing with retrofit, or something else. Been trying for days to figure out, so any advice would be greatly appreciated.
JSON
https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json
public class ItemListActivity extends AppCompatActivity {
private boolean mTwoPane;
public static final String LOG_TAG = "myLogs";
public static List<Recipe> recipeList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getRecipes();
setContentView(R.layout.activity_item_list);
getRecipes();
//Logging to check that recipeList contains data
if(recipeList.isEmpty()){
Log.d(LOG_TAG, "Is empty");
}else {
Log.d(LOG_TAG, "Is not empty");
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.item_list);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);
recyclerView.setAdapter(simpleItemRecyclerViewAdapter);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
}
}
public void getRecipes(){
String ROOT_URL = "https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/";
Retrofit RETROFIT = new Retrofit.Builder()
.baseUrl(ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RecipeService service = RETROFIT.create(RecipeService.class);
Call<List<Recipe>> call = service.getMyJson();
call.enqueue(new Callback<List<Recipe>>() {
#Override
public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) {
Log.d(LOG_TAG, "Got here");
if (!response.isSuccessful()) {
Log.d(LOG_TAG, "No Success");
}
Log.d(LOG_TAG, "Got here");
recipeList = response.body();
//Logging to check data is there
Log.v(LOG_TAG, "LOGS" + recipeList.size());
for (int i = 0; i < recipeList.size(); i++) {
String newString = recipeList.get(i).getName();
Ingredients[] ingredients = recipeList.get(i).getIngredients();
for(int j = 0; j < ingredients.length; j++){
Log.d(LOG_TAG, ingredients[j].getIngredient());
}
Steps[] steps = recipeList.get(i).getSteps();
for(int k = 0; k < steps.length; k++){
Log.d(LOG_TAG, steps[k].getDescription());
}
Log.d(LOG_TAG, newString);
}
}
#Override
public void onFailure(Call<List<Recipe>> call, Throwable t) {
Log.e("getRecipes throwable: ", t.getMessage());
t.printStackTrace();
}
});
}
public class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final List<Recipe> mValues;
public SimpleItemRecyclerViewAdapter(List<Recipe> items) {
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list_content, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mContentView.setText(mValues.get(position).getName());
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId());
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, ItemDetailActivity.class);
intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId());
context.startActivity(intent);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public View mView;
public TextView mContentView;
public Recipe mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mContentView = (TextView) view.findViewById(R.id.content);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
RecipeService
public interface RecipeService {
#GET("baking.json")
Call<List<Recipe>> getMyJson();}
Models
Recipe
public class Recipe{
private Ingredients[] ingredients;
private String id;
private String servings;
private String name;
private String image;
private Steps[] steps;
public Ingredients[] getIngredients ()
{
return ingredients;
}
public void setIngredients (Ingredients[] ingredients)
{
this.ingredients = ingredients;
}
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
public String getServings ()
{
return servings;
}
public void setServings (String servings)
{
this.servings = servings;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getImage ()
{
return image;
}
public void setImage (String image)
{
this.image = image;
}
public Steps[] getSteps ()
{
return steps;
}
public void setSteps (Steps[] steps)
{
this.steps = steps;
}
#Override
public String toString()
{
return "[ingredients = "+ingredients+", id = "+id+", servings = "+servings+", name = "+name+", image = "+image+", steps = "+steps+"]";
}}
Ingredients
public class Ingredients{
private String measure;
private String ingredient;
private String quantity;
public String getMeasure ()
{
return measure;
}
public void setMeasure (String measure)
{
this.measure = measure;
}
public String getIngredient ()
{
return ingredient;
}
public void setIngredient (String ingredient)
{
this.ingredient = ingredient;
}
public String getQuantity ()
{
return quantity;
}
public void setQuantity (String quantity)
{
this.quantity = quantity;
}
#Override
public String toString()
{
return "[measure = "+measure+", ingredient = "+ingredient+", quantity = "+quantity+"]";
}}
Steps
public class Steps{
private String id;
private String shortDescription;
private String description;
private String videoURL;
private String thumbnailURL;
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
public String getShortDescription ()
{
return shortDescription;
}
public void setShortDescription (String shortDescription)
{
this.shortDescription = shortDescription;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public String getVideoURL ()
{
return videoURL;
}
public void setVideoURL (String videoURL)
{
this.videoURL = videoURL;
}
public String getThumbnailURL ()
{
return thumbnailURL;
}
public void setThumbnailURL (String thumbnailURL)
{
this.thumbnailURL = thumbnailURL;
}
#Override
public String toString()
{
return "[id = "+id+", shortDescription = "+shortDescription+", description = "+description+", videoURL = "+videoURL+", thumbnailURL = "+thumbnailURL+"]";
}}
Logs
https://gist.github.com/2triggers/12b6eeb32ed8909ab50bbadd4742d7f7
this will be empty always because this line will execute before getting the response from a server.
if(recipeList.isEmpty()){
Log.d(LOG_TAG, "Is empty");
}else {
Log.d(LOG_TAG, "Is not empty");
}
Better call this after this line recipeList = response.body();
SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);
recyclerView.setAdapter(simpleItemRecyclerViewAdapter);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
}
it is because you are sending the recipelist into the adapter before even it is populated , after you are sending the recipelist into the adapter which is empty you are populating your recipelist from getRecipes method, you might be wondering you have declared the getRecipes method before even you are assigning the recipelist to adapter so how come it is empty, yea but the fact is your getRecipes work on background thread so even before your recipelist gets populated your adapter assignment takes place on the main thread so you are basically assigning the empty list, one thing you can do is notify when the adapter when the data changes or when the the recipelist is filled with data that is from within the getRecipe method.
when you assign the recipelist = response.body right after this you can notify the adapter
or move this two lines
SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);
recyclerView.setAdapter(simpleItemRecyclerViewAdapter);
right after the
recipelist = response.body;
in getRecipes method
Try create the Constructor with all atributes from your Recipe.class
Like:
public Ingredients(String measure, String ingredients, String quantity ){
this.measure = measure;
this.ingredients = ingredients;
this.quantity = quantity
}
Do same in all class where make up your object of list.
Im having an issue with getting data that is obtained when my listadapter is set to my listview. Im trying to get this data in onItemClick so that i can put it into my intent extra's for my other activity to obtain.
The Problem
Currently i've created null string variables and then in my adapter assigning the strings with the desired text by methods within my model. However the problem im having is that the text that is being pulled is not the correct text for the position that onitemclick was called for.
Here some code...
XMLParseActivity
public class XMLParseActivity extends Activity implements AdapterView.OnItemClickListener {
private ListView mIssueListView;
private IssueParser mIssueParser;
private List<IssueFeed> mIssueList;
private IssueAdapter mIssueAdapter;
private String result_connectedtype = "";
private String result_symptom = "";
private String result_problem = "";
private String result_solution = "";
private String result_comments = "";
...
public class IssueAdapter extends ArrayAdapter<IssueFeed> {
public List<IssueFeed> issueFeedList;
public IssueAdapter(Context context, int textViewResourceId, List<IssueFeed> issueFeedList) {
super(context, textViewResourceId, issueFeedList);
this.issueFeedList = issueFeedList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
IssueHolder issueHolder = null;
if (convertView == null) {
view = View.inflate(XMLParseActivity.this, R.layout.issue_list_item, null);
issueHolder = new IssueHolder();
issueHolder.issueConnectedType = (TextView) view.findViewById(R.id.result_connected_type);
issueHolder.issueSymptomView = (TextView) view.findViewById(R.id.result_symptom);
view.setTag(issueHolder);
} else {
issueHolder = (IssueHolder) view.getTag();
}
IssueFeed issueFeed = issueFeedList.get(position);
issueHolder.issueConnectedType.setText(issueFeed.getConnected_type());
issueHolder.issueSymptomView.setText(issueFeed.getSymptom());
//THE DATA I WANT TO USE IN MY INTENT
result_solution = issueFeed.getSolution();
result_comments = issueFeed.getComments();
result_connectedtype = issueFeed.getConnected_type();
result_problem = issueFeed.getProblem();
result_symptom = issueFeed.getSymptom();
return view;
}
}
static class IssueHolder {
public TextView issueSymptomView;
public TextView issueConnectedType;
}
#Override
public void onItemClick(AdapterView<?> adapterView, View v, int position, long id) {
//Put the strings in intent extra
Intent intent = new Intent(this, SpecificIssueActivity.class);
intent.putExtra("symptom", result_symptom);
intent.putExtra("problem", result_problem);
intent.putExtra("solution", result_solution);
intent.putExtra("comments", result_comments);
intent.putExtra("connectedtype", result_connectedtype);
startActivity(intent);
}
The listAdapter is set in a asynctask in the below code
public class DoLocalParse extends AsyncTask<String, Void, List<IssueFeed>> {
ProgressDialog prog;
String jsonStr = null;
Handler innerHandler;
#Override
protected void onPreExecute() {
prog = new ProgressDialog(XMLParseActivity.this);
prog.setMessage("Loading....");
prog.show();
}
#Override
protected List<IssueFeed> doInBackground(String... params) {
mIssueParser = new IssueParser(null);
mIssueList = mIssueParser.parseLocally(params[0]);
return mIssueList;
}
#Override
protected void onPostExecute(List<IssueFeed> result) {
prog.dismiss();
runOnUiThread(new Runnable() {
#Override
public void run() {
mIssueAdapter = new IssueAdapter(XMLParseActivity.this, R.layout.issue_list_item,
mIssueList);
int count = mIssueAdapter.getCount();
if (count != 0 && mIssueAdapter != null) {
mIssueListView.setAdapter(mIssueAdapter);
}
}
});
}
}
And my model IssueFeed looks like this
public class IssueFeed implements Serializable {
private String connected_type;
private String symptom;
private String problem;
private String solution;
private String comments;
public IssueFeed() {
}
public IssueFeed(String connected_type, String symptom, String problem, String solution, String comments) {
this.connected_type = connected_type;
this.symptom = symptom;
this.problem = problem;
this.solution = solution;
this.comments = comments;
}
public String getConnected_type() {
return connected_type;
}
public String getSymptom() {
return symptom;
}
public String getProblem() {
return problem;
}
public String getSolution() {
return solution;
}
public String getComments() {
return comments;
}
public void setConnected_type(String connected_type) {
this.connected_type = connected_type;
}
public void setSymptom(String symptom) {
this.symptom = symptom;
}
public void setProblem(String problem) {
this.problem = problem;
}
public void setSolution(String solution) {
this.solution = solution;
}
public void setComments(String comments) {
this.comments = comments;
}
}
I have solve the issue by getting the data from some simple methods in my model to obtain the values.