How to detect if RecyclerView is empty? - java

I have a RecyclerView getting external JSON data parsed from a server. It works fine however the Volley async task on JSON sometimes takes a while and when it does the fragment displays an empty blank view.
How can I create a test to check if the view is empty and display a msg if it is? I tried to check:
if (recyclerView == null)
if (jsonList == null)
if (adapter.getItemCount() == 0)
if (bundle == null)
But those tests either dont do anything or they display the error message every single time even if the RecyclerView is not empty.
This is the code on the fragment:
public void onViewCreated(View view, Bundle savedInstanceState) {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.supportsPredictiveItemAnimations();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setClickable(true);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);
if (novaAdapter.getItemCount() != 0) {
recyclerView.setAdapter(novaAdapter);
}else{
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Retrieving data from Server");
pDialog.show();
}
super.onViewCreated(view, savedInstanceState);
and the method on the Adapter:
#Override
public int getItemCount() {
return (null != novaList ? novaList.size() : 0);
}
The way it is now the progress dialog always run no matter if the view is empty or not.
UPDATE: Here's the adapter code:
public class NovaAdapter extends RecyclerView.Adapter<NovaListRowHolder> {
ArrayList<HashMap<String, String>> novaList = new ArrayList<HashMap<String, String>>();
public static final String STATUS = "status";
public static final String NAME = "name";
public static final String ID = "id";
private Context mContext;
public NovaAdapter(Context context, ArrayList<HashMap<String, String>> novaList) {
this.novaList = novaList;
this.mContext = context;
}
#Override
public NovaListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.instances_list, null);
NovaListRowHolder mh = new NovaListRowHolder(v);
return mh;
}
#Override
public void onBindViewHolder(NovaListRowHolder novaListRowHolder, int i) {
HashMap<String, String> e = novaList.get(i);
novaListRowHolder.name.setText(e.get(NAME));
novaListRowHolder.status.setText(e.get(STATUS));
novaListRowHolder.setId(e.get(ID));
}
#Override
public int getItemCount() {
return (null != novaList ? novaList.size() : 0);
}class NovaListRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
protected TextView name;
protected TextView status;
protected String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public NovaListRowHolder(View view) {
super(view);
view.setOnClickListener(this);
this.name = (TextView) view.findViewById(R.id.nameInstance);
this.status = (TextView) view.findViewById(R.id.statusInstance);
}
public void onClick(View view){
Dialog dialog = new Dialog(view.getContext());
dialog.setContentView(R.layout.instances_listdetail);
dialog.setTitle("Details " + name.getText() + " " + getPosition());
dialog.show();
}
UPDATE2:
I updated another class which is pretty much the same as the one above with a callback interface however now the recyclerView displays for 1 second and then goes blank. The dialog doesn't even show. Here's the code:
public class SubnetsFragment extends Fragment implements OnJSONLoaded{
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
private OnFragmentInteractionListener mListener;
public ArrayList<HashMap<String, String>> jsonList;
public RecyclerView recyclerView;
public ProgressDialog pDialog;
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static SubnetsFragment newInstance(int sectionNumber) {
SubnetsFragment fragment = new SubnetsFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public SubnetsFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle extras = getArguments();
Serializable parsedList = extras.getSerializable("SubnetsParsed");
jsonList = (ArrayList<HashMap<String, String>>)parsedList;
if (extras == null){
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setTitle("Token Expired");
alert.setMessage("Authentication Token expired! Please login again.")
.setNeutralButton("Connect", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(getActivity(), Login.class);
startActivity(intent);
getActivity().finish();
getFragmentManager().beginTransaction().remove(SubnetsFragment.this).commit();
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
}
View rootView = inflater.inflate(R.layout.fragment_subnets, container, false);
recyclerView = (RecyclerView)rootView.findViewById(R.id.subnetsRV);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.supportsPredictiveItemAnimations();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setClickable(true);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
onJsonLoaded(jsonList);
}
#Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
SubnetsParser.setOnJSONLoadedListener(new OnJSONLoaded() {
#Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
if (list.size() != 0){
SubnetsAdapter subnetsAdapter = new SubnetsAdapter(getActivity(),jsonList);
recyclerView.setAdapter(subnetsAdapter);
}else {
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Retrieving data from Server");
pDialog.show();
}
}
});
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((Stackerz) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
//try {
// mListener = (OnFragmentInteractionListener) activity;
//} catch (ClassCastException e) {
// throw new ClassCastException(activity.toString()
// + " must implement OnFragmentInteractionListener");
//}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
And this is the JSON Parser class:
public class SubnetsParser extends Activity{
public static final String NAME = "name";
public static final String GW = "gw";
public static final String CIDR = "cidr";
public static final String ID = "id";
public String authToken;
public String neutronURL;
public static SubnetsParser parser = null;
public static OnJSONLoaded mListener;
public static void setOnJSONLoadedListener(OnJSONLoaded listener) {
mListener = listener;
}
public interface OnJSONLoaded {
void onJsonLoaded(ArrayList<HashMap<String, String>> list);
}
public static SubnetsParser shared(){
if (parser == null){
parser = new SubnetsParser();
}
return parser ;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public static ArrayList<HashMap<String, String>> parseJSON(String subnetsJSON){
ArrayList<HashMap<String, String>> jsonList = new ArrayList<HashMap<String, String>>();
try {
Subnets subnets = new Subnets();
JSONObject subnet = new JSONObject(subnetsJSON);
JSONArray subnetobj = subnet.getJSONArray("subnets");
for (int i = 0; i < subnetobj.length(); i++) {
JSONObject objsrv = subnetobj.getJSONObject(i);
subnets.setName(objsrv.getString("name"));
subnets.setGw(objsrv.getString("gateway_ip"));
subnets.setCidr(objsrv.getString("cidr"));
subnets.setId(objsrv.getString("id"));
HashMap<String, String> map = new HashMap<String, String>();
map.put(NAME, subnets.getName());
map.put(GW, subnets.getGw());
map.put(CIDR, subnets.getCidr());
map.put(ID, subnets.getId());
jsonList.add(map);
}
} catch (JSONException e) {
Log.d("ErrorInitJSON", e.toString());
e.printStackTrace();
}
Collections.sort(jsonList, new Comparator<HashMap<String, String>>() {
#Override
public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
return (lhs.get("name")).compareToIgnoreCase(rhs.get("name"));
}
});
if (mListener != null) {
mListener.onJsonLoaded(jsonList);
}
return jsonList;
}
}

You can check if it's empty by running:
if (adapter.getItemCount() == 0)
If it's not working it means you haven't Override the getItemCount on your adapter! so make sure it's overrided:
#Override
public int getItemCount() {
return mDataSet.size(); // Where mDataSet is the list of your items
}
Update:
So based on your update this is how you could proceed. In my opinion you just need a callback. You are checking if the list is empty on your onViewCreated. You should, instead, use a callback. Do something like that:
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.supportsPredictiveItemAnimations();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setClickable(true);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Retrieving data from Server");
pDialog.show();
}
In the class you are using to populate your jsonList, I assume an asynctask or a separate class add this:
private OnJsonLoaded mListener;
public void setOnJsonLoadedListener(OnJsonLoaded listener) {
mListener = listener;
}
public interface OnJsonLoaded {
void onJsonLoaded(ArrayList<HashMap<String, String>> list);
}
now, in the asynctask that populate ur jsonLise or when the json parser finish his job, call the listener:
if (mListener != null) {
mListener.onJsonLoaded(jsonList);
}
In your fragment (the one with NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList); and your recyclerview) add the interface implementation:
classThatParseJson.setOnJsonLoadedListener(new OnJsonLoaded() {
#Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
if (list.size() != 0) {
NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);
recyclerView.setAdapter(novaAdapter);
} else {
// Show something like a dialog that the json list is 0 or do whatever you want... here the jsonlist have a count of 0 so it's empty!
}
}
});
the code may containts errors, i written it by hand without using IDE so maybe you have to fix small things but the logic is quite clear!
Update based on your Update 2:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_subnets, container, false);
recyclerView = (RecyclerView)rootView.findViewById(R.id.subnetsRV);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.supportsPredictiveItemAnimations();
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setClickable(true);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
// start json parser here instead of passing to fragment as a bundle
SubnetsParser.parseJSON(yourparams);
}
#Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
SubnetsParser.setOnJSONLoadedListener(new OnJSONLoaded() {
#Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
if (list.size() != 0){
SubnetsAdapter subnetsAdapter = new SubnetsAdapter(getActivity(),jsonList);
recyclerView.setAdapter(subnetsAdapter);
}else {
//pDialog = new ProgressDialog(getActivity());
//pDialog.setMessage("Retrieving data from Server");
//pDialog.show();
//Instead of a progressdialog, put here a dialog informing that the list is empty!
}
}
});
}

How is described in https://developer.android.com/training/material/lists-cards.html
The overriden method getItemCount() is invoked by the layout manager.
This is the snippet:
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
So to detect if the recyclerView is empty you must request it to your LayoutManager. Example:
if( mLayoutManager.getItemCount() == 0 ){
//Do something
}
I try to getItemCount() of my Adapter but this returns 0, I don't know why it is...

if (adapter.getItemCount() == 0)
doing this worked for me...

You can do it using interface callback:
Create interface
public interface OnAdapterCountListener {
void onAdapterCountListener(int count);
}
Add below variables and methods in adapter
private OnAdapterCountListener onAdapterCountListener;
public void setOnAdapterCountListener(OnAdapterCountListener l) {
onAdapterCountListener = l;
}
Add this line in onCreateViewHolder of your adapter
onAdapterCountListener.onAdapterCountListener(getItemCount());
Finally, call interface in your activity
listAdapter.setOnAdapterCountListener(new OnAdapterCountListener() {
#Override
public void onAdapterCountListener(int count) {
if (count > 0)
adapterEmptyText.setVisibility(View.GONE);
}
});

Create a Class and inherit Recyclerview - Follow the bellowing code
public class RecyclerviewEmpty extends RecyclerView {
private View emptyView;
private final AdapterDataObserver observer = new AdapterDataObserver() {
#Override
public void onChanged() {
checkIfEmpty();
}
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
checkIfEmpty();
}
#Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
checkIfEmpty();
}
};
public RecyclerviewEmpty(#NonNull Context context) {
super(context);
}
public RecyclerviewEmpty(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public RecyclerviewEmpty(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void checkIfEmpty() {
if (emptyView != null && getAdapter() != null) {
final boolean emptyViewVisible = getAdapter().getItemCount() == 0;
emptyView.setVisibility(emptyViewVisible ? VISIBLE : GONE);
setVisibility(emptyViewVisible ? GONE : VISIBLE);
}
}
#Override
public void setAdapter(#Nullable Adapter adapter) {
final Adapter oldAdapter = getAdapter();
if (oldAdapter != null) {
oldAdapter.unregisterAdapterDataObserver(observer);
}
super.setAdapter(adapter);
if (adapter != null) {
adapter.registerAdapterDataObserver(observer);
}
checkIfEmpty();
}
public void setEmptyView(View emptyView) {
this.emptyView = emptyView;
checkIfEmpty();
}
activity_xml - define class name in a View
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_main"
tools:context=".Ui.FavouriteActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<view
android:id="#+id/rv_fav_activity"
class="com.kumar.random.quotes.Views.RecyclerviewEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="#+id/list_empty1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="Empty Favourite"
android:textSize="14sp" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Activity.java
private RecyclerviewEmpty rvFavourite;
private void setUpRv() {
rvFavourite.setEmptyView(emptyView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
MainQuotesAdapter adapter = new MainQuotesAdapter(this, favouriteItem);
rvFavourite.setLayoutManager(layoutManager);
rvFavourite.setAdapter(adapter);
}
Please notes_01:
rvFavourite.setEmptyView(emptyView);
Please Notes_02:
public void setEmptyView(View emptyView) {
this.emptyView = emptyView;
checkIfEmpty();
}
Please Notes_03
<view
android:id="#+id/rv_fav_activity"
class="com.kumar.random.quotes.Views.RecyclerviewEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Related

Using Recyclerview with Volley not working in fragment

I am trying to use Volley to get data via JSON and populate the data in RecyclerView in fragment. I have tested the code with normal activity and it works, but I am finding it difficult implementing thesame thing in fragment. I can see the response in JSON format when I Log in console but it seems no data is added to the list item, thus nothing is displayed in fragment and no error in LogCat.
explore_content.xml
This is the xml that'l be inflated in the adapter
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="#+id/imagesExplore1"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/testUrl"
android:layout_below="#+id/imagesExplore1"
android:paddingLeft="50dp"
android:textSize="19sp"
/>
</RelativeLayout>
fragment_challenge.xml
This is where I put the RecyclerView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="fragments.ChallengeFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/testRecyclerView"
android:paddingBottom="20dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:scrollbars="vertical"
android:layout_marginTop="20dp"
/>
</RelativeLayout>
ExploreImagesAdapter.java
The adapter I use
public class ExploreImagesAdapter extends RecyclerView.Adapter<ExploreImagesAdapter.MyViewHolder> {
private Context context;
private List<ExploreImages> exploreImagesList;
RequestOptions options;
public ExploreImagesAdapter(Context context, List<ExploreImages> exploreImagesList) {
this.context = context;
this.exploreImagesList = exploreImagesList;
options = new RequestOptions().centerCrop().placeholder(R.drawable.add_photo).error(R.drawable.back_left_icon);
}
#NonNull
#Override
public ExploreImagesAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.explore_content, parent, false);
return new ExploreImagesAdapter.MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Glide.with(context).load(exploreImagesLlist.get(position).getImage_url()).apply(options).into(holder.imageView);
holder.testUrl.setText(exploreImagesList.get(position).getImage_url());
}
#Override
public int getItemCount() {
int a ;
if(exploreImagesList != null && exploreImagesList.isEmpty()) {
a = exploreImagesList.size();
}
else {
a = 0;
}
return a;
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView testUrl;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imagesExplore1);
testUrl = itemView.findViewById(R.id.testUrl);
}
}
public void setItems(List<ExploreImages> data) {
exploreImagesList = data;
notifyDataSetChanged();
}
public void addData (List<ExploreImages> data) {
exploreImagesList.addAll(data);
notifyDataSetChanged();
}
}
ExploreImages.java
A model for the data
ublic class ExploreImages {
private String image_id;
private String image_url;
private String photo_year;
public ExploreImages(){
}
public ExploreImages(String image_id, String image_url, String photo_year) {
this.image_id = image_id;
this.image_url = image_url;
this.photo_year = photo_year;
}
public String getImage_id() {
return image_id;
}
public String getImage_url() {
return image_url;
}
public String getPhoto_year(){
return photo_year;
}
public void setImage_id(String image_id) {
this.image_id = image_id;
}
public void setImage_url(String image_url) {
this.image_url = image_url;
}
public void setPhoto_year(String photo_year){ this.photo_year = photo_year;}
}
ExploreFragment.java
Finally the fragment where I make the network call and set the Adapter
public class ExploreFragment extends Fragment {
private JsonArrayRequest request;
private RequestQueue requestQueue;
private List<ExploreImages> lstAnime;
private ArrayList<ExploreImages> tempList;
public ChallengeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
lstAnime = new ArrayList<>();
View root = inflater.inflate(R.layout.fragment_explore, container, false);
RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.testRecyclerView);
ExploreImagesAdapter myAdapter = new ExploreImagesAdapter(getActivity(), lstAnime);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
/* myAdapter.notifyDataSetChanged();*/
jsonrequest();
// Inflate the layout for this fragment
return root;
}
private void jsonrequest() {
request = new JsonArrayRequest(EndPoints.EXPLORE_IMAGES_URL, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
/*Log.e("Errorrr", "["+response+"]");*/
JSONObject jsonObject = null;
int i;
for(i=0; i<response.length(); i++){
try {
jsonObject = response.getJSONObject(i);
ExploreImages anime = new ExploreImages();
anime.setImage_id(jsonObject.getString("id"));
anime.setImage_url(jsonObject.getString("url"));
anime.setPhoto_year(jsonObject.getString("photo_year"));;
Log.e("CHAAAA", "["+response+"]");
lstAnime.add(anime);
ExploreImagesAdapter myAdapter = new ExploreImagesAdapter(getActivity(),
lstAnime);
myAdapter.setItems(lstAnime);
}
catch (JSONException e){
e.printStackTrace();
Log.e("TESTERROR", "["+response+"]");
}
/*ExploreImagesAdapter myAdapter = new ExploreImagesAdapter(getActivity(), lstAnime);
myAdapter.addData(lstAnime);*/
setRecyclerView(lstAnime);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(request);
}
private void setRecyclerView(List<ExploreImages> lstAnime) {
RecyclerView recyclerViewx = getActivity().findViewById(R.id.testRecyclerView);
ExploreImagesAdapter myAdapter = new ExploreImagesAdapter(getActivity(), lstAnime);
recyclerViewx.setAdapter(myAdapter);
recyclerViewx.setLayoutManager(new LinearLayoutManager(getActivity()));
}
}
I have searched Everywhere and tried everything but no data is displayed even when the JSON is parsed in Volley
Do these things
1) Set linearlayout manager after declaring recyclerview
2) Declare recyclerview and adapter class globally
3) Update adapter after parsing JSON array to arraylist
Eg
public class ExploreFragment extends Fragment {
private JsonArrayRequest request;
private RequestQueue requestQueue;
private List<ExploreImages> lstAnime;
private ArrayList<ExploreImages> tempList;
ExploreImagesAdapter myAdapter;
public ChallengeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
lstAnime = new ArrayList<>();
View root = inflater.inflate(R.layout.fragment_explore, container, false);
RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.testRecyclerView);
// set layout manager here
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
myAdapter = new ExploreImagesAdapter(getActivity(), lstAnime);
recyclerView.setAdapter(myAdapter);
jsonrequest();
// Inflate the layout for this fragment
return root;
}
private void jsonrequest() {
request = new JsonArrayRequest(EndPoints.EXPLORE_IMAGES_URL, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
/*Log.e("Errorrr", "["+response+"]");*/
JSONObject jsonObject = null;
int i;
for(i=0; i<response.length(); i++){
try {
jsonObject = response.getJSONObject(i);
ExploreImages anime = new ExploreImages();
anime.setImage_id(jsonObject.getString("id"));
anime.setImage_url(jsonObject.getString("url"));
anime.setPhoto_year(jsonObject.getString("photo_year"));;
Log.e("CHAAAA", "["+response+"]");
lstAnime.add(anime);
}
catch (JSONException e){
e.printStackTrace();
Log.e("TESTERROR", "["+response+"]");
}
}
// update adapter here
myAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(request);
}
}
you are doing several things wrong here
make ExploreImagesAdapter as global variable inside of fragment and use it everywhere else
now when you will get your data just call your adapter and add Data in it you already have function for that.
First of all you're always creating a new Adapter instance and you shouldn't. Keep one instance global to this Fragment and you're good to go. Then update that same instance.
Using your code:
private ExploreImagesAdapter myAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
lstAnime = new ArrayList<>();
View root = inflater.inflate(R.layout.fragment_explore, container, false);
RecyclerView recyclerViewx = getActivity().findViewById(R.id.testRecyclerView);
myAdapter = new ExploreImagesAdapter(getActivity(), lstAnime);
recyclerViewx.setAdapter(myAdapter);
recyclerViewx.setLayoutManager(new LinearLayoutManager(getActivity()));
jsonrequest();
return root;
}
private void jsonrequest() {
request = new JsonArrayRequest(EndPoints.EXPLORE_IMAGES_URL, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
/*Log.e("Errorrr", "["+response+"]");*/
JSONObject jsonObject = null;
int i;
for(i=0; i<response.length(); i++){
try {
jsonObject = response.getJSONObject(i);
ExploreImages anime = new ExploreImages();
anime.setImage_id(jsonObject.getString("id"));
anime.setImage_url(jsonObject.getString("url"));
anime.setPhoto_year(jsonObject.getString("photo_year"));;
Log.e("CHAAAA", "["+response+"]");
lstAnime.add(anime);
}
catch (JSONException e){
e.printStackTrace();
Log.e("TESTERROR", "["+response+"]");
}
}
myAdapter.setItems(lstAnime);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(request);
}
RecyclerView recyclerViewx = getActivity().findViewById(R.id.testRecyclerView);
this line refers to the RecyclerView in your activity. You should use in the fragment

Update recyclerview data

since several days I try to handle data in recyclerview in viewpager2. The viewpager has an adapter managing the data in recyclerview. But everything I try to do seems to not work. Maybe I missundersteand the purpose or something. I hope you can help me.
This activity manages the viewpager and its adapter. It sends the data to the inner recyclerview:
public class AudioFilePanel extends AppCompatActivity
{
private String currentTab;
private ViewPagerAdapter adapter;
private ViewPager2 viewPager;
private TabLayout tabLayout;
private Map<String, List<String>> content;
private String path;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_file_panel);
viewPager = findViewById(R.id.view_pager2);
tabLayout = findViewById(R.id.tabs);
Button addFilesByTag = findViewById(R.id.add_files_with_tag);
if (null == currentTab)
{
currentTab = "music";
}
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()));
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setText(content.keySet().toArray()[position].toString())).attach();
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
#Override
public void onTabSelected(TabLayout.Tab tab)
{
currentTab = tab.getText().toString();
}
#Override
public void onTabUnselected(TabLayout.Tab tab)
{
}
#Override
public void onTabReselected(TabLayout.Tab tab)
{
}
});
addFilesByTag.setOnClickListener(l ->
{
Intent fileBrowser = new Intent(AudioFilePanel.this, FileBrowser.class);
startActivityForResult(fileBrowser, 1);
});
}
private void updateViweData()
{
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()));
viewPager.setAdapter(adapter);
}
private Map<String, List<String>> listByTag()
{
Map<String, List<String>> result = new HashMap<>();
DirectoryDao dao = new DirectoryDao(getApplicationContext());
String[] categories = {"music", "ambience", "effect"};
for (String category : categories)
{
List<String> directories =
dao.getDirectoriesForCategory(category).stream().map(Directory::getPath).collect(Collectors.toList());
result.put(category, directories);
}
return result;
}
This is the view pager adapter. It takes the data directly from the activity and should trigger data update in the inner recyclerview every time when an item will be clicked. See line 118-128:
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder>
{
private List<List<String>> filesListsByCategory;
private LayoutInflater mInflater;
private Context ctx;
private ItemListAdapter adapter;
private List<String> categoryFiles;
public ViewPagerAdapter(Context context, List<List<String>> data)
{
this.mInflater = LayoutInflater.from(context);
this.filesListsByCategory = data;
this.ctx = context;
}
#NotNull
#Override
public ViewHolder onCreateViewHolder(#NotNull ViewGroup parent, int viewType)
{
return new ViewHolder(mInflater.inflate(R.layout.item_viewpager, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
FileBrowserService fbs = new FileBrowserService();
categoryFiles = filesListsByCategory.get(position);
adapter = new ItemListAdapter(categoryFiles, new ItemList.OnListFragmentInteractionListener()
{
#Override
public void onListFragmentInteraction(String item)
{
categoryFiles = fbs.getFiles(categoryFiles.get(position));
categoryFiles.add(0, "previous directory");
updateUi(adapter, holder);
}
});
holder.myView.setAdapter(adapter);
}
private void updateUi(ItemListAdapter adapter, ViewHolder holder)
{
adapter.notifyDataSetChanged();
holder.myView.setAdapter(adapter);
}
#Override
public int getItemCount()
{
return filesListsByCategory.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
RecyclerView myView;
RelativeLayout relativeLayout;
ViewHolder(View itemView)
{
super(itemView);
myView = itemView.findViewById(R.id.my_list);
myView.setLayoutManager(new LinearLayoutManager(ctx));
relativeLayout = itemView.findViewById(R.id.container);
}
}
}
It is the adapter of inner recyclerview. It represents just a list of elements:
public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ViewHolder>
{
private List<String> files;
private final OnListFragmentInteractionListener mListener;
public ItemListAdapter(List<String> items, OnListFragmentInteractionListener listener)
{
files = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_item, parent, false));
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position)
{
holder.file = files.get(position);
holder.mContentView.setText(files.get(position));
holder.mView.setOnClickListener(v ->
{
if (null != mListener)
{
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.file);
}
});
}
#Override
public int getItemCount()
{
return files.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
private final View mView;
private final TextView mContentView;
private String file;
private ViewHolder(View view)
{
super(view);
mView = view;
mContentView = view.findViewById(R.id.content);
}
}
}
The last thing is the ItemList fragment.
public class ItemList extends Fragment
{
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
private OnListFragmentInteractionListener mListener;
/**
* Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon screen orientation
* changes).
*/
public ItemList()
{
}
// TODO: Customize parameter initialization
#SuppressWarnings("unused")
public static ItemList newInstance(int columnCount)
{
ItemList fragment = new ItemList();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener)
{
mListener = (OnListFragmentInteractionListener) context;
} else
{
throw new RuntimeException(context.toString() + " must implement OnListFragmentInteractionListener");
}
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (getArguments() != null)
{
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_item_list, container, false);
if (view instanceof RecyclerView)
{
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1)
{
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else
{
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new ItemListAdapter(getArguments().getStringArrayList("list"), mListener));
}
return view;
}
#Override
public void onDetach()
{
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this fragment to allow an interaction in this
* fragment to be communicated to the activity and potentially other fragments contained in that activity.
* <p/>
* See the Android Training lesson
* <a href= "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnListFragmentInteractionListener
{
// TODO: Update argument type and name
void onListFragmentInteraction(String item);
}
}
When I click, the data won't update. What I would like to have is:
This is what you have to do
add this method into your adapter class
public void updateData(List<String> filesList, int flag) {
if (flag == 0) { //append
for (int i = 0; i < filesList.size(); i++) {
files.add(messageList.get(i));
notifyItemInserted(getItemCount());
}
} else { //clear all
files.clear();
notifyDataSetChanged();
}
}
Then whenever you need to update recycle view call like below
mItemListAdapter.updateData(yourNewListOfItems, 0);
if you need to reset recycle-view call like below
mItemListAdapter.updateData(null, 1);
Add notifyDataSetChanged() in your adapter

Cannot cast onItem clicklistener inside Fragment Class form Adapter Class

I have an Fragment with recycleview where I populate it with json items from internet.
It load fine and Next step I want to is open new Activity when any row is clicked. It works in activity, thus I modified the same code for fragment but for fragment it throws exception in line
mExampleAdapter.setOnItemClickListener(getActivity());
with errror setOnItemClickListener of refrence adatper cannot be applied to Fragment activty and thus when I change line to
(ExampleAdapter.OnItemClickListener)
and when i build and run . Then app crashes with error that Mainactivity which holds framgnet cannot be cast in to .ExampleAdapter$OnItemClickListener
Here is my whole Fragment class
public class Mynotes extends Fragment implements ExampleAdapter.OnItemClickListener{
public static final String YTD_LINK = "link";
private RecyclerView mRecyclerView;
private ExampleAdapter mExampleAdapter;
private ArrayList<ExampleItem> mExampleList;
private RequestQueue mRequestQueue;
String url="https://api.myjson.com/bins/16mecx";
public Mynotes() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_jsonfeed, container, false);
mRecyclerView = view.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new MyDividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL, 36));
mExampleList = new ArrayList<>();
mExampleAdapter = new ExampleAdapter(getActivity(), mExampleList);
mRecyclerView.setAdapter(mExampleAdapter);
mExampleAdapter.setOnItemClickListener((ExampleAdapter.OnItemClickListener) getActivity());
parseJSON();
return view;
}
private void parseJSON() {
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
myProgressBar.setVisibility(View.GONE);
try {
JSONArray jsonArray = response.getJSONArray("hits");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject hit = jsonArray.getJSONObject(i);
String videoTitle = hit.getString("title");
String link = hit.getString("link");
mExampleList.add(new ExampleItem(videoTitle, link));
mExampleAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(request);
}
#Override
public void onItemClick(int position) {
Intent intent = new Intent(getActivity(), NewActiviyt.class);
ExampleItem clickedItem = mExampleList.get(position);
intent.putExtra(YTD_LINK, clickedItem.getmLink());
startActivity(intent);
}
#Override
public void onRefresh() {
}
}
and my Adapter Class is
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
private Context mContext;
private ArrayList<ExampleItem> mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public ExampleAdapter(Context context, ArrayList<ExampleItem> exampleList) {
mContext = context;
mExampleList = exampleList;
}
#Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.example_item, parent, false);
return new ExampleViewHolder(v);
}
#Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
String title = currentItem.getTitle();
// int likeCount = currentItem.getLikeCount();
// String imageUrl = currentItem.getImageUrl();
holder.mTextViewCreator.setText(title);
// holder.mTextViewLikes.setText("Likes: " + likeCount);
// Glide.with(mContext).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(holder.mImageView);
}
#Override
public int getItemCount() {
return mExampleList.size();
}
public class ExampleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView mTextViewCreator;
// public TextView mTextViewLikes;
// public ImageView mImageView;
public ExampleViewHolder(View itemView) {
super(itemView);
// mTextViewLikes = itemView.findViewById(R.id.text_view_likes);
// mImageView = itemView.findViewById(R.id.image_view);
mTextViewCreator = itemView.findViewById(R.id.text_title);
}
#Override
public void onClick(View view) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
}
}
Thanks in advance.
replace getActivity with getContext when you work in fragment,
You can read more here
What is different between getContext and getActivity from Fragment in support library?
Your activity should implement ExampleAdapter.OnItemClickListener

recyclerview item showing showing empty white screen in navigation drawer fragment

I am developing news and I have implemented recyclerview with search view in navigation drawer fragment however recyclerview item in navigation drawer showing empty white screen.
I am getting two ending point in fragment class and below my root URL.
private static final String ROOT_URL = "https://newsapi.org";
below my first ending point where I am getting top headlines.
#GET("/v2/top-headlines?sources=bbc-sport&apiKey=my-api-key")
Call<SportNews> getArticles();
below second ending point where I am getting everything
#GET("/v2/everything?apiKey=my-api-key")
Call<Search> getSearchViewArticles(#Query("q") String q);
below BBCSportsFragment class where I have implemented RecyclerView and SearchView
public class BBCSportFragment extends Fragment implements ArticleAdapter.ClickListener {
public static List<Article> articleList = new ArrayList<>();
public static List<Article> origArticleList = new ArrayList<>();
#ActivityContext
public Context activityContext;
Search search;
#ApplicationContext
public Context mContext;
#BindView(R.id.recycler_view)
RecyclerView recyclerView;
BBCSportFragmentComponent bbcSportFragmentComponent;
BBCFragmentContextModule bbcFragmentContextModule;
private SportNews sportNews;
private static ArticleAdapter articleAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bbcsport, container, false);
ButterKnife.bind(this, view);
SportInterface sportInterface = SportClient.getApiService();
Call<SportNews> call = sportInterface.getArticles();
call.enqueue(new Callback<SportNews>() {
#Override
public void onResponse(Call<SportNews> call, Response<SportNews> response) {
if (response == null) {
sportNews = response.body();
if (sportNews != null && sportNews.getArticles() != null) {
articleList.addAll(sportNews.getArticles());
}
articleAdapter = new ArticleAdapter(articleList, sportNews);
ApplicationComponent applicationComponent;
applicationComponent = (ApplicationComponent) MyApplication.get(Objects.requireNonNull(getActivity())).getApplicationContext();
bbcSportFragmentComponent = (BBCSportFragmentComponent) DaggerApplicationComponent.builder().contextModule(new ContextModule(getContext())).build();
bbcSportFragmentComponent.injectBBCSportFragment(BBCSportFragment.this);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(applicationComponent));
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(articleAdapter);
}
}
#Override
public void onFailure(Call<SportNews> call, Throwable t) {
}
});
SportInterface searchInterface = SportClient.getApiService();
Call<Search> searchCall = searchInterface.getSearchViewArticles("q");
searchCall.enqueue(new Callback<Search>() {
#Override
public void onResponse(Call<Search> call, Response<Search> response) {
search = response.body();
if (search != null && search.getArticles() != null) {
articleList.addAll(search.getArticles());
origArticleList.clear();
origArticleList.addAll(search.getArticles());
}
articleAdapter = new ArticleAdapter(articleList, search);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(articleAdapter);
}
#Override
public void onFailure(Call<Search> call, Throwable t) {
}
});
return view;
}
private Context getContext(ApplicationComponent applicationComponent) {
return null;
}
public static void doFilter(String searchQuery) {
searchQuery = searchQuery.toLowerCase();
articleList.clear();
for (Article article : origArticleList) {
final String text = article.getTitle();
if (text.equals(searchQuery))
articleList.add(article);
}
articleAdapter.notifyDataSetChanged();
}
}
below adapter class
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.CustomViewHolder> {
public static final String urlKey = "urlKey";
List<Article> articles;
private ClipboardManager myClipboard;
private ClipData myClip;
public ArticleAdapter(List<Article> articles, SportNews sportNews) {
this.articles = articles;
}
public ArticleAdapter(ClickListener clickListener) {
}
public ArticleAdapter(List<Article> articleList, Search search) {
}
#NonNull
#Override
public ArticleAdapter.CustomViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.article_list, null);
return new ArticleAdapter.CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull edgar.yodgorbek.sportnews.adapter.ArticleAdapter.CustomViewHolder customViewHolder, int position) {
Article article = articles.get(position);
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
Date d = new Date();
try {
d = input.parse(article.getPublishedAt());
} catch (ParseException e) {
e.printStackTrace();
}
String formatted = output.format(d);
customViewHolder.articleTime.setText(formatted);
customViewHolder.articleAuthor.setText(article.getSource().getName());
customViewHolder.articleTitle.setText(article.getTitle());
Picasso.get().load(article.getUrlToImage()).into(customViewHolder.articleImage);
customViewHolder.itemView.setOnClickListener(v -> {
Intent intent = new Intent(v.getContext(), DetailActivity.class);
intent.putExtra("urlKey", article.getUrl());
v.getContext().startActivity(intent);
});
customViewHolder.articleShare.setOnClickListener(v -> {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String articleDescription = article.getDescription();
String articleTitle = article.getTitle();
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, articleDescription);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, articleTitle);
v.getContext().startActivity((Intent.createChooser(sharingIntent, "Share using")));
});
customViewHolder.articleFavorite.setOnClickListener(v -> {
myClipboard = (ClipboardManager) v.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
myClip = ClipData.newPlainText("label", customViewHolder.articleTitle.getText().toString());
myClipboard.setPrimaryClip(myClip);
Toast.makeText(v.getContext(), "Copied to clipboard", Toast.LENGTH_SHORT).show();
});
}
#Override
public int getItemCount() {
if (articles == null) return 0;
return articles.size();
}
public interface ClickListener {
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.articleAuthor)
TextView articleAuthor;
#BindView(R.id.articleTitle)
TextView articleTitle;
#BindView(R.id.articleImage)
ImageView articleImage;
#BindView(R.id.articleTime)
TextView articleTime;
#BindView(R.id.articleShare)
ImageButton articleShare;
#BindView(R.id.articleFavorite)
ImageButton articleFavorite;
public CustomViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
below main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search_white"
android:title="#string/search_hint"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
following screeshot of recyclerview item in navgation drawer fragment
Sorry for late reply, but it seems like you are calling both APIs at once.
One for getting all data and another one for getting filtered data which contain some string (E.g. In your code you are having "q").
You need to remove below lines from onCreateView of your Fragment. Only call it after click on search icon. And replace the parameter "q" in searchInterface.getSearchViewArticles("q"); with the string value which you will get from the search box.
SportInterface searchInterface = SportClient.getApiService();
Call<Search> searchCall = searchInterface.getSearchViewArticles("q");
searchCall.enqueue(new Callback<Search>() {
#Override
public void onResponse(Call<Search> call, Response<Search> response) {
search = response.body();
if (search != null && search.getArticles() != null) {
articleList.clear();
articleList.addAll(search.getArticles());
}
if(articleAdapter != null){
articleAdapter.notifyDataSetChanged();
} else {
articleAdapter = new ArticleAdapter(articleList, search);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(articleAdapter);
}
}
#Override
public void onFailure(Call<Search> call, Throwable t) {
}
});

Other ways to search a ListView

I am trying to use TextChangedListener to implement search functionality on my ListView. But after adding some character in EditText; the ListView goes blank. I have implemented filter method in my ArrayAdapter class.
I am getting my data from JSON.
My Logcat shows: getSlotFromBufferLocked: unknown buffer
Is there any other way to search ListView?
Here's my code:
UserList.java
public class UserList extends AppCompatActivity {
private ListView listView;
private ArrayList<MyDataModel> list;
private MyArrayAdapter adapter;
private EditText search;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_list);
search = (EditText) findViewById(R.id.search);
//Array List for Binding Data from JSON to this List
list = new ArrayList<>();
//Binding that List to Adapter
adapter = new MyArrayAdapter(this, list);
//Getting List and Setting List Adapter
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String text = search.getText().toString().toLowerCase(Locale.getDefault());
adapter.filter(text);
}
#Override
public void afterTextChanged(Editable s) {
}
});
//Checking Internet Connection
if (InternetConnection.checkConnection(getApplicationContext())) {
new GetDataTask().execute();
} else {
Snackbar.make(findViewById(R.id.parentLayout),"Internet Connection Not Available", Snackbar.LENGTH_LONG).show();
}
}
//Creating Get Data Task for Getting Data From Web
class GetDataTask extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
int jIndex;
int x;
#Override
protected void onPreExecute() {
super.onPreExecute();
//Progress Dialog for User Interaction
x=list.size();
if(x==0)
jIndex=0;
else
jIndex=x;
dialog = new ProgressDialog(UserList.this);
dialog.setTitle("Please Wait..."+x);
dialog.setMessage("Retrieving Data");
dialog.show();
}
#Nullable
#Override
protected Void doInBackground(Void... params) {
//Getting JSON Object from Web Using okHttp
JSONObject jsonObject = JSONParser.getDataFromWeb();
try {
if (jsonObject != null) {
if(jsonObject.length() > 0) {
JSONArray array = jsonObject.getJSONArray(Keys.KEY_CONTACTS);
//Check Length of Array...
int lenArray = array.length();
if(lenArray > 0) {
for( ; jIndex < lenArray; jIndex++) {
//Creating Every time New Object and adding to List
MyDataModel model = new MyDataModel();
JSONObject innerObject = array.getJSONObject(jIndex);
String name = innerObject.getString(Keys.KEY_NAME);
model.setName(name);
list.add(model);
}
}
}
} else {
}
} catch (JSONException je) {
Log.i(JSONParser.TAG, "" + je.getLocalizedMessage());
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
dialog.dismiss();
//Checking if List size if more than zero then update ListView
if(list.size() > 0) {
adapter.notifyDataSetChanged();
} else {
Snackbar.make(findViewById(R.id.parentLayout), "No Data Found", Snackbar.LENGTH_LONG).show();
}
}
}
}
I have implemented the filter method in my ArrayAdapter class.
Here's my ArrayAdapter class:
MyArrayAdapter.java
public class MyArrayAdapter extends ArrayAdapter<MyDataModel> implements Filterable{
List<MyDataModel> modelList;
Context context;
private LayoutInflater mInflater;
private ArrayList<MyDataModel> arrayList;
public MyArrayAdapter(Context context, List<MyDataModel> objects) {
super(context, 0, objects);
this.context = context;
this.mInflater = LayoutInflater.from(context);
modelList = objects;
this.arrayList = new ArrayList<MyDataModel>();
this.arrayList.addAll(modelList);
}
#Override
public MyDataModel getItem(int position) {
return modelList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder vh;
if (convertView == null) {
View view = mInflater.inflate(R.layout.layout_row_view, parent, false);
vh = ViewHolder.create((RelativeLayout) view);
view.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
MyDataModel item = getItem(position);
vh.textViewName.setText(item.getName());
return vh.rootView;
}
private static class ViewHolder {
public final RelativeLayout rootView;
public final TextView textViewName;
private ViewHolder(RelativeLayout rootView, TextView textViewName) {
this.rootView = rootView;
this.textViewName = textViewName;
}
public static ViewHolder create(RelativeLayout rootView) {
TextView textViewName = (TextView) rootView.findViewById(R.id.textViewName);
return new ViewHolder(rootView, textViewName);
}
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
modelList.clear();
if (charText.length() == 0) {
modelList.addAll(arrayList);
} else {
for (MyDataModel wp : arrayList) {
if (wp.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
modelList.add(wp);
}
}
}
notifyDataSetChanged();
}
Try,
modelList = new ArrayList<MyDataModel>;
Write this line after modelList.clear(); and check.
Go with this link, and follow steps for implementing the same:
and the problem with buffer is called every textchanged listener will call everytime if you add or delete any character or space in it. So avoid using that. It will cause memory leak problems.

Categories

Resources