I am trying to update items onRefresh in the recylerview but it is not producing the reuquired list. When I close the app and open it back then it gives the updated items list but it does not update items list through onRefresh method. So basically in order to update the list you have to close and open the app and you can not update it in other way.
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(),
RecyclerView.VERTICAL, false));
//myAdapter.notifyDataSetChanged();
recyclerView.invalidate();
swipeRefreshLayout.setRefreshing(false);
I have tried both notifyDataSetChanged() and invalidate() but none of them are working. There is also no error in logcat. How do I change the method to update it onRefresh?
I have the same adapter setting in the onCreateView method
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
myAdapter = new MyAdapter(getContext(), videoFiles);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
}
This is whole activity with recylerview
public class FilesFragment extends Fragment {
RecyclerView recyclerView;
View view;
MyAdapter myAdapter;
// public static List<Files> items; from adapter class
public FilesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_files, container, false);
recyclerView = view.findViewById(R.id.filesRV);
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
// recyclerView.invalidate();
swipeRefreshLayout = view.findViewById(R.id.swipeToRefresh);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// recyclerView.invalidate();
myAdapter.notifyDataSetChanged();
// updateData(items);
swipeRefreshLayout.setRefreshing(false);
}
public void updateData(List<Files> items) {
// items.clear();
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
items.addAll(items);
myAdapter.notifyDataSetChanged();
}
});
if (items!= null && items.size() > 0) {
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
}
return view;
}
No need to set new adapter every time. Just call notify dataset changed like below:
recyclerView.getAdapter().notifyDataSetChanged();
And before that please make sure that your items are updated. My wild guess is you are not inserting or updating the items. If its a arraylist please insert or update an item before calling the notifyDataSetChanged()
myAdapter.notifyDataSetChanged();
add this line to notifiy adapter that the data source has changed
put this in onResume() to make it seamless
also you can try to do following
recyclerView.setAdapter(null);
recyclerView.setLayoutManager(null);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(myLayoutManager);
myAdapter.notifyDataSetChanged();
what this will do is invalidate the recycler view with new updated data
although there is invalidate method present it tend to not work in certain conditions
public class FilesFragment extends Fragment {
RecyclerView recyclerView;
View view;
MyAdapter myAdapter;
// public static List<Files> items; from adapter class
public FilesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_files, container, false);
recyclerView = view.findViewById(R.id.filesRV);
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
// recyclerView.invalidate();
swipeRefreshLayout = view.findViewById(R.id.swipeToRefresh);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// recyclerView.invalidate();
// myAdapter.notifyDataSetChanged();
updateData(items);
swipeRefreshLayout.setRefreshing(false);
}
});
public void updateData(List<Files> items) {
// items.clear();
myAdapter = new MyAdapter(getContext(), items);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
items.addAll(items);
myAdapter.notifyDataSetChanged();
recyclerview.getAdapter.notifydatasetchanged();
}
return view;
}
Related
I try to create a HORIZONTAL recyclerView but recyclerView can't find the context here is my Fragmnet code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.context =context;
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = container.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
recyclerView.setAdapter(adapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
return inflater.inflate(R.layout.main_fragment, container, false);
}
and here is Recycler view adapter code:
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {
Context context;
ArrayList<CategoryModel> categorys;
public CategoryAdapter(Context context, ArrayList<CategoryModel> categoryModels) {
this.categorys = categoryModels;
this.context = context;
}
#NonNull
#Override
public CategoryAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.product_category,parent,false);
return new ViewHolder(view);
}
i'm also attached the Debug result please check the image
Try like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
// Defines the xml file for the fragment
return inflater.inflate(R.layout.main_fragment, parent, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = view.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
To use Context inside Fragment use getContext() method .
CategoryAdapter adapter = new CategoryAdapter(getContext(),CategoryData.getCategory());
From official doc
Return the Context this fragment is currently associated with.
If you are using Context only for inflating view inside onCreateViewHolder method in CategoryAdapter class then you don't need to pass Context in Constructor. You can get Context from ViewGroup which is first parameter of the onCreateViewHolder method.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_category,parent,false);
In your onCreate() fragment callback I see this line:
public void onCreate(Bundle savedInstanceState) {
...
this.context =context;
...
}
This line doesn't do anything; there's no context argument to the onCreate() method or anything like that, so you're just assigning a variable back to itself. Since your Context context field doesn't have an explicit intialization, the default is null. So this is the same as writing
public void onCreate(Bundle savedInstanceState) {
...
this.context = null;
...
}
Later on, in onCreateView(), you're instantiating your adapter with this line:
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
Because of what I said above, this is functionally the same as
CategoryAdapter adapter = new CategoryAdapter(null, CategoryData.getCategory());
To solve this, you need some place to get a Context instance from. Fragments are often "attached" to a context, and, when they're attached, you can get that context by calling getContext(). A fragment is guaranteed to be attached to a context in the onActivityCreated() callback, so you will want to move your adapter creation to that callback instead of onViewCreated().
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
RecyclerView recyclerView = getView().findViewById(R.id.category_recycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
Previous Question:
May I know why this error will occur when I try to start RecyclerView activity doing a search from fragment.
After added adapter:
error: OwnerDAO.getOwner()' on a null object reference
Fragment code:
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
SearchAdapter adapter;
OwnerDAO mOwnerDao;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.activity_search, container, false);
recyclerView = (RecyclerView)v.findViewById(R.id.recycler_search);
layoutManager = new LinearLayoutManager(this.getActivity());
mOwnerDao = new OwnerDAO(getContext())
adapter = new SearchAdapter(getContext(),mOwnerDao.getOwner());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter( adapter );
return v;
}
Search Adapter:
public SearchAdapter(Context context, List<Owner> owners) {
this.context = context;
this.owners = owners;
}
Set the layoutManager after setAdapter like this :-
recyclerView.setAdapter( adapter );
recyclerView.setLayoutManager(layoutManager);
The error will be removed !!
Recyclerview in my Fragment is giving me this error but I couldn't figure it out. There are lots of questions about this issue but none of them solved my problem so far.
Here is a piece of code from my fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
initCollapsingToolbar();
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
prepareSectors();
try {
Glide.with(this).load(R.drawable.cover).into((ImageView) view.findViewById(R.id.backdrop));
} catch (Exception e) {
e.printStackTrace();
}
return view;
}
You did not create an instance of your adapter before setting it to RecyclerView.
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
// Your adapter initialization here
adapter = new YourAdapter(getActivity(), ....);
recyclerView.setAdapter(adapter);
UPDATE:
Get LayoutInflater from passed context. Update your SectorAdapter code portion as below:
public Context mContext;
public List<Sector> sectorList;
LayoutInflater layoutInflater;
public SectorAdapter(Context mContext, List<Sector> sectorList) {
this.mContext = mContext;
this.sectorList = sectorList;
layoutInflater = LayoutInflater.from(mContext);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = layoutInflater.inflate(R.layout.sector_card, parent, false);
return new MyViewHolder(itemView);
}
Try moving your RecyclerView codes to onViewCreated()
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
sectorList = new ArrayList<>();
prepareSectors();
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
adapter = new SectorAdapter(getActivity(), sectorList);
recyclerView.setAdapter(adapter);
}
Hope this will help~
There is no any code for your adapter. Thus you need to implement the adapter and pass the instance to the recyclerView.
RecyclerView.LayoutManager mLayoutManager ....
....
// Your adapter initialization here
adapter = new someAdapter(....);
recyclerView.setAdapter(adapter);
This will help you!
Hiy guys,
I have a fragment with a RecyclerViewin it. That RecyclerView is populated by a Firebase 'DatabaseReference' object and on that reference I have added a ValueListener as follows:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_home, container, false);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Do something
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "onCancelled", databaseError.toException());
}
});
ItemRecyclerViewAdapter adapter = new ItemRecyclerViewAdapter(activity, itemsDatabaseReference);
adapter.setHasStableIds(true);
// use a linear layout manager
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
DividerItemDecoration itemDecoration = new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL_LIST);
recyclerView.addItemDecoration(itemDecoration);
recyclerView.setAdapter(adapter);
return view;
}
ItemRecyclerViewAdapter extends FirebaseRecyclerAdapter. The problem is that onDataChange happens after onResume so that at times the recycler is empty. What I can't understand is the fact that the recycler view is not always empty. Sometimes data are shown and sometimes not.
Thanks
I think if you are using FirebaseRecyclerAdapter (or any class extended from that) as your RecyclerView adapter, you should set recyclerView.setHasFixedSize(false). So the recyclerView knew that data is constantly updated.
Actually onResume(); is strictly bound with activity onResume();
If you are using viewpager then there is a method in fragment
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//do your logic . updating recycler view
}
if you are infalting in framelayout
then you can update in onViewCreated();
I have never seen like this before. There is no error or exception the code just skipps some line.
I have a class which is doing something and when it's done returns with an Adapter and it's working fine the adapter contains the correct number and returns with it correctly. After that in my Fragment I'm trying to use this Adapter with a RecyclerView and create a list. Here is my fragment:
public class ServicesFragment extends Fragment {
ArrayList<Item> list;
public RecyclerView mRecyclerView;
public RecyclerView.LayoutManager mLayoutManager;
public ItemAdapter itemAdapter;
DownloadDataThread downloadDataThread;
public static boolean dataisready;
ProgressDialog dialog;
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_service, parent, false);
mRecyclerView = (RecyclerView)v.findViewById(R.id.services_recycler_view);
list = new ArrayList<Item>();
list.add(0,new Item());
itemAdapter = new ItemAdapter(list);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
mRecyclerView.setLayoutManager(mLayoutManager);
mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(itemAdapter);
downloadDataThread = ((MainActivity)getActivity()).downloadDataThread;
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable helloRunnable = new Runnable() {
public void run() {
dataisready = downloadDataThread.ready;
if(dataisready){
itemAdapter = downloadDataThread.getItemAdapter();
Log.d("THREAD","adapter " + itemAdapter);
readAndLoadList(itemAdapter);
executor.shutdown();
}
Log.d("THREAD","nézem "+dataisready);
}
};
executor.scheduleAtFixedRate(helloRunnable, 0, 200, TimeUnit.MILLISECONDS);
return v;
}
private void readAndLoadList(ItemAdapter itemAdapter1){
itemAdapter = itemAdapter1;
itemAdapter.notifyDataSetChanged();
Log.d("THREAD"," adaptert22 "+itemAdapter.getItemCount());
mRecyclerView.setHasFixedSize(true);
Log.d("THREAD","muszáfá0 "+ mRecyclerView);
mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
Log.d("THREAD","muszáfá1 "+ mLayoutManager);
mRecyclerView.setLayoutManager(mLayoutManager);
// And after that the other logs never shows up
Log.d("THREAD","muszáfá2 "+ mLayoutManager);
mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
Log.d("THREAD","muszáfá3 "+ mLayoutManager);
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
Log.d("THREAD","muszáfá4 ");
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
Log.d("THREAD","muszáfá5 ");
mRecyclerView.setAdapter(itemAdapter);
mRecyclerView.invalidate();
mRecyclerView.getAdapter().getItemCount();
Log.d("THREAD","lássuk az adaptert33 "+mRecyclerView.getAdapter().getItemCount());
}
}
So as you can see I'm checking in every 200 millisecond that the adapter is ready or not and when it's ready I'm returning with it's adapter and trying to load the RecyclerView but after that line : mRecyclerView.setLayoutManager(mLayoutManager);˛ the other logs never shows up.
Before you ask me I'm created a complete RecyclerView and load in the beginning of the onCreateView because I always got an error for RecyclerView but before I have added that it was also bad.
Have you any idea whats going on here?