I have a small problem that I can't solve:
I have an array of objects (Country) that I get them from API.
One of the parameters in each object(Country) is an array of border Country - value name = border.
In one Fragment I show all the countries that get from API.
One of my goals is to click on a some country and will opens a new screen where all the countries bordering the country I clicked on will be shown.
I already have all the logic of switching between screens, RecyclerViews on both screen and more, but I don't know how to create and parse the new array of the bordering countries to the new screen.
That what i have for now:
All countries adapter:
public class CountryAdapter extends RecyclerView.Adapter<CountryAdapter.CountryViewHolder> {
#Override
public void onBindViewHolder(#NonNull CountryViewHolder holder, final int position) {
holder.mTVCountryName.setText(countries.get(position).getName());
holder.mTVCountryNativeName.setText(countries.get(position).getNativeName());
GlideToVectorYou
.init()
.with(mContext)
.load(Uri.parse(countries.get(position).getFlag()), holder.mCountryFlag);
holder.mCountryFlag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (iOnItemClickListener != null) {
//Array list of all border countries by alpha3 value
List<String> borderCountriesAlpha3 = new ArrayList<>();
for (int i = 0; i < countries.get(position).getBorders().size(); i++) {
try {
borderCountriesAlpha3.add(countries.get(position).getBorders().get(i));
} catch (Exception e) {
}
}
iOnItemClickListener.onItemClick(position, borderCountriesAlpha3);
}
}
});
}
Getting the data from API:
public void getAllCountries(){
ApiService apiService = ApiClient.getRetrofitInstance().create(ApiService.class);
call = apiService.getAllCountries();
call.enqueue(new Callback<List<Country>>() {
#Override
public void onResponse(Call<List<Country>> call, Response<List<Country>> response) {
mCountryPresenter.generateDataList(response.body());
}
#Override
public void onFailure(Call<List<Country>> call, Throwable t) {
}
});
}
Country pojo class:
public class Country implements Comparable<Country> {
#SerializedName("name")
#Expose
private String name;
#SerializedName("alpha3Code")
#Expose
private String alpha3Code;
#SerializedName("borders")
#Expose
private List<String> borders = null;
#SerializedName("nativeName")
#Expose
private String nativeName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlpha3Code() {
return alpha3Code;
}
public void setAlpha3Code(String alpha3Code) {
this.alpha3Code = alpha3Code;
}
public List<String> getBorders() {
return borders;
}
public void setBorders(List<String> borders) {
this.borders = borders;
}
public String getNativeName() {
return nativeName;
}
public void setNativeName(String nativeName) {
this.nativeName = nativeName;
}
}
Fragment that contain recycler view for all countries:
public class CountryListFragment extends Fragment implements CountryPresenter {
private View view;
private RecyclerView mRVCountries;
private CountryAdapter mCountryAdapter;
private CountriesView mCountriesView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_country_list, container, false);
initView(view);
initClasses();
initContentView();
return view;
}
private void initClasses() {
mCountriesView = new CountriesView(this, getContext());
}
private void initView(View view) {
mRVCountries = view.findViewById(R.id.rvCountries);
}
private void initContentView() {
mCountriesView.getAllCountries();
}
#Override
public void generateDataList(List<Country> countries) {
mCountryAdapter = new CountryAdapter(countries, getContext(), getActivity());
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
mRVCountries.setLayoutManager(layoutManager);
mRVCountries.setAdapter(mCountryAdapter);
mCountryAdapter.setiOnItemClickListener(new CountryAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position, List<String> borderCountries) {
Log.d("myDebug", "onItemClick: " + position + " " + borderCountries);
}
});
}
public void sortByNativeName() {
mCountryAdapter.sortByNativeName();
}
public void sortByArea() {
mCountryAdapter.sortByArea();
}
}
You can use Java's streaming API or Collections API to search a list, copy a sublist to another etc. Here is an example of your requirement of finding bordering countries for a given country and get a lost of border country objects -
package com.advisory.pic.etl.claim.standardize;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
}
public void workOnCountries(){
List<Country> countries = Arrays.asList(new Country("United States","USA",Arrays.asList("MXO","CDA")),
new Country("Mexico","MXO",Arrays.asList("USA","CLB")),
new Country("Colombia","CLB",Arrays.asList("MXO","VNZ")),
new Country("Canada","CNA",Arrays.asList("USA")));
//get list of neighbouring countries for USA
//first find USA in the list of countries
Country country = null;
for(Country c : countries){
if(c.alpha3Code.equalsIgnoreCase("USA")){
country = c;
}
}
//find border countries
List<String> b = country.borders;
//get border contries from main country list
List<Country> borderCountries = countries.stream().filter(c -> b.contains(c)).collect(Collectors.toList());
}
private class Country{
Country(String name, String alpha3Code, List<String> borders){
this.name = name;
this.alpha3Code = alpha3Code;
this.borders = borders;
}
private String name;
private String alpha3Code;
private List<String> borders = null;
}
}
if you want to pass array of objects to another screen you can use serialize in bundle
mCountryAdapter.setiOnItemClickListener(new CountryAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position, List<String> borderCountries) {
Bundle bundle=new Bundle();
bundle.putSerializable("list",(ArrayList<String>) borderCountries);
// then you can add bundle to intent if you navigate activity or navigate
//fragment set this bundle
Log.d("myDebug", "onItemClick: " + position + " " + borderCountries);
}
});
Related
I have this recyclerview, when I click on an item I want to get the data in the red square from database.
And I want to show it like that
This is how I save it :
Save.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
#Override
public void onClick(View v) {
String refernce = TextRef.getEditText().getText().toString();
String nompdv = textNomPdv.getEditText().getText().toString();
String etat = textEtatCommande.getEditText().getText().toString();
String datecommande = TextDateCommande.getEditText().getText().toString();
String produitcommande = textProduit.getEditText().getText().toString();
String qntcommande = editTextProduitQnt.getEditText().getText().toString();
DatabaseReference newPost = reference.child(refernce);
newPost.child("refernce").setValue(refernce);
newPost.child("nompdv").setValue(nompdv);
newPost.child("etat").setValue(etat);
newPost.child("datecommande").setValue(datecommande);
newPost.child("user_id").setValue(uid);
Map<String, Object> values = new HashMap<>();
values.put(produitcommande, qntcommande);
DatabaseReference produitRef = reference.child(refernce).child("produit");
produitRef.updateChildren(values);
This is how I send data from first activity (recyclerview) :
v.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), Order_detail.class);
int pos = v.getAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
Order clickedDataItem = listArray.get(pos);
intent.putExtra("nompdv", clickedDataItem.getNompdv());
intent.putExtra("reference", clickedDataItem.getRefernce());
intent.putExtra("datecommande", clickedDataItem.getDatecommande());
intent.putExtra("etat", clickedDataItem.getEtat());
}
view.getContext().startActivity(intent);
}
});
How to do to get the products and their quantities when clicking on an item in recyclerview?
Update : This my Order class :
public class Order implements Serializable {
public String refernce, nompdv, etat, datecommande, produitcommande, qntcommande;
String user_id;
public Order(){}
public Order(String refernce, String nompdv, String etat, String datecommande, String produitcommande, String qntcommande, String user_id) {
this.refernce = refernce;
this.nompdv = nompdv;
this.etat = etat;
this.datecommande = datecommande;
this.produitcommande = produitcommande;
this.qntcommande = qntcommande;
this.user_id = user_id;
}
public String getRefernce() {
return refernce;
}
public void setRefernce(String refernce) {
this.refernce = refernce;
}
public String getNompdv() {
return nompdv;
}
public void setNompdv(String nompdv) {
this.nompdv = nompdv;
}
public String getEtat() {
return etat;
}
public void setEtat(String etat) {
this.etat = etat;
}
public String getDatecommande() {
return datecommande;
}
public void setDatecommande(String datecommande) {
this.datecommande = datecommande;
}
public String getProduitcommande() {
return produitcommande;
}
public void setProduitcommande(String produitcommande) {
this.produitcommande = produitcommande;
}
public String getQntcommande() {
return qntcommande;
}
public void setQntcommande(String qntcommande) {
this.qntcommande = qntcommande;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
}
The form how I save data
Update 2 :
This the Adapter for the recyclerview :
public class CommandeAdapter extends
RecyclerView.Adapter<CommandeAdapter.CommandeViewHolder> {
List<Order> listArray;
public CommandeAdapter(List<Order> List) {
this.listArray = List;
}
#NonNull
#Override
public CommandeAdapter.CommandeViewHolder onCreateViewHolder(#NonNull #NotNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.commande_model, parent, false);
return new CommandeViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull #NotNull CommandeAdapter.CommandeViewHolder holder, int position) {
CommandeViewHolder v = (CommandeViewHolder) holder;
final Order dataa = listArray.get(position);
v.nom_pdv.setText(dataa.getNompdv());
v.date.setText(dataa.getDatecommande());
v.etat.setText(dataa.getEtat());
v.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), Order_detail.class);
int pos = v.getAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
Order clickedDataItem = listArray.get(pos);
intent.putExtra("nompdv", clickedDataItem.getNompdv());
intent.putExtra("reference", clickedDataItem.getRefernce());
intent.putExtra("datecommande", clickedDataItem.getDatecommande());
intent.putExtra("etat", clickedDataItem.getEtat());
}
}
view.getContext().startActivity(intent);
}
});
}
public class CommandeViewHolder extends RecyclerView.ViewHolder {
TextView nom_pdv, date, etat;
public CommandeViewHolder(#NonNull #NotNull View itemView) {
super(itemView);
nom_pdv = itemView.findViewById(R.id.namepdv);
date = itemView.findViewById(R.id.dateliv);
etat = itemView.findViewById(R.id.etat);
}
}
#Override
public int getItemCount() {
return listArray.size();
}}
And this is activity detail :
public class Order_detail extends AppCompatActivity {
TextView namepdv, refcommande, datecommande, etat, produitcmnd, qnt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_commande_detail2);
namepdv = findViewById(R.id.nompdv);
refcommande = findViewById(R.id.refcommande);
datecommande = findViewById(R.id.datecommande);
etat = findViewById(R.id.etatcommande);
// --------------------- //
namepdv.setText(getIntent().getStringExtra("nompdv"));
refcommande.setText(getIntent().getStringExtra("reference"));
datecommande.setText(getIntent().getStringExtra("datecommande"));
etat.setText(getIntent().getStringExtra("etat"));
}}
From your question I am assuming that keys under produit are random.
So when you will retrieve order details produit will be a Hashmap. Declare produit as Hashmap<String,String> in Order class.
You can print those keys and values.
for(Map.Entry<String, String> e : clickedDataItem.getproduit().entrySet()) {
// print e.getKey() e.getValue()
}
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 am very new to android and developing an app which will fetch some data from Firebase realtime database and show data on UI. but whenever app is loaded just nothing happened. In the Logcat window it is continuously
showing:
D/KeyguardUpdateMonitor: received broadcast
android.intent.action.BATTERY_CHANGED
D/KeyguardUpdateMonitor: handleBatteryUpdate
I/BatteryInfoReceiver: ACTION_BATTERY_CHANGED
W/QCNEJ: |CORE| CNE received unexpected action:
android.intent.action.BATTERY_CHANGED
i have also tried to search it out but can't understand..
just want to know
what is the mean of this
"android.intent.action.BATTERY_CHANGED"
and why its not showing any data on UI.
my firebase realtime database rules (read/write) are set to true. because i am just trying something..
is there any problem with permissions or manifest file? because i
don't have included any of the permissions in app..
i am using my redmi note 4 for testing app.
code for the app is here..
Model class.
public class ad {
private String adImage, SellerID, price, location, adTitle, adDescription;
public ad(){
}
public ad(String adImage, String seller, String price, String location, String adTitle, String description) {
this.adImage = adImage;
this.SellerID = seller;
this.price = price;
this.location = location;
this.adTitle = adTitle;
this.adDescription = description;
}
public String getAdImage() {
return adImage;
}
public void setAdImage(String adImage) {
this.adImage = adImage;
}
public String getSellerID() {
return SellerID;
}
public void setSellerID(String seller) {
this.SellerID = seller;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getAdTitle() {
return adTitle;
}
public void setAdTitle(String adTitle) {
this.adTitle = adTitle;
}
public String getAdDescription() {
return adDescription;
}
public void setAdDescription(String adDescription) {
this.adDescription = adDescription;
}
}
my adsViewHolder class
public class adsViewHolder extends RecyclerView.ViewHolder {
public ImageView ad_image ;
public TextView ad_title ;
public TextView ad_price ;
public TextView ad_location;
public adsViewHolder(#NonNull View itemView) {
super(itemView);
ad_image = (ImageView)itemView.findViewById(R.id.defPic);
ad_title = (TextView)itemView.findViewById(R.id.adTitle);
ad_price = (TextView)itemView.findViewById(R.id.adPrice);
ad_location = (TextView)itemView.findViewById(R.id.AdCityName);
}
}
my AdsProfile Activity code for fetching and shwoing data on ui.
public class AdsProfile extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private RecyclerView AdsListRecyclerView;
private DatabaseReference mRef;
FirebaseRecyclerOptions<ad> options;
FirebaseRecyclerAdapter<ad, adsViewHolder> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ads_profile);
AdsListRecyclerView = (RecyclerView)findViewById(R.id.Ads_Display_Recycler_View);
AdsListRecyclerView.setHasFixedSize(true);
mRef = FirebaseDatabase.getInstance().getReference("ads");
options = new FirebaseRecyclerOptions.Builder<ad>()
.setQuery(mRef, ad.class).build();
adapter = new FirebaseRecyclerAdapter<ad, adsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull adsViewHolder holder, int position, #NonNull ad model) {
holder.ad_title.setText(model.getAdTitle());
holder.ad_price.setText(model.getPrice());
holder.ad_location.setText(model.getLocation());
}
#NonNull
#Override
public adsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.ad_layout,viewGroup,false);
return new adsViewHolder(view);
}
};
AdsListRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
adapter.startListening();
AdsListRecyclerView.setAdapter(adapter);
}
}
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’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.