I am trying to bind JSON data on to the recyclerView , but data seems not to bind to the RecyclerView.
Surprisingly when i Toast the data i see it's available. What could be the problem?
private void parseJson(String result){
try {
if (result!=null) {
String resultTostring = "" + result;
JSONObject obj = new JSONObject(resultTostring).getJSONObject("ScheduleResource");
JSONArray arr = obj.getJSONArray("Schedule");
itemList = new ArrayList<>();
for (int i = 0; i < arr.length(); i++)
{
String DepartureAirport = arr.getJSONObject(i).getJSONObject("Flight").getJSONObject("Departure").getString("AirportCode");
String ArrivalAirport = arr.getJSONObject(i).getJSONObject("Flight").getJSONObject("Arrival").getString("AirportCode");
String Duration = arr.getJSONObject(i).getJSONObject("TotalJourney").getString("Duration");
String DepartureTime = arr.getJSONObject(i).getJSONObject("Flight").getJSONObject("Departure").getJSONObject("ScheduledTimeLocal").getString("DateTime");
String ArrivalTime = arr.getJSONObject(i).getJSONObject("Flight").getJSONObject("Arrival").getJSONObject("ScheduledTimeLocal").getString("DateTime");
String Stops = arr.getJSONObject(i).getJSONObject("Flight").getJSONObject("Details").getJSONObject("Stops").getString("StopQuantity");
FlightModel model = new FlightModel();
model.setDepartureAirport(DepartureAirport);
model.setArrivalAirport(ArrivalAirport);
model.setDuration(Duration);
model.setDeparturTimee(DepartureTime);
model.setArrivalTime(ArrivalTime);
model.setStops(Stops);
model.Stops= Stops;
itemList.add(model);
Toast.makeText(FlightListActivity.this, "DEPT : " + DepartureAirport + " Arrival " + ArrivalAirport+
" Duration : " + Duration + " Dept time : "+ DepartureTime+" Arr Time "+ ArrivalTime
+" Stops "+ Stops, Toast.LENGTH_LONG).show();
}
// Setup and Handover data to recyclerview
final FlightAdapter adapter = new FlightAdapter(FlightListActivity.this, itemList);
flights_rv.setAdapter(adapter);
flights_rv.setLayoutManager(new LinearLayoutManager(FlightListActivity.this));
}
else{
Toast.makeText(FlightListActivity.this,Config.POOR_NETWORK_CONNECTION, Toast.LENGTH_LONG).show();
}
}
catch (JSONException r){
System.out.println("ERROR PROB : "+ r);
// Toast.makeText(ListOfFlights.this,"ERROR PROB : "+ r,Toast.LENGTH_LONG).show();
}
}
In my Adapter i have attached the Layout which will have the appearance of the data in the List , and also my POJO class is set which has both getters and setters, but when i try to attach the adapter on to the RecyclerView the data doesn't bind why ?
EDIT
My Adapter Class
public class FlightAdapter extends RecyclerView.Adapter<FlightHolder> {
private List<FlightModel> itemList= Collections.emptyList();
private Context context;
public FlightAdapter(Context context,List<FlightModel> itemList) {
this.context = context;
this.itemList = itemList;
}
#Override
public FlightHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_details, parent, false);
FlightHolder rcv = new FlightHolder(layoutView, context);
return rcv;
}
#Override
public void onBindViewHolder(FlightHolder holder, int position) {
final FlightModel sr = itemList.get(position);
final String DepartureAirport = sr.getDepartureAirport();
final String ArrivalAirport = sr.getArrivalAirport();
final String Duration = sr.getDuration();
final String DepartureTime = sr.getDeparturTimee();
final String ArrivalTime = sr.getArrivalTime();
final String Stops = sr.getStops();
final String DirectFlight = sr.getDirectFlights();
holder.from_txt.setText(DepartureAirport);
holder.to_txt.setText(ArrivalAirport);
holder.duration_txt.setText(Duration);
holder.depature_txt.setText(DepartureTime);
holder.arrival_txt.setText(ArrivalTime);
holder.stops_txt.setText(Stops);
holder.dept_txt.setText(DepartureAirport);
holder.arr_txt.setText(ArrivalAirport);
holder.root.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Intent i = new Intent(FlightAdapter.this.context, DetailsLocalLeader.class);
// context.startActivity(i);
}
});
}
#Override
public int getItemCount() {
;
return itemList.size();
}
}
For more information , below is the link to the project :
https://github.com/huxaiphaer/FlightsApp/blob/master/app/src/main/java/adapter/FlightAdapter.java
First of all, get someone to review your code structure. Read and understand Java Standard Naming Conventions. Use a design pattern for your app, probably MVP. Use Gson library to parse JSON data for you.
To answer your question, I would say that your JSON structure is flawed. Your code outputs this error
ERROR PROB : org.json.JSONException: Value "SOME_LONG_JSON" at Flight of type org.json.JSONArray cannot be converted to JSONObject
It means that you are trying to parse a JSONArray as a JSONObject. In the Schedule array, there's 9th entry which is supposed to be a JSONObject(as seen in previous 8 entries). But, it is a JSONArray.
So, first 8 entries are like:
{
"Departure": {},
"Arrival": {},
"MarketingCarrier": {},
"Equipment": {},
"Details": {}
}
and, the 9th entry is like :
[
{
"Departure": {},
"Arrival": {},
"MarketingCarrier": {},
"Equipment": {},
"Details": {}
},
{
"Departure": {},
"Arrival": {},
"MarketingCarrier": {},
"Equipment": {},
"Details": {}
}
]
That's why you get this parsing exception in try-catch block. So, you can do this to check if your object is JSONArray or JSONObject like this in parseJson(String result):
Object departureObject = arr.getJSONObject(i).getJSONObject("Flight").get("Departure");
if (departureObject instanceof JSONObject) {
String departureAirport = ((JSONObject) departureObject).getString("Airport");
}
else if (departureObject instanceof JSONArray) {
JSONArray departures = (JSONArray) departureObject;
// use for-loop here to get data from array
}
But, seriously, use POJO with Gson and simplify parsing process. Also, if you have control over how API works, try to keep an object of one type only. If it is supposed to be a list, it better be a list even if there are no items or if there's one or more.
Try these things, it might solve this problem, but I doubt it. You will face more problems with parsing I think. Ping me after you've done this.
Also, if you try to parse all of JSON received by Server, you will see that it is not even complete. Look at the end of your JSON data.
Try something like this for your adapter:
public class FlightAdapter extends RecyclerView.Adapter<FlightAdapter.MyViewHolder> {
private List<FlightModel> mItemList;
private Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
//TODO: Add all your views and the types hear!
Public TextView mTvName;
public MyViewHolder(View v){
super(v);
//TODO: add here for each view in your row
mTvName = (TextView)v.findViewById(R.id.tvName);
}
}
public FlightAdapter(Context context,List<FlightModel> itemList) {
this.context = context;
this.mItemList = itemList;
}
#Override
public FlightHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_details, parent, false);
return new MyViewHolder(layoutView);
}
#Override
public void onBindViewHolder(FlightHolder holder, int position) {
FlightModel model = mItemList.get(position);
//TODO: Add for each view and data point!!
String name = model.getName();
holder.mTvName.setText(name);
holder.layoutView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Intent i = new Intent(FlightAdapter.this.context, DetailsLocalLeader.class);
// context.startActivity(i);
}
});
}
#Override
public int getItemCount() {
return mItemList.size();
}
}
Disclaimer!
I typed this in a text editor, so there might be a few syntax errors or misspellings. Please let me know if you have any issues.
Related
I want to get string from arraylist inside oncreateview fragment but i cant figure itout since no position index has been pass. get(position) return error.
String price = arrayList.get(position).getPrice();
i need to get string price and settext for price.this is my main concern.
this values should return from arraylist.
this is response JSON array from volley using mysingleton.
Single Product Response: [{"price":"75","date":"2017-07-13 03:25:31","pk_i_id":"4"}]
this main activty fragment
public class MainActivityFragment extends Fragment {
private TextView product,price,date,title;
private String product_id;
ArrayList<ProductItem> arrayList = new ArrayList<>();
Context context;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_activity, container, false);
product = (TextView) view.findViewById(R.id.tv1);
title = (TextView) view.findViewById(R.id.tvTitle);
price = (TextView) view.findViewById(R.id.tvPrice);
date = (TextView) view.findViewById(R.id.tvDate);
if (getArguments() != null) {
Log.i(TAG, "getArgument is not null");
product_id = getArguments().getString("product_id");
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id);
arrayList = productBackgroundTask.getList();
String price = arrayList.get(position).getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
// price.setText(price);
}else {
Log.i(TAG, "getArgument is null");
}
return view;
}
}
this is task to get arraylist using volley
public class ProductBackgroundTask {
private Context context;
ArrayList<ProductItem> arrayList = new ArrayList<>();
String json_url = "phpfile.php";
private String product_id;
public ProductBackgroundTask(Context context, String product_id) {
this.context = context;
this.product_id = product_id;
}
public ArrayList<ProductItem> getList(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
return arrayList;
}
}
and this is class of array list
public class ProductItem {
private String Price,Date;
private int ProductId;
public ProductItem(String Price, String Date, int ProductId){
this.setPrice(Price);
this.setDate(Date);
this.setProductId(ProductId);
}
public int getProductId() {
return ProductId;
}
public void setProductId(int productId) {
ProductId = productId;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
Date = date;
}
Clearly in your oncreate you haven’t initialized the product item and you cannot parse the complete list.You can try two to solve this
1.Pass specific item number instead of position i.e
say if you want to show 4th item then position=3
2.Or write a loop like this to parse entire arrayList like this
for(ProductItem productItem:arrayList){
String price = productItem.getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
price.setText(price);
}
Mistake you're doing is that in the MainActivityFragment your trying to assign the value to the arrayList even before the data is added to the arrayList in the ProductBackgroundTask-getList. That's the reason you are getting the list null all the time. Try to use interfaces.
1.Make your MainActivityFragment implement the interface.
2.Set the value to the interface method once you get the data from the server.
3.Get the data in the MainActivityFragment inside interface method and do all the operation you're doing inside the onCreateView method.
Now your arraylist will have the data whatever you received from the server.
Below is the link for the example on interfaces if you haven't used them before. He is doing exactly as your requirement.
https://www.justinmccandless.com/post/setting-up-a-callback-function-in-android/
Allow me. The arrayList that you return from getList isn't populated at the time you call String price = arrayList.get(position).getPrice();. The server call using volley takes some time to process and that's when the onResponse gets called. This happens AFTER you've returned the arrayList which is in fact empty.
The sequence of events is as follows.
• Call to arrayList = productBackgroundTask.getList(); which returns an empty ArrayList.
• String price = arrayList.get(position).getPrice();
Now after a while..
• onResponse inside getList() gets called.
Do you now see why it's empty?
Simple Solution: • Define a simple interface ProductListener alongside ProductBackgroundTask. (With only a single abstract method onProducts).
• Instantiate it inside the Fragment's onCreateView using an anonymous class and pass it to the constructor of ProductListener to save it for later use. Do whatever you want to do with the products inside the onProducts method. (Since that will be called with the actual data)
• Call its onProducts method with the data that's parsed and fetched inside the onResponse method.
ProductBackgroundTask code:
public class ProductBackgroundTask {
private Context context;
// I removed the instance ArrayList since that can be made
// local.
// Here, we add a reference to our callback interface as we can use it later.
private ProductListener listener;
String json_url = "http://192.168.43.55/android/v1/productList.php";
private String product_id;
// Instantiate this class using an additional listener argument
// which would be a concrete implementation of our interface.
public ProductBackgroundTask(Context context, String product_id, ProductListener listener) {
this.context = context;
this.product_id = product_id;
this.listener = listener;
}
// getList should not return anything,
// so I keep the return as void.
public void getList() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
ArrayList<ProductItem> arrayList = new ArrayList<>();
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
// Notice this line here, this is what
// calls the callback with the products.
listener.onProducts(arrayList);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
}
}
// Callback interface, we would need a concrete implementation
// of this and pass that to the constructor of ProductBackgroundTask.
interface ProductListener {
void onProducts(ArrayList<ProductItem> products);
}
The code inside onCreateView:
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id, new ProductListener() {
// This method will be called with the needed products.
// Give an anonymous class implementation of our interface
// right here since we won't be using it anymore.
public void onProducts(ArrayList<ProductItem> products) {
// Get the price you want.
String str = arrayList.get(0).getPrice();
// Use str wherever necessary. Use the UI thread here if you need
// to change any visible elements on the screen.
}
});
// Simply call this method to get the ball rolling.
productBackgroundTask.getList();
This is a concrete implementation of the this answer and you won't be changing much code.
Please help me out to load more data from the server upon scrolling my RecyclerView . Here I have successfully created RecyclerView by loading data from my Mysql server by using volley string request.
Here is my code.
private void populateRecycleView() {
if (Utility.checkNetworkConnection(this)) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Searching...");
progressDialog.setMessage("Searching for the blood donor. Please wait a moment.");
progressDialog.setCancelable(false);
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.GET_DONORS_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONArray jsonArray = new JSONArray(response);
int count = 0;
while (count < jsonArray.length()) {
JSONObject jsonObject = jsonArray.getJSONObject(count);
String firstName = jsonObject.getString("fName");
String secondName = jsonObject.getString("sName");
String email = jsonObject.getString("emailid");
String password = jsonObject.getString("pass");
String mobile = jsonObject.getString("mobile");
String bloodRt = jsonObject.getString("blood");
String age = jsonObject.getString("age");
String gender = jsonObject.getString("gender");
String country = jsonObject.getString("country");
String location = jsonObject.getString("location");
String latitude = jsonObject.getString("latitude");
String longitude = jsonObject.getString("longitude");
String profilePicFIleName = jsonObject.getString("picname");
String profilePicURL = jsonObject.getString("pic");
Donor donor = new Donor(firstName, secondName, email, password, mobile, bloodRt, age, gender,
country, location, latitude, longitude, profilePicFIleName, profilePicURL);
donorsList.add(donor);
count++;
}
donorsAdapter = new DonorsAdapter(FindDonorResult.this, donorsList);
recyclerView = (RecyclerView) findViewById(R.id.rv_search_result_donor);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(FindDonorResult.this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(donorsAdapter);
donorsAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(FindDonorResult.this, "Active data network is not available.", Toast.LENGTH_LONG).show();
}
}
) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("bloodGroup", bloodGroup);
return params;
}
};
NetworkRequestSingleTon.getOurInstance(this).addToRequestQue(stringRequest);
} else {
Utility.checkNetworkConnectionFound(this);
}
}
And this is my RecyclerView adapter...
public class DonorsAdapter extends RecyclerView.Adapter<DonorsAdapter.CustomViewHolder> {
private Context context;
private ArrayList<Donor> donorList;
private String bloodGroup;
public DonorsAdapter(Context context, ArrayList<Donor> donorList) {
this.context = context;
this.donorList = donorList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_blood_donors_result,
parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
final Donor donor = donorList.get(position);
String displayName = donor.getFirstName() + " " + donor.getSecondName();
holder.tvDisplayName.setText(displayName);
holder.tvEmailID.setText(donor.getEmail());
String userProfileURL = donor.getProfilePicURL();
if (!userProfileURL.equals("")) {
Picasso.with(context).load(userProfileURL).resize(80, 80).centerCrop().
into(holder.ivProfilePic);
} else {
holder.ivProfilePic.setImageResource(R.drawable.ic_person_white_24dp);
}
bloodGroup = donor.getBloodGroup();
if (bloodGroup.equals("A+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_);
else if (bloodGroup.equals("A-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_negative);
else if (bloodGroup.equals("B+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_positive);
else if (bloodGroup.equals("B-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_negative);
else if (bloodGroup.equals("O+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_positive);
else if (bloodGroup.equals("O-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_negative);
else if (bloodGroup.equals("AB+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_positive);
else if (bloodGroup.equals("AB-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_negative);
if(Utility.isNetworkEnabled){
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, DisplayDonorDetails.class);
intent.putExtra("donor", donor);
context.startActivity(intent);
}
});
}else {
Toast.makeText(context, "Network not available.", Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
if(donorList != null){
return donorList.size();
}else {
return 0;
}
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
ImageView ivProfilePic, ivBloodTypeDisplay, ivArrow;
TextView tvDisplayName;
TextView tvEmailID;
ConstraintLayout constraintLayout;
public CustomViewHolder(View itemView) {
super(itemView);
ivProfilePic = (ImageView) itemView.findViewById(R.id.civ_user_profile_picture);
ivBloodTypeDisplay = (ImageView) itemView.findViewById(R.id.civ_user_blood_type_display);
ivArrow = (ImageView) itemView.findViewById(R.id.civ_arrow);
tvDisplayName = (TextView) itemView.findViewById(R.id.tvUserNameOnRV);
tvEmailID = (TextView) itemView.findViewById(R.id.tvEmailDisplayOnRV);
constraintLayout = (ConstraintLayout) itemView.findViewById(R.id.recycle_view_item_container);
}
}
}
Populate your donorsAdapter only with the 50 first elements of your donorsList, create a function that save the position of the latest element displayed and add other 50 donors to your adapter starting from the latest position saved when you need it.
Hope it helps.
EDIT
First create an emptyList:
List<Donor> subElements = new ArrayList<>();
and pass it to your adapter:
donorsAdapter = new DonorsAdapter(FindDonorResult.this, subElements);
Now you can create a method like this (you can call in onClick event for example):
private int LAST_POSITION = 0;
private int DONORS_NUM_TOSHOW = 50;
public void showMoreDonors(){
if(donarsList.size() > Last_postion+50){
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,Last_postion+DONORS_NUM_TOSHOW));
for(Donor a : tempList){
subElements.add(a);
}
Last_postion += DONORS_NUM_TOSHOW;
donorsAdapter.notifyDataSetChanged();
}else{
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,donorsList.size()));
for(Donor a : tempList){
subElements.add(a);
}
donorsAdapter.notifyDataSetChanged();
}
}
Remember to check when donorsList is over.
I didn't test it, but i hope it is usefull to understand the idea.
Finally, I sort this out. I have got an awesome tutorial from this blog.
http://android-pratap.blogspot.in/2015/06/endless-recyclerview-with-progress-bar.html.
I made some changes to populate the list because my data is on a remote server and by using volley library I fetched the data into the list. Remaining things are same.
How to Loop to show all cuisine data (New American, Japanese, Asia). In RestaurantRVAdapter, I used like this -
List<Restaurant> restaurant; // There is a data in restaurant holder.tv_cuisine.setText(restaurant.getCuisine().get(0).getCuisineName());
It only shows New American because I use .get(0).getCuisineName()
[
{...},
{...},
{...},
{...},
{
"restaurant_id": "41",
"restaurant_logo": "52ee9f67ce39f62d9c0b1538ca26646f.jpg",
"restaurant_name": "Shwe Lar Food Restaurant",
"street_address": "Napier Road",
"phone_no": "09940255323430",
"rating": "4.5",
"cuisine": [
{
"cuisine_name": "New American"
},
{
"cuisine_name": "Japanese"
},
{
"cuisine_name": "Asia"
}
],
}
]
In your RecyclerView Adapter update your code like this.
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Restaurant rest = restaurant.get(position);
holder.tv_cuisine.setText(rest.getCuisineName());
}
First you get jsonArray then used fori lool to get all json object then you can get exat data, like as
JSONArray jsonArray = obj.getJSONArray("cuisine");
List<JSONObject> postList = new ArrayList<JSONObject>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonPost = jsonArray.getJSONObject(i);
postList.add(jsonPost);
}
mAdapter.updateList(postList, mStockstype);
in Adapter you make a method like
public void updateList(List<JSONObject> list, String type) {
mDataList.clear();
mDataList.addAll(list);
notifyDataSetChanged();
}
Then in adapter you get you data
JSONObject object = mDataList.get(position);
String name = object.optString("cuisine_name");
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Restaurant rest = restaurant.get(position); // get the specific restaurent
List<Cuisine> cuisineList = rest.getCuisine(); // list to carry cuisineList
String cuisineString = ""; //string to carrying cuisines
for(int i=0; i<cuisineList.size(); i++) {
cuisineString.concat(cuisineList.get(i));
cuisineString.concat(",");
}
holder.tv_cuisine.setText(strCuisine);
}
Build comma separated text for Cuisines,
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Restaurant rest = restaurant.get(position);
List<Cuisine> cuisineList = rest.getCuisine();
// Build comma separated text for Cuisines
String strCuisine = "";
for(i=0; i<cuisineList.size(); i++) {
strCuisine.concat(cuisineList.get(i).getCuisineName());
strCuisine.concat(",");
}
holder.tv_cuisine.setText(strCuisine);
}
It should like this,
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Restaurant rest = restaurant.get(position); // get the specific restaurent
List<Cuisine> cuisineList = rest.getCuisine(); // list to carry cuisineList
String cuisineString = ""; //string to carrying cuisines
for(int i=0; i<cuisineList.size(); i++) {
cuisineString.concat(cuisineList.get(i).getCuisineName());
cuisineString.concat(",");
}
cuisineString = cuisineString.substring(0, cuisineString.length() - 1);// Removes last ,
holder.tv_cuisine.setText(cuisineString);
}
I got tired using this library, this is my first time using it and made a lot of success ways, but i'm a bit confused in getting the following Json :
{
"Guides":
{
"English": {"ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
,"Arabic": {"EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
}
}
Googled and saw a lot of guides and answered, and made my List like this :
public class PostItem {
List<PostItemArabic> Arabic;
List<PostItemEnglish> English;
}
class PostItemArabic{
private String ArabicSony;
private String ArabicNexus;
private String ArabicSamsung;
private String ArabicHTC;
public String getArabicSony() {
return ArabicSony;
}
public void setArabicSony(String arabicSony) {
ArabicSony = arabicSony;
}
public String getArabicNexus() {
return ArabicNexus;
}
public void setArabicNexus(String arabicNexus) {
ArabicNexus = arabicNexus;
}
public String getArabicSamsung() {
return ArabicSamsung;
}
public void setArabicSamsung(String arabicSamsung) {
ArabicSamsung = arabicSamsung;
}
public String getArabicHTC() {
return ArabicHTC;
}
public void setArabicHTC(String arabicHTC) {
ArabicHTC = arabicHTC;
}
}
class PostItemEnglish{
private String EnglishSony;
private String EnglishNexus;
private String EnglishSamsung;
private String EnglishHTC;
public String getEnglishSony() {
return EnglishSony;
}
public void setEnglishSony(String englishSony) {
EnglishSony = englishSony;
}
public String getEnglishNexus() {
return EnglishNexus;
}
public void setEnglishNexus(String englishNexus) {
EnglishNexus = englishNexus;
}
public String getEnglishSamsung() {
return EnglishSamsung;
}
public void setEnglishSamsung(String englishSamsung) {
EnglishSamsung = englishSamsung;
}
public String getEnglishHTC() {
return EnglishHTC;
}
public void setEnglishHTC(String englishHTC) {
EnglishHTC = englishHTC;
}
}
My Model :
private class Model {
private List<PostItem> Guides;
public List<PostItem> getGuides() {
return Guides;
}
public void setGuides(List<PostItem> roms_center) {
this.Guides = roms_center;
}
}
And printing the result like this :
List<PostItem> Guides = response.body().getGuides();
for(int i = 0 ; i < Guides.size() ; i ++ ) {
for (int b = 0; b < Guides.get(i).English.size() ; b++){
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishHTC());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishNexus());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSamsung());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSony());
}
for (int b = 0; b < Guides.get(i).Arabic.size() ; b++){
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicHTC());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicNexus());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSamsung());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSony());
}
}
My work isn't correct, and getting a lot of errors,
Here's the last error i got :
`Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 3 column 18 path $.Guides
What's the way to make it correct ? `
Based on your models when you try to get the guides list your telling retrofit to populate an array. Retrofit is then getting the data and finding that it is a single object and not array. So you need to update your model to reflect the data returned. For example:
class PostItem {
List<Language> mLanguages;
}
class Language{
String mLanguageTitle; //for example english
List<String> mData; //for this is your list of data
}
Then in your activity instead of getting guides you would get just a post item for example:
response.body().getPostItem();
Hope it helps !
First of all, you can use the retrofit Gson library.
You can handle this in two ways:
Option 1: reformat your languages in your json to be an array like Doug says.
{
"Guides":
[
{"Lang":"English","ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
, {"Lang":"Arabic","EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
]
}
Then you will need to redesign your class to reflect this structure.
Like Doug sayd:
class PostItem {
List<Language> mLanguages;
}
Option 2: Create a custom json desirializer in your class. this will take the Json and break it down into whatever structure you want it to be.
public class PostItem implements JsonDeserializer
#Override
public MyDesirializer deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jarabic = (JsonObject) json.get("Arabic");
//whatever manipulations you want to do (fill with your own code)
PostItem item = new PostItem();
item.arabic = jarabic;
...
...
return item;
}
I know that there are several similar questions already answered, but because the fact that I'm very new to Android development, I couldn't figure out how to solve this on my own. The question is pretty self-explanatory. I'm fetching data from the database over HTTP request and want to adapt that data into a listview. I'm using Volley for my HTTP requests and underneath is my onResponse -method.
Everything else works perfectly, I just haven't found a way to adapt that data into a listview.
#Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
// If we are getting success from server
try {
JSONObject jObject = new JSONObject(response);
int count = jObject.getInt("count");
if(count == 0) {
noEventsTextView.setText(jObject.getString("msg").toString());
noEventsTextView.setGravity(Gravity.CENTER);
noEventsImageView.setVisibility(View.VISIBLE);
} else {
JSONArray childArray = jObject.getJSONArray("lectures");
for(int i = 0; i < childArray.length(); i++) {
JSONObject finalObject = childArray.getJSONObject(i);
// TODO Adapt data to listView
}
}
} catch(JSONException e) {
e.printStackTrace();
}
}
}
And here's an example of JSON I get back from the server:
{
count: 2,
msg: "",
lectures: [
{
id: "1",
starting_at: "2015-11-30 13:00:00",
ending_at: "2015-11-30 15:00:00",
user_id: "1",
course: "Course #1",
user_name: "John Doe"
},
{
id: "2",
starting_at: "2015-11-30 13:00:00",
ending_at: "2015-11-30 15:00:00",
user_id: "1",
course: "Course #2",
user_name: "John Doe"
}
]
}
Create a class of each key value pairs of Json and the map your json to that class using Jackson and the add generic list of that class to your List Adapter .
Like
Custom Class{
String id;
String starting_at;
String ending_at;
String user_id;
String course ;
String username;
}
Map your response through Jackson to ArrayList
and then
ListAdapter(ArrayList)
https://w2davids.wordpress.com/android-json-parsing-made-easy-using-jackson/
and you are ready to go.......you can use gson also but jackson is a bit faster so you can go for anyone according to ur need......
hope it helps.
create array Variables for each key value pairs of Json.
and pass all those variable to a listview.
new Listadapter(this,id[],starting_at[],ending_at[],user_id[],course[],username[]);
or There is a concept called Gson.
which will allow you to write data to Serializable class without using array.
And after assigning data to these class you can pass the Serializable class to adapter and used it inside adapter getView method.
There is a simple tutorial on this which I wrote to assign data to serializable class, think it will give you an idea.
hope it helps.
You can have a POJO consisting of all the keys a lecture has.
DataPOJO.java
public class DataPOJO {
private int id;
private String starting_at;
private String ending_at;
private String user_id;
private String course;
private String user_name;
}
Inside your onResponse:
#Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
// If we are getting success from server
try {
JSONObject jObject = new JSONObject(response);
int count = jObject.getInt("count");
if(count == 0) {
noEventsTextView.setText(jObject.getString("msg").toString());
noEventsTextView.setGravity(Gravity.CENTER);
noEventsImageView.setVisibility(View.VISIBLE);
} else {
JSONArray childArray = jObject.getJSONArray("lectures");
ArrayList<DataPOJO> datas = new ArrayList<DataPOJO>();
for(int i = 0; i < childArray.length(); i++) {
JSONObject finalObject = childArray.getJSONObject(i);
DataPOJO data = new DataPOJO;
data.id = finalObject.getInt("id");
data.starting_at = finalObject.getString("starting_at");
//so on
//add data to arraylist......
datas.add(data);
}
//set adapter of your listview here, you have to have an instance of your list view
listView.setAdapter(new MyAdapter(datas, context));
}
} catch(JSONException e) {
e.printStackTrace();
}
}
}
MyAdapter.java
public class MyAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<DataPOJO> listItem;
public MyAdapter(Context mContext, ArrayList<DataPOJO> listItem) {
this.mContext = mContext;
this.listItem = listItem;
}
#Override
public int getCount() {
return listItem.size();
}
#Override
public Object getItem(int position) {
return listItem.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_items, null);
((TextView) convertView.findViewById(R.id.name)).setText(listItem.get(position).user_name);
return convertView;
}
}
list_items.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#000"
android:textSize="18sp"/>
</RelativeLayout>