I have a RecycleView to which I give an Array of Post objects. When it's loaded first time, everything works fine but trying to replace the data or just entering in the Fragment again then the RecycleView does not show anything. Also I have checked the size of the new data and it's different from zero. Here is my code:
// Init the list
list = (RecyclerView) view.findViewById(R.id.list);
list.setLayoutManager(new LinearLayoutManager(mContext));
...
if (adapter != null) {
adapter.replaceCurrentPosts(new ArrayList<>(postList));
}
else {
adapter = new PostAdapter(mContext, new ArrayList<>(postList), this);
list.setAdapter(adapter);
}
...
public PostAdapter(Context context, List<Post> posts, onPostElementClickListener listener) {
this.context = context;
this.posts = posts;
this.mListener = listener;
}
public void replaceCurrentPosts(List<Post> newPosts) {
this.posts.clear();
this.posts.addAll(newPosts);
this.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return posts.size();
}
package com.example.jiteshmohite.myapplication;
public class PostAdapter extends RecyclerView.Adapter {
private Context context;
private List<Post> posts;
private onPostElementClickListener mListener;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.info_text);
}
}
public PostAdapter(Context context, List<Post> posts, onPostElementClickListener listener) {
this.context = context;
this.posts = posts;
this.mListener = listener;
}
public void replaceCurrentPosts(List<Post> newPosts) {
posts.clear();
posts = newPosts;
this.notifyDataSetChanged();
}
#Override
public PostAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(PostAdapter.ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(posts.get(position).getName());
holder.mTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.onClick(position);
}
});
}
#Override
public int getItemCount() {
return posts.size();
}
interface onPostElementClickListener {
public void onClick(int pos);
}
}
private RecyclerView list;
private PostAdapter postAdapter;
private RecyclerView.LayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_example);
list = (RecyclerView) findViewById(R.id.list);
layoutManager = new LinearLayoutManager(getApplicationContext());
list.setLayoutManager(layoutManager);
postAdapter = new PostAdapter(getApplicationContext(), getPostData(), listener);
list.setAdapter(postAdapter);
}
private PostAdapter.onPostElementClickListener listener = new PostAdapter.onPostElementClickListener() {
#Override
public void onClick(int pos) {
Toast.makeText(getApplicationContext(), pos + "" , Toast.LENGTH_SHORT).show();
List<Post> posts = getPostData();
posts.get(pos).setName("abc");
postAdapter.replaceCurrentPosts(posts);
}
};
// get post list which contains name
public List<Post> getPostData() {
Post post = new Post();
post.setName("xyz");
List<Post> posts = new ArrayList<Post>();
posts.add(post);
posts.add(post);
posts.add(post);
posts.add(post);
posts.add(post);
return posts;
}
}
I suggesting rather then notifyDataSetChanged() you should refer notifyItemChange which modify specific positions.
please let me know if it is not work for you.
why don't you try to add one element (or maybe more) instead of remove all and re-add all items?
Related
I am stuck need your kind help, i have an activity in android user sign up, and apart from general information i have a list of existing users/entities shown in recyclerview and each item of recyclerview list contains a follow button, i want to captures the position/ buttons that were clicked to check which users/entities the new user has followed. Any suggest how to do it?
I had customer adapter and recycler view, Check the attached image for clarity. I want to create an array list that will contain ids of each list item whose button is clicked.
RecyclerView containing list item and follow button
//this adapter use on admin
public class FollowLocalBusinessAdapter extends RecyclerView.Adapter {
AlertDialog.Builder alertDialogBuilder;
private Context context;
private List<FollowLocalBusinessMC> list;
private LayoutInflater layoutInflater;
private DatabaseReference mDatabase;//database reference
private FollowLocalBusinessMC localBusinessMC;
private ListAdapterListener mListener;
public FollowLocalBusinessAdapter(Context context, List<FollowLocalBusinessMC> list) {
this.context = context;
this.list = list;
layoutInflater = LayoutInflater.from(context);
alertDialogBuilder = new AlertDialog.Builder(context);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int position) {
View view = layoutInflater.inflate(R.layout.list_item_local_business, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(final FollowLocalBusinessAdapter.MyViewHolder holder, final int position)//is called
{
localBusinessMC = list.get(position);
if (holder != null) {
if (holder.followBtn.getText().equals("Follow")) {
holder.followBtn.setBackgroundResource(R.drawable.follow_btn_bg);
holder.followBtn.setTextColor(context.getResources().getColor(R.color.colorBlueButton));
} else {
holder.followBtn.setBackgroundResource(R.drawable.following_btn_bg);
holder.followBtn.setTextColor(context.getResources().getColor(R.color.colorWhite));
}
holder.mainHeading.setText(localBusinessMC.getMainHeading());
holder.subHeading.setText(localBusinessMC.getSubHeading());
Glide.with(context).load(localBusinessMC.getIcon()).into(holder.icon);
holder.followBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "" + list.get(position).getId(), Toast.LENGTH_SHORT).show();
if (holder.followBtn.getText().equals("Follow")) {
holder.followBtn.setText("Following");
holder.followBtn.setTextColor(context.getResources().getColor(R.color.colorWhite));
holder.followBtn.setBackgroundResource(R.drawable.following_btn_bg);
} else {
holder.followBtn.setText("Follow");
holder.followBtn.setBackgroundResource(R.drawable.follow_btn_bg);
holder.followBtn.setTextColor(context.getResources().getColor(R.color.colorBlueButton));
}
}
});
}
}
#Override
public int getItemCount() {
return list.size();
}
public interface ListAdapterListener { // create an interface
void onClickAtOKButton(int position); // create callback function
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView mainHeading, subHeading;
ImageView icon;
Button followBtn;
MyViewHolder(View v) {
super(v);
mainHeading = v.findViewById(R.id.main_lbsr_id);
subHeading = v.findViewById(R.id.sub_lbsr_id);
icon = v.findViewById(R.id.icon_lbsr_id);
followBtn = v.findViewById(R.id.followBtn_lbsr_id);
}
}
}
create an interface in your Adapter with one method :
public interface CallBack{
void onItemClicked(int position , /*anyThing else*/);
}
then get an instance of interface in your Adapter :
private YourAdapter.CallBack;
in your Adpater constructor get object of CallBack :
public YourAdapter(Context context, List</* */> list, YourAdapter.CallBackcallback callBack) {
this.context = context;
this.list= list;
this.callback = callback;
}
#Override
public void onBindViewHolder(#NonNull ChoosenExerciseViewHolder holder, final int position) {
holder.View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onItemClicked(
//pass any parameter youe defined
//for ex : position , ///);
}
});
}
then in your Activity/Fragment :
private YourAdapter.CallBack callback= (position, /* */ ) -> {
// do what you want
};
YourAdapter adapter = new YourAdapter(getContext(), calback, list);
receyclerview.setAdapter(adapter )
The RecyclerView shows only items that was in ArrayList (data of the adapter) on creation. All my attempts to add more lines seems to work, but the list stays with initial data.
It isn't duplicate, as I tried all the suggestions found on google.
What I already did:
adapter.notifyDataSetChanged();
adapter.notifyItemChanged(5);
recycleList.invalidate();
recycleList.setAdapter(adapter);
running the update on UIThread with Handler
The adapter work as it should - onCreateView do it's work (creat new lines) as well as onBindView (bind new data). getItemCount() returns correct value (larger after update). Everything looks like it should be - instead of the final view - does not change.
The only thing that will work is recreate the adapter from scratch with new dataset - completely unacceptable by design (ugly on long lists).
Here is the code:
Create in fragment:
adapter = new MyListAdapter(getContext());
adapter.addItems(initialItems); // These and only these I see on the list
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);
Trying to update from fragment:
public void onUpdateReady(ArrayList<Model> freshData) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() { // UI thread
adapter.addItems(freshData);
adapter.notifyDataSetChanged();
adapter.notifyItemChanged(5);
recycleList.invalidate();
//notifyItemRangeInserted(3,freshData.size());
}
});
}
Adapter:
private Context mContext;
private ArrayList<Model> data;
public MyListAdapter(Context mContext) {
this.mContext = mContext;
data=new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.textName.setText(data.get(position).getName());
}
#Override
public int getItemCount() {
return data.size();
}
public void addItems(Collection<Model> list) {
data.addAll(list);
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.textName) TextView textName;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
}
UPDATE: Changed according to comments:
public void addItems(Collection<Model> list) {
ArrayList<Model> newData=new ArrayList<>(); // Make new array
newData.addAll(data); // Take old
newData.addAll(list); // Add new
data=newData; // change to data to newly created array
notifyDataSetChanged();
}
try this
In Fragment
ArrayList<Data> items=new ArrayList<>();
items.addAll(initialItems);
adapter = new MyListAdapter(getContext(),items);
LinearLayoutManager mLayoutManager=new LinearLayoutManager(getContext());
recycleList.setLayoutManager(mLayoutManager);
recycleList.setAdapter(adapter);
public void onUpdateReady(ArrayList<Model> freshData) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() { // UI thread
items.addAll(freshData);
adapter.notifyDataSetChanged();
followList.invalidate();
}
});
}
private Context mContext;
private ArrayList<Model> data;
public MyListAdapter(Context mContext,ArrayList<Model> data) {
this.mContext = mContext;
this.data=data;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.textName.setText(data.get(position).getName());
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.textName) TextView textName;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
}
Change your Adapter constructor:
private ArrayList<Model> data;
public MyListAdapter(Context mContext,ArrayList<Model> data) {
this.mContext = mContext;
this.data = data;}
public void addItems(Collection<Model> list) {
data.addAll(list);
}
fragment:
adapter = new MyListAdapter(getContext(),initialItems);
I had a similar problem once and calling invalidateViews on the ListView worked, even if it was a hack. Instead of recycleList.invalidate(); try recycleList.invalidateViews();
I ran into situation where the RecyclerView with GridLayoutManager is not working on onClick(). Like ListView, when I tap/click on a picture in a GridView, the onClick is not returning the single item details. When I click on a poster of a movie, it should only display the details about the particular movie, but instead it is displaying multiple movies details in a scroll view.
Look at the code below:
public class MoviesGridAdapter extends RecyclerView.Adapter<MoviesGridAdapter.PosterViewHolder> {
private Context context;
private List<Movies> movieItems = new ArrayList<>();
CustomItemClickListener listener;
public MoviesGridAdapter(Context context, List<Movies> movieItems) {
this.context = context;
this.movieItems = movieItems;
}
#Override
public PosterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movies_grid_view_item, parent, false);
final MoviesGridAdapter.PosterViewHolder vh = new MoviesGridAdapter.PosterViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Context zContext = context;
Intent intent = new Intent(zContext, MoviesDetailActivity.class);
Movies movies = movieItems.get(vh.getAdapterPosition());
intent.putExtra("Items Selection", movies.getPosterPath());
intent.putExtra("Items Selection 1", movies.getTitle());
intent.putExtra("Items Selection 2", movies.getReleaseDate());
intent.putExtra("Items Selection 3", movies.getVoteAverage());
intent.putExtra("Items Selection 4", movies.getOverview());
zContext.startActivity(intent);
}
});
return vh;
}
public void setMoviesData(List<Movies> moviesData) {
movieItems = moviesData;
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(PosterViewHolder holder, final int position) {
Context mcontext = context;
Movies movies = movieItems.get(position);
String posterUrlPath = movies.getPosterPath();
Picasso.with(mcontext)
.load(Constants.MOVIES_POSTER_URL + posterUrlPath)
.into(holder.poster);
}
#Override
public int getItemCount() {
return movieItems.size();
}
public class PosterViewHolder extends RecyclerView.ViewHolder {
ImageView poster;
public PosterViewHolder(final View itemView) {
super(itemView);
poster = (ImageView) itemView.findViewById(R.id.movies_image_view_retrofit);
}
}
}
And following is the Fragment:
public class MoviesFragment extends Fragment {
private static final int COLUMN_COUNT = 2;
private List<Movies> movieItems = new ArrayList<>();
private RecyclerView recyclerView;
private MoviesGridAdapter adapter;
private Subscription subscription;
public MoviesFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.movies_fragment_content, container, false);
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), COLUMN_COUNT);
recyclerView = (RecyclerView) view.findViewById(R.id.movies_recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
adapter = new MoviesGridAdapter(getActivity(), movieItems);
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onStart() {
super.onStart();
if (movieItems != null) {
adapter.setMoviesData(movieItems);
}
loadDate();
}
private void loadDate() {
MoviesAPI api = RetrofitManager.getMoviesClient().create(MoviesAPI.class);
subscription = api.getPopularMovies(APIKeys.MOVIES_DB_API_KEY)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(
new Action1<MoviesResponse>() {
#Override
public void call(MoviesResponse response) {
movieItems = response.getMovies();
adapter.setMoviesData(response.getMovies());
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
}
}
);
}
}
Thank you guys for the attention. The solution I am looking is: when I click a picture from the grid view, I need the details about the particular movie like title, overview, releaseDate etc.
Make your model parcelable or send your model fields one by one but using a different keyword. You're adding same keyword with different values in here:
intent.putExtra("Items Selection", movies.getPosterPath());
intent.putExtra("Items Selection", movies.getTitle());
intent.putExtra("Items Selection", movies.getReleaseDate());
intent.putExtra("Items Selection", movies.getVoteAverage());
intent.putExtra("Items Selection", movies.getOverview());
Here's a tutorial link how you can make your model parcelable. And after that you can update your adapter as following:
public class MoviesGridAdapter extends RecyclerView.Adapter<MoviesGridAdapter.PosterViewHolder> {
private Context context;
private List<Movies> movieItems = new ArrayList<>();
CustomItemClickListener listener;
public MoviesGridAdapter(Context context, List<Movies> movieItems) {
this.context = context;
this.movieItems = movieItems;
}
#Override
public PosterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movies_grid_view_item, parent, false);
return new PosterViewHolder(view);
}
public void setMoviesData(List<Movies> moviesData) {
movieItems = moviesData;
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(PosterViewHolder holder, final int position) {
Movies movie = movieItems.get(position);
String posterUrlPath = movie.getPosterPath();
Picasso.with(mcontext)
.load(Constants.MOVIES_POSTER_URL + posterUrlPath)
.into(holder.poster);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, MoviesDetailActivity.class);
intent.putExtra("movie", movie)
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return movieItems.size();
}
public class PosterViewHolder extends RecyclerView.ViewHolder {
ImageView poster;
public PosterViewHolder(View itemView) {
super(itemView);
poster = (ImageView) itemView.findViewById(R.id.movies_image_view_retrofit);
}
}
}
Don't set your click listener in onCreateViewHolder. Instead set your listener in onBindViewHolder method
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 create a RecyclerView list that shows a default layout. I then add a new item to the list and the layout updates to show the new item (a CardView). I then navigate back to a previous activity. When I return to the RecyclerView activity I am returned to the generic, default list and my new CardView item does not show.
I have the normal onCreate(Bundle savedInstanceState) code in the Activity. It seems like the adapter just creates a new RecyclerView list upon returning to it rather than returning to the previously created list. What am I missing here?
Activity:
public class ListContactsActivity extends AppCompatActivity {
private ListContactsAdapter mContactsAdapter;
private RecyclerView mRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerviewlist);
final List<Contact> mContacts;
mContacts = new ArrayList<>();
mRecyclerView = (RecyclerView) findViewById(R.id.cardList);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mContactsAdapter = new ListContactsAdapter(this, mContacts);
mContactsAdapter.setOnItemTapListener(new ListContactsAdapter.OnItemTapListener() {
#Override
public void onItemTap(Contact contact, int position) {
mContactsAdapter.removeItem(contact, position);
}
});
mRecyclerView.setAdapter(mContactsAdapter);
...
Adapter:
public class ListContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class EmptyViewHolder extends RecyclerView.ViewHolder {
public EmptyViewHolder(View itemView) {
super(itemView);
}
}
private class ContactViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView cardBlankText2;
public ContactViewHolder(View itemView) {
super(itemView);
cardBlankText2 = (TextView) itemView.findViewById(R.id.cardBlankText2);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mOnItemTapListener != null) {
Contact contact = mContacts.get(getLayoutPosition());
mOnItemTapListener.onItemTap(contact, getLayoutPosition());
}
}
}
private Context mContext;
private LayoutInflater mLayoutInflater;
private List<Contact> mContacts;
private List<ListItem> mItems;
private OnItemTapListener mOnItemTapListener;
public ListContactsAdapter(Context context, List<Contact> contacts) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContacts = contacts;
mItems = buildItemsList();
}
public void setOnItemTapListener(OnItemTapListener listener) {
mOnItemTapListener = listener;
}
private List<ListItem> buildItemsList() {
List<ListItem> items = new ArrayList<>();
if (mContacts.size() > 0) {
for (Contact contact : mContacts) {
items.add(new ContactItem(contact));
}
} else {
// when R. list is first created or when the number of cards
// is deleted until there are zero, show the defaultcard_layout
// and "Click the + above to get started".
for (int i=0; i<1; i++) {
items.add(new EmptyItem());
}
}
return items;
}
public void addItem(Contact contact) {
if (mContacts.size()==0) {
// if list is empty
// remove empty cards first
mItems.clear();
notifyDataSetChanged();
}
// add item on the top of the list and scroll to the top position
mContacts.add(contact);
mItems.add(new ContactItem(contact));
notifyItemInserted(0);
}
public void removeItem(Contact contact, int position) {
mContacts.remove(contact);
if (mContacts.size()==0) {
// if no more contacts in list,
// rebuild from scratch
mItems.clear();
mItems.addAll(buildItemsList());
notifyDataSetChanged();
} else {
// else remove one item
mItems.remove(position);
notifyItemRemoved(position);
}
}
#Override
public int getItemCount() {
return mItems.size();
}
#Override
public int getItemViewType(int position) {
return mItems.get(position).getType();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ListItem.EMPTY_TYPE) {
View itemView = mLayoutInflater.inflate(R.layout.defaultcard_layout, parent, false);
return new EmptyViewHolder(itemView);
} else {
View itemView = mLayoutInflater.inflate(R.layout.singlecard_layout, parent, false);
return new ContactViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
int type = getItemViewType(position);
if (type == ListItem.CONTACT_TYPE) {
ContactItem item = (ContactItem) mItems.get(position);
final Contact contact = item.getContact();
ContactViewHolder holder = (ContactViewHolder) viewHolder;
holder.cardBlankText2.setText(contact.getName() + " " + contact.getSurname());
}
}
}
When an activity is popped off the stack by navigating back, it doesn't retain any of its views or state. The activity object and all its views and state are destroyed. If you need to somehow save what an activity was doing and need to restore that, you need to write the code to do that.