I am using a Fragment to view a RecyclerView. But I always get this error
E/RecyclerView: No adapter attached; skipping layout
I have created an adapter for my recyclerview but the layout does not display. The php backend is working fine. Can somebody please help. Here are my codes for the fragment and adapter
Tips.java
public class Tips extends Fragment {
Configuration config = new Configuration();
String HttpUrl = config.viewtips_url;
List<TipModel> tipList;
RecyclerView recyclerView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_tips, container, false);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
tipList = new ArrayList<>();
loadTips();
return view;
}
private void loadTips() {
StringRequest stringRequest = new StringRequest(Request.Method.GET, HttpUrl,
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);
tipList.add(new TipModel(
jsonObject.getInt("id"),
jsonObject.getString("tip")
));
}
TipAdapter tipAdapter = new TipAdapter(getActivity(), tipList);
recyclerView.setAdapter(tipAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(getActivity()).add(stringRequest);
}
TipAdapter.java
public class TipAdapter extends RecyclerView.Adapter<TipAdapter.TipViewHolder> {
private Context context;
private List<TipModel> tipList;
public TipAdapter(Context context, List<TipModel> tipList) {
this.context = context;
this.tipList = tipList;
}
#Override
public TipViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.itemlayout, null);
return new TipViewHolder(view);
}
#Override
public void onBindViewHolder(TipViewHolder holder, int position) {
TipModel tipModel = tipList.get(position);
holder.textViewTip.setText(tipModel.getTip());
}
#Override
public int getItemCount() {
return tipList.size();
}
class TipViewHolder extends RecyclerView.ViewHolder {
TextView textViewTip;
public TipViewHolder(View view) {
super(view);
textViewTip = view.findViewById(R.id.textViewTip);
}
}
It happens because RecyclerView is expecting an adapter when dispatching layout on view created, so it is fine if there is no adapter when the view is created, it will just skip the layout part.
If you are worried about the error, then you could set an empty adapter when the view is created:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tips, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
tipList = new ArrayList<>();
recyclerView.setAdapter(new TipAdapter(getActivity(), tipList));
}
Then adjust your code in the response callback:
#Override
public void onResponse(String response) {
// Instead of setting adapter here...
// TipAdapter tipAdapter = new TipAdapter(getActivity(), tipList);
// recyclerView.setAdapter(tipAdapter);
// Just notify the adapter that tipList has changed.
recyclerView.getAdapter().notifyDataSetChanged();
// ...
}
TipList is the Adapter's datastore, it belongs to the Adapter and not to the Fragment
I have edited your code ( don't have access to Android Studio, doing it in Text Editor, please check for syntax errors )
Fragment
public class Tips extends Fragment {
Configuration config = new Configuration();
String HttpUrl = config.viewtips_url;
RecyclerView recyclerView;
TipAdapter tipAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Initialize the Tip Adapter
tipAdapter = new TipAdapter(getActivity());
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_tips, container, false);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// Assign the Adapter to recyclerView
recyclerView.setAdapter(tipAdapter);
return view;
}
private void loadTips() {
StringRequest stringRequest = new StringRequest(Request.Method.GET, HttpUrl,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
// Create a new TipList
List<TipModel> tipList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
tipList.add(new TipModel(
jsonObject.getInt("id"),
jsonObject.getString("tip")
));
}
tipAdapter.updateWith(tipList)
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(getActivity()).add(stringRequest);
}
TipAdapter
public class TipAdapter extends RecyclerView.Adapter<TipAdapter.TipViewHolder> {
private Context context;
private List<TipModel> tipList = new ArrayList<>();
public TipAdapter(Context context) {
this.context = context;
}
#Override
public TipViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.itemlayout, null);
return new TipViewHolder(view);
}
#Override
public void onBindViewHolder(TipViewHolder holder, int position) {
TipModel tipModel = tipList.get(position);
holder.textViewTip.setText(tipModel.getTip());
}
#Override
public int getItemCount() {
return tipList.size();
}
class TipViewHolder extends RecyclerView.ViewHolder {
TextView textViewTip;
public TipViewHolder(View view) {
super(view);
textViewTip = view.findViewById(R.id.textViewTip);
}
}
public updateWith(List<TipModel> tipList) {
this.tipList = tipList;
notifyDataSetChanged();
}
This is how I did it, when I had a similar problem while inflating recycler view in fragment. This code worked perfectly for me:
P.S. - This is the patch of code what I used in my application. I am sorry for any inconvenience.
First of all, in the onCreateView() of your Display Fragment:
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_home, container, false);
Firebase.setAndroidContext(getActivity());
((Home_Drawer) getActivity())
.setActionBarTitle("Home");
recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view_home_frag);
progressBar = (ProgressBar) root.findViewById(R.id.mainPageProgressBar);
// Log.i("inside", "rv initiated" +mLayoutManager.toString());
// Assign activity this to progress dialog.
progressDialog = new ProgressDialog(getActivity());
// Setting up message in Progress dialog.
progressDialog.setMessage("Loading Images From Firebase.");
// Showing progress dialog.
progressDialog.show();
// The path is already defined in MainActivity.
databaseReference = FirebaseDatabase.getInstance().getReference().child("productDisplay");
Log.i("inside", databaseReference.toString());
return root;
}
Then, we call onStart(). This is because recycler view generally does not inflate, ehile setting the adapter in onCreateView().
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerOptions<DisplayItemsModel> item_info =
new FirebaseRecyclerOptions.Builder<DisplayItemsModel>()
.setQuery(databaseReference, DisplayItemsModel.class)
.build();
final FirebaseRecyclerAdapter<DisplayItemsModel, ViewHolder> info_adapter =
new FirebaseRecyclerAdapter<DisplayItemsModel, ViewHolder>(item_info) {
#Override
protected void onBindViewHolder(final ViewHolder holder, final int position, final DisplayItemsModel model) {
mContext = getContext();
final DatabaseReference dref = getRef(position).getRef();
Log.i("dref", dref.toString());
// Adding Add Value Event Listener to databaseReference.
dref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot snapshot) {
holder.item_name_single_card.setText(snapshot.child("name").getValue().toString());
holder.price_single_card.setText(snapshot.child("price").getValue().toString());
String image_url = snapshot.child("image").getValue().toString();
Picasso.get().load(image_url).into(holder.thumbnail);
// Continue with your code.
This worked perfectly for me. Hope it solves your problem.
Related
I'm trying to add a load more.
I tried to apply what I'd search and it doesn't work.
here's my code.
LatestGradeFragment
public class LatestGradeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
List<ListGradeData> sectionList;
RecyclerView recyclerView;
SwipeRefreshLayout mSwipeRefreshLayout;
public static LatestGradeFragment newInstance() {
return new LatestGradeFragment();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_latest_grade, container, false);
//RecyclerView+CardView for section
recyclerView = (RecyclerView) rootView.findViewById(R.id.display_recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
sectionList = new ArrayList<>();
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshSection);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark);
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
// Fetching data from server
loadSection();
}
});
return rootView;
}
#Override
public void onRefresh() {
loadSection();
}
private void loadSection() {
mSwipeRefreshLayout.setRefreshing(true);
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.USER_GRADE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
//converting the string to json array object
JSONArray array = new JSONArray(response);
if(sectionList!=null) {
sectionList.clear();
}
//traversing through all the object
for (int i = 0; i < array.length(); i++) {
//getting product object from json array
JSONObject sections = array.getJSONObject(i);
//adding the product to product list
sectionList.add(new ListGradeData(
sections.getInt("id"),
sections.getString("section"),
sections.getString("level"),
sections.getString("schoolyear")
));
}
//creating adapter object and setting it to recyclerview
LatestGradeAdapter adapter = new LatestGradeAdapter(getActivity(), sectionList);
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
// Stopping swipe refresh
mSwipeRefreshLayout.setRefreshing(false);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Stopping swipe refresh
mSwipeRefreshLayout.setRefreshing(false);
}
});
//adding our stringrequest to queue
Volley.newRequestQueue(getActivity().getApplicationContext()).add(stringRequest);
}
#Override
public String toString() {
return "LatestGradeFragment";
}
}`
and here's my LatestGradeAdapter:
public class LatestGradeAdapter extends RecyclerView.Adapter<LatestGradeAdapter.RecyclerViewHolder> {
private Context mCtx;
private List<ListGradeData> sectionList;
`public LatestGradeAdapter(Context mCtx, List<ListGradeData> sectionList) {
this.mCtx = mCtx;
this.sectionList = sectionList;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.section_data_list, parent, false);
return new LatestGradeAdapter.RecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder holder, int position) {
final ListGradeData sections = sectionList.get(position);
//BIND DATA
holder.textViewSection.setText(sections.getSection());
holder.textViewLevel.setText(sections.getLevel());
holder.textViewSchoolYear.setText(sections.getSchoolyear());
}
#Override
public int getItemCount() {
return sectionList.size();
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
//Variables for list
TextView textViewSection, textViewLevel, textViewSchoolYear;
//Variables for head section
TextView textHeaderSection, textHeaderLevel, textHeaderSchoolYear;
public RecyclerViewHolder(final View itemView) {
super(itemView);
textViewSection = (TextView) itemView.findViewById(R.id.textSection);
textViewLevel = (TextView) itemView.findViewById(R.id.textLevel);
textViewSchoolYear = (TextView) itemView.findViewById(R.id.textYear);
}
}
}`
Add this code in your LatestGradeFragment.class
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();
if (lastVisiblePosition == recyclerView.getChildCount()) {
progrssBar.setVisibility(View.VISIBLE);
loadMore(); //This methos is used for load next set of items.
}
}
});
public void loadMore(){
//load next set of items to adapter
adapter.notifyDataSetChanged();
progrssBar.setVisibility(View.GONE);
}
Create your fragment_latest_grade like this:
<?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">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/progressBar" />
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:visibility="gone" />
</RelativeLayout>
I want to show information that call from API to recycler view in fragment, but the recycler view doesnt show the information. The Api show GET method and need to display the list in Recycler View.
This is my Model
public class PhoneModel {
public PhoneModel() {
}
private int amount;
private String amount_display;
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getAmount_display() {
return amount_display;
}
public void setAmount_display(String amount_display) {
this.amount_display = amount_display;
}
}
This is my Adapter. i just want to show one information only in Recycler View.
public class PhoneAdapter extends RecyclerView.Adapter<PhoneAdapter.PhoneViewHolder> {
private ArrayList<PhoneModel> listItems;
private Context context;
LayoutInflater inflater;
public PhoneAdapter(Context context) {
this.listItems = new ArrayList<>();
this.context = context;
inflater = LayoutInflater.from(context);
}
#Override
public PhoneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = inflater.from(parent.getContext())
.inflate(R.layout.view_holder_phone,parent,false);
return new PhoneViewHolder(v);
}
#Override
public void onBindViewHolder(PhoneViewHolder holder, int position) {
holder.test.setText(listItems.get(position).getAmount_display());
}
#Override
public int getItemCount() {
return listItems.size();
}
public void add(PhoneModel model) {
listItems.add(model);
notifyDataSetChanged();
}
public void clear() {
listItems.clear();
notifyDataSetChanged();
}
public class PhoneViewHolder extends RecyclerView.ViewHolder {
private TextView test;
private TextView currentBal;
public PhoneViewHolder(View itemView) {
super(itemView);
test = itemView.findViewById(R.id.tv_deposit);
currentBal = itemView.findViewById(R.id.tv_current_bal);
}
}
}
This is my Activity which i connect with Phone Model and Phone Adapter.
public class HistoryFragment extends Fragment {
private final static String TAG = HistoryFragment.class.getSimpleName();
private PhoneAdapter phoneAdapter;
private RecyclerView recyclerView;
public HistoryFragment() {
// 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_history, container, false);
recyclerView = view.findViewById(R.id.recycler_history);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(getActivity(),
LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLinearLayoutManager);
phoneAdapter = new PhoneAdapter(getContext());
recyclerView.setAdapter(phoneAdapter);
phoneHistory();
return view;
}
private void phoneHistory(){
StringRequest request = new StringRequest(
Request.Method.GET,
ServerApi.URL_PHONE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Gson gson = new GsonBuilder().create();
JSONObject jsonObject = null;
if(response != null) {
try {
jsonObject = new JSONObject(response);
PhoneModel phoneModel = gson.fromJson(jsonObject.getJSONObject("value").toString(), PhoneModel.class);
phoneAdapter.add(phoneModel);
} catch (JSONException e) {
Log.d(TAG, e.getLocalizedMessage());
}
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
return headers;
}
};
Volley.newRequestQueue(getContext()).add(request);
}
}
Try this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_history, container, false);
recyclerView = view.findViewById(R.id.recycler_history);
LinearLayoutManager mLinearLayoutManager = new
LinearLayoutManager(getActivity(),
LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLinearLayoutManager);
phoneHistory();
phoneAdapter = new PhoneAdapter(getContext());
recyclerView.setAdapter(phoneAdapter);
return view;
}
You getting empty data because in adapter constructor you creating new arraylist().
Change this:
public PhoneAdapter(Context context) {
this.listItems = new ArrayList<>();
this.context = context;
inflater = LayoutInflater.from(context);
}
To
public PhoneAdapter(Context context,Arraylist list) {
this.listItems = list;
this.context = context;
inflater = LayoutInflater.from(context);
}
also change in fragment:
phoneAdapter = new PhoneAdapter(getContext());
recyclerView.setAdapter(phoneAdapter,list);
and in phoneHistory() method
if(response != null) {
try {
jsonObject = new JSONObject(response);
PhoneModel phoneModel = gson.fromJson(jsonObject.getJSONObject("value").toString(), PhoneModel.class);
phoneModel .add(phoneModel);
list.add(phoneModel )
phoneAdapter.notifyDataSetChanged()
} catch (JSONException e) {
Log.d(TAG, e.getLocalizedMessage());
}
}
Hope it will help you!!
homepageThis is my fragment class
public class Premiums extends Fragment {
private RecyclerView recyclerPremium;
private RecyclerView.LayoutManager mLayoutManager;
private List<FeaturedAddDetails> featuredAddDetailsList = new ArrayList<>();
private List<PremiumDetails> premiumDetailslist = new ArrayList<>();
private NewestAdapter newestAdapter;
private PremiumAdapter premiumAdapter;
private String jsonResponse;
private PremiumDetails premiumDetails;
private JSONObject jsonobject;
public Premiums() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View mainView = inflater.inflate(R.layout.premium_fragment, container, false);
recyclerPremium = (RecyclerView) mainView.findViewById(R.id.recycler_premium);
premiumAdd();
premiumAdapter = new PremiumAdapter(getActivity().getApplicationContext(), premiumDetailslist);
recyclerPremium.setAdapter(premiumAdapter);
return mainView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerPremium.setLayoutManager(mLayoutManager);
recyclerPremium.setHasFixedSize(true);
}
private void premiumAdd() {
PremiumRequestHandler premiumHandler = new PremiumRequestHandler("premiumADD");
premiumHandler.executeAsStringRequest(new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("response", response);
JSONArray jsonarray = null;
try {
jsonarray = new JSONArray(response);
} catch (JSONException e) {
e.printStackTrace();
}
for (int i = 0; i < jsonarray.length(); i++) {
try {
jsonobject = jsonarray.getJSONObject(i);
Log.e("id", String.valueOf(jsonobject.getInt("id")));
premiumDetails = new PremiumDetails(jsonobject.getInt("id"),
jsonobject.getInt("userid"),
jsonobject.getInt("mobile"),
jsonobject.getInt("cityid"),
jsonobject.getInt("price"),
jsonobject.getInt("comments"),
jsonobject.getInt("created"),
jsonobject.getInt("categoryid"),
jsonobject.getInt("MainCategoryID"),
jsonobject.getInt("views"),
jsonobject.getInt("ImageCount"),
jsonobject.getInt("storeid"),
jsonobject.getString("title"),
jsonobject.getString("default_photo"),
jsonobject.getString("CityName"),
jsonobject.getString("CategoryName"),
jsonobject.getString("currency"),
jsonobject.getString("description"));
premiumDetailslist.add(premiumDetails);
premiumAdapter.setPremiumDetails(premiumDetailslist);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new BaseRequest.ErrorResponseCallback() {
#Override
public void onError(Exception exception) {
}
});
}
This is my adapter class
public class PremiumAdapter extends RecyclerView.Adapter<PremiumAdapter.MyViewHolderPremium> {
private List<PremiumDetails> premiumDetailsList;
private ImageLoader imageLoader;
private Context context;
public PremiumAdapter(Context context, List<PremiumDetails> premiumDetailsList) {
this.premiumDetailsList = premiumDetailsList;
this.context = context;
notifyDataSetChanged();
}
public void setPremiumDetails(List<PremiumDetails> premiumDetailsList) {
this.premiumDetailsList = premiumDetailsList;
notifyDataSetChanged();
}
public class MyViewHolderPremium extends RecyclerView.ViewHolder {
private TextView txtTitle,txtDescription,txtCityName,txtPrice,txtCategory,txtHour,txtPhotoNo;
private NetworkImageView imgPhoto;
public MyViewHolderPremium(View itemView) {
super(itemView);
txtTitle = (TextView)itemView.findViewById(R.id.txt_title_fad);
txtDescription = (TextView)itemView.findViewById(R.id.description_fad);
txtCityName = (TextView)itemView.findViewById(R.id.city_name_fad);
txtPrice = (TextView)itemView.findViewById(R.id.price_fad);
txtCategory = (TextView)itemView.findViewById(R.id.category_fad);
txtHour = (TextView)itemView.findViewById(R.id.hours_fad);
txtPhotoNo = (TextView)itemView.findViewById(R.id.txt_photo_no_fad);
imgPhoto=(NetworkImageView)itemView.findViewById(R.id.img_photo_lod_fad);
}
}
#Override
public MyViewHolderPremium onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.featured_ad_adapter_layout,parent,false);
final MyViewHolderPremium myViewHolderPremium = new MyViewHolderPremium(itemView);
return myViewHolderPremium;
}
#Override
public void onBindViewHolder(MyViewHolderPremium holder, int position) {
PremiumDetails premiumDetails = premiumDetailsList.get(position);
holder.txtTitle.setText(premiumDetails.getTitle());
holder.txtDescription.setText(premiumDetails.getDescription());
holder.txtCityName.setText(premiumDetails.getCityName());
holder.txtPrice.setText(Integer.toString(premiumDetails.getPrice()));
holder.txtCategory.setText(premiumDetails.getCategoryName());
holder.txtHour.setText(Integer.toString(premiumDetails.getCreated()));
holder.txtPhotoNo.setText(Integer.toString(premiumDetails.getImageCount())+" photos " );
try {
imageLoader= VolleyHandler.getImageLoader();
} catch (Exception e) {
e.printStackTrace();
}
//imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
//imageLoader.get(featuredAddDetails.getDefault_photo(), ImageLoader.getImageListener(holder.imgPhoto, R.mipmap.ic_launcher, android.R.drawable.ic_dialog_alert));
holder.imgPhoto.setImageUrl(premiumDetails.getDefault_photo(),imageLoader);
}
#Override
public int getItemCount() {
Log.e("size", String.valueOf(premiumDetailsList.size()));
return premiumDetailsList.size();
}}
I am getting error on showing values but I got values from json and I can't add it to adapter and model class, plz help me I look stackoverflow whole day but I can't find my issue
my getItemCount() is showing as 0"
You are setting the adapter and then you are calling premiumAdd() method.First call that method and then set the adapter.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View mainView = inflater.inflate(R.layout.premium_fragment, container, false);
recyclerPremium = (RecyclerView) mainView.findViewById(R.id.recycler_premium);
premiumAdd();
premiumAdapter = new PremiumAdapter(getActivity().getApplicationContext(), premiumDetailslist);
recyclerPremium.setAdapter(premiumAdapter);
return mainView;
Try notifyDataSetChanged() after setting data in the Constructor of your Adapter
[EDIT] Whenever your data changes, you need to inform your Adapter about it also, then call notifyDataSetChanged() on it.
You are probably setting empty data into the Adapter, your List changes, but the Adapter does not know about it.
[Update]
In addition to your Adapter constructor, add a setData(List) to your adapter to change your dataset at runtime.
public void setPremiumDetails(List<PremiumDetails> premiumDetailsList) {
this.premiumDetailsList = premiumDetailsList;
notifyDataSetChanged();
}
When your request in premiumAdd() returns, and you receive a new set of data, you call setPremiumDetails on your Adapter with the new data and the List will update.
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View mainView = inflater.inflate(R.layout.premium_fragment, container, false);
recyclerPremium = (RecyclerView) mainView.findViewById(R.id.recycler_premium);
mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerPremium.setLayoutManager(mLayoutManager);
recyclerPremium.setHasFixedSize(true);
premiumAdd();
premiumAdapter = new PremiumAdapter(getActivity().getApplicationContext(), premiumDetailslist);
recyclerPremium.setAdapter(premiumAdapter);
return mainView;
}
and remove premiumAdapter.notifyDataSetChanged();
added adapter code:
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.ViewHolder> {
ArrayList<Model> dataset;
public RVAdapter(ArrayList<Model> dataset) {
this.dataset = dataset;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Model model = dataset.get(position);
holder.name.setText(model.name) ;
holder.status.setText(model.status);
if (model.status.equalsIgnoreCase("good"))
holder.ivStatus.setImageResource(R.drawable.ic_tick_48);
else
holder.ivStatus.setImageResource(R.drawable.ic_delete_48);
}
#Override
public int getItemCount() {
Log.e("TAG","SIZE: "+dataset.size());
return dataset.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView status;
ImageView ivStatus;
RelativeLayout parent;
public ViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.rv_item_name);
status = (TextView) itemView.findViewById(R.id.rv_item_status);
ivStatus = (ImageView) itemView.findViewById(R.id.rv_item_iv);
parent = (RelativeLayout) itemView.findViewById(R.id.rv_item_parent);
}
}
}
your notifiy adapter on every single add
for (...){
....
premiumDetailslist.add(premiumDetails);
premiumAdapter.notifyDataSetChanged();// called every time wrong
}
also provide what exact error log says
and move the notifyDataSetChanged() after the for not in the loop
if no data is showing try recyclerview.invalidate , but i wont particularly do that way, would try debugging, log every step, inspect with method in the expected sequence isnt working
please any one explain RecyclerView in fragment using volley to get json data.
Already i refered below link coding Google recyclerview in fragment
this is my first project in android, so i cannot understand that coding.
Please any one help me.
My fragmnet Coding:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View drawer = inflater.inflate(R.layout.fragment_progress, container, false);
orderLists = new ArrayList<>();
getProgressData();
recyclerView = (RecyclerView) drawer.findViewById(R.id.progress);
adapter = new ProgressOrderListAdapter(orderLists, this);
adapter.clearAdaptor();
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
private void getProgressData(){
String mobilecustomertoken = SharedPreferencesManager.readPreferenceString("MobileCustomerToken", "D/N");
JSONObject progressData = new JSONObject();
try{
progressData.put("mobilecustomertoken", mobilecustomertoken);
JsonObjectRequest progressObject = new JsonObjectRequest(1, Common.OrderDetails + "progress", progressData, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject progressResponse) {
Log.d("Responseprogress", progressResponse.toString());
try {
int status = progressResponse.getInt("status");
if(status == 1) {
progressOrderProgress(progressResponse);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.d("Response", "PROGRESS ERROR");
}
});
progressObject.setShouldCache(false);
ServiceBellApp.getInstance().addToRequestQueue(progressObject);
}
catch (JSONException localJSONException){
localJSONException.printStackTrace();
return;
}
}
private void progressOrderProgress(JSONObject progressResponse) throws JSONException {
JSONArray result = progressResponse.getJSONArray("orderdata");
OrderList orderListModule = new OrderList();
for(int i=0; i<result.length(); i++){
JSONObject orderData = result.getJSONObject(i);
orderListModule.setPackage_name(orderData.getString("package_name"));
orderListModule.setOrderdate(orderData.getString("orderdate"));
orderListModule.setServicedate(orderData.getString("servicedate"));
orderListModule.setServicetime(orderData.getString("servicetime"));
orderListModule.setOrderid(orderData.getString("orderid"));
orderListModule.setOrdstatus(orderData.getString("ordstatus"));
orderListModule.setOrderamount(orderData.getInt("orderamount"));
}
orderLists.add(orderListModule);
}
My adapter code:
public class OrderListAdapter extends RecyclerView.Adapter<OrderListAdapter.ViewHolder> {
List<OrderList> List;
private FragmentPending mContext;
public OrderListAdapter(List<OrderList> List, FragmentPending context) {
this.mContext = context;
this.List = List;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.order_list_view, null);
ViewHolder holder = new ViewHolder(view);
// this is where the each item is inflated.
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
OrderList orderListsPos = List.get(position);
// this is where the data for each item is assigned
holder.textViewPackageName.setText(orderListsPos.getPackage_name());
holder.textOrderdate.setText(orderListsPos.getOrderdate());
holder.textServicedate.setText(orderListsPos.getServicedate());
holder.textServicetime.setText(orderListsPos.getServicetime());
holder.textOrderid.setText(orderListsPos.getOrderid());
holder.textOrderamount.setText("Rs." + orderListsPos.getOrderamount());
holder.textStatus.setText(orderListsPos.getOrdstatus());
}
#Override
public int getItemCount() {
return List.size();
}
public void clearAdaptor() {
List.clear();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView textViewPackageName;
public TextView textServicedate;
public TextView textServicetime;
public TextView textOrderdate;
public TextView textOrderid;
public TextView textOrderamount;
public TextView textStatus;
public ViewHolder(View itemView) {
super(itemView);
textViewPackageName = (TextView) itemView.findViewById(R.id.productName);
textOrderdate = (TextView) itemView.findViewById(R.id.orderdate);
textOrderid = (TextView) itemView.findViewById(R.id.orderno);
textOrderamount = (TextView) itemView.findViewById(R.id.orderprice);
textStatus = (TextView) itemView.findViewById(R.id.orderstatus);
}
}}
First you need four things
1 ) layout that holds the each recycler view layout item
2 ) A view holder for creating each layout
3 ) A Model Class to holds the data
4 ) Recycler Adaptor which deals with the data for the Each Layout item
FIrst create a layout item
for eample lets create a single view with only TextView in it
XML
each_item.xml
<TextView
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:gravity="start|center_vertical"
android:textColor="#color/white"
android:textSize="18sp" />
and lets now create a view holder
i will post both code for the view holder and RecyclerAdaptor
public class Adaptor extends RecyclerView.Adapter<Adaptor.ViewHolder> {
List<Model> List = Collections.emptyList();
private Context mContext;
private LayoutInflater inflater;
public Adaptor(Context context, List<Model> List) {
inflater = LayoutInflater.from(context);
this.mContext = context;
this.List = List;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.each_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
// this is where the each item is inflated.
return holder;
}
#Override
public void onBindViewHolder(WinnersViewHolder holder, int position) {
Model mModel = List.get(position);
// this is where the data for each item is assigned
holder.nameView.setText("" + mModel.getName());
}
#Override
public int getItemCount() {
return List.size();
}
public void clearAdaptor() {
List.clear();
}
public class ViewHolder extends RecyclerView.ViewHolder {
protected TextView nameView;
public ViewHolder(View itemView) {
super(itemView);
this.nameView = (TextView) itemView.findViewById(R.id.name);
}
}
}
Now the model class
public class Model {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
}
Now the back end is done, Lets implement it on the Fragment
List<Model> List = new ArrayList<>();
private RecyclerView mRecyclerView;
private Adaptor adaptor;
public Fragment() {
// constructor of fragment
// Required empty public constructor
}
in the onCreatView() get the id of recyclerView
View fragmentView = inflater.inflate(R.layout.fragment_layout, container, false);
mRecyclerView = (RecyclerView) fragmentView .findViewById(R.id.recycler_view);
and then pass the data to the Adaptor by creating its object
adaptor = new Adaptor(getContext(), List);
adaptor.clearAdaptor();
mRecyclerView.setAdapter(adaptor);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
You are done now, only thing pending is if you are accessing data form server call notifyDataSetChanged() or adaptor = new Adaptor(getContext(), getList()); where the getList() returns the Model data and do not call adaptor.clearAdaptor() .
hope this helps ..
EDIT
you can two ways infalte the each layout item .. one is above and second is in onCreateViewHolder
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.each_item, null);
Check this link It is really helpful for beginners for understanding concepts from start to mastering the RecyclerView.
https://github.com/codepath/android_guides/wiki/Using-the-RecyclerView
Hope this helps you to understand recycler view concepts.
RecycerView + Fragment + Volley
Fragment Code:
public class DogListFragment extends Fragment{
private RecyclerView rv;
private StaggeredGridLayoutManager llm;
private DogListAdapter adapter;
private ArrayList<DogModel> dogList;
private Context context;
public static DogListFragment getInstance(){
return new DogListFragment();
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
dogList = new ArrayList<>();
adapter = new DogListAdapter(context, dogList, this);
getListFromServer();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_dog_list, parent, false);
rv = view.findViewById(R.id.rv);
llm = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(llm);
rv.setAdapter(adapter);
return view;
}
public void getListFromServer(){
String url = "https://dog.ceo/api/breed/hound/images/random/20";
RequestQueue requestQueue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("message");
for(int i=0;i<array.length();i++){
String imageUrl = array.getString(i);
dogList.add(new DogModel(imageUrl));
}
adapter.updateDataSet(dogList);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
requestQueue.add(request);
}
}
Full code
Woof Repository
It has the following implementations
Fragment communication via interface
Reusing fragment by
getSupportFragmentManager().findFragmentByTag(TAG)
Which lifecycle method should have API call so that it is called just
once
How to save RecylcerView state in Fragment (Scroll position + content)
Pagination in RecyclerView
Rest Calls (Volley)
Image Rendering (Glide)
JSON Parsing
I have an adapter which won't get notified after fetching new data by Retrofit however, I'm using notifyDataSetChanged and get success in the logs but nothing works either :(
Also I tried to use local array with this adapter and it works great.
public class alberrClassNews extends Fragment {
private RecyclerView recyclerView;
private List<alberrNewsListContent> alberrNews = new ArrayList<alberrNewsListContent>();
private final String TAG = "Get JSONArray";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.alberrnewsclass, container, false);
getActivity().setTitle("nnnn");
recyclerView = (RecyclerView) view.findViewById(R.id.alberrNewsList);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
final alberrNewsAdapter aNA = new alberrNewsAdapter(getActivity(), alberrNews);
recyclerView.setAdapter(aNA);
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("loading");
progressDialog.show();
final Retrofit alberrRetrofit = new Retrofit.Builder()
.baseUrl("http://nn.com/abbn/")
.addConverterFactory(GsonConverterFactory.create()).build();
alberrService service = alberrRetrofit.create(alberrService.class);
Call<JSONArray> call = service.alberrNews();
call.enqueue(new Callback<JSONArray>() {
#Override
public void onResponse(Call<JSONArray> call, Response<JSONArray> response) {
progressDialog.dismiss();
Log.i(TAG, "success");
try{
JSONArray jsonArray = response.body().getJSONArray(0);
for (int i = 0 ; i < jsonArray.length() ; i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
alberrNewsListContent newsContent = new alberrNewsListContent();
newsContent.setAlberrNewsTitle(jsonObject.getString("title"));
newsContent.setAlberrNewsSubject(jsonObject.getString("subject"));
newsContent.setAlberrNewsImage(jsonObject.getString("image"));
alberrNews.add(newsContent);
}
} catch (JSONException e){
e.printStackTrace();
}
aNA.notifyDataSetChanged();
}
#Override
public void onFailure(Call<JSONArray> call, Throwable t) {
Log.i(TAG, "Failed");
progressDialog.dismiss();
Toast.makeText(getActivity().getApplicationContext(),
"no connection", Toast.LENGTH_SHORT).show();
}
});
return view;
}
Adapter Class
public class alberrNewsAdapter extends RecyclerView.Adapter<alberrNewsAdapter.ViewHolder> {
private List<alberrNewsListContent> newsListContent;
private Context context;
public alberrNewsAdapter(Context ncontext , List<alberrNewsListContent> nnewsListContent ){
this.context = ncontext;
this.newsListContent = nnewsListContent;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.alberrnewscontent, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(alberrNewsAdapter.ViewHolder holder, int position) {
final alberrNewsListContent newsContent = newsListContent.get(position);
holder.alberrNewsTitle.setText(newsContent.getAlberrNewsTitle());
holder.alberrNewsSubject.setText(newsContent.getAlberrNewsSubject());
Glide.with(context)
.load(newsContent.getAlberrNewsImage())
.override(300, 260)
.into(holder.alberrNewsImage);
}
#Override
public int getItemCount() {
return newsListContent.size();
}
public void replaceDataSet(List<alberrNewsListContent> alberrNews){
this.newsListContent = alberrNews;
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView alberrNewsTitle;
TextView alberrNewsSubject;
ImageView alberrNewsImage;
CardView alberrNewsCardView;
public ViewHolder(View itemView) {
super(itemView);
alberrNewsTitle = (TextView)itemView.findViewById(R.id.alberrNewsTitle);
alberrNewsSubject = (TextView)itemView.findViewById(R.id.alberrNewsSubject);
alberrNewsImage = (ImageView)itemView.findViewById(R.id.alberrNewsImage);
alberrNewsCardView = (CardView)itemView.findViewById(R.id.alberrNewsCardView);
}
}
}
In your alberrNewsAdapter, you can create a new method called replaceDataSet() which will replace your dataset in the adapter and call notifyDataSetChanged().
private List<alberrNewsListContent> alberrNews alberrNews;
public void replaceDataSet(List<alberrNewsListContent> alberrNews){
this.alberrNews = alberrNews;
notifyDataSetChanged();
}
And in onResponse() instead of calling aNA.notifyDataSetChanged(); call aNA.replaceDataSet();
Pass new list content to the adapter via public method and call notifyDataSetChanged(); inside that method. Currently, you're not updating the list inside the adapter.