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) {
}
});
Related
When you click on the CardView, a DialogFragment should appear, but the application crashes, writes the following in the logs
Process: com.example.testfuntura, PID: 15385
java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to androidx.appcompat.app.AppCompatActivity
at com.example.testfuntura.Attraction.AdapterAttractionsPackageOffer.lambda$onBindViewHolder$0(AdapterAttractionsPackageOffer.java:56)
at com.example.testfuntura.Attraction.-$$Lambda$AdapterAttractionsPackageOffer$4cZEQxk2beWA40yZmNkr6ZJp7o8.onClick(lambda)
at android.view.View.performClick(View.java:5692)
at android.view.View$PerformClick.run(View.java:22596)
My Adapter
public class AdapterAttractionsPackageOffer extends RecyclerView.Adapter<AdapterAttractionsPackageOffer.AttractionsViewHolderPackageOffer> {
public ArrayList<ItemPOA> mFavList;
public AdapterAttractionsPackageOffer(ArrayList<ItemPOA> favList) {
mFavList = favList;
}
#NonNull
#Override
public AttractionsViewHolderPackageOffer onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_attraction_package_offer, parent, false);
return new AttractionsViewHolderPackageOffer(v);
}
public static class AttractionsViewHolderPackageOffer extends RecyclerView.ViewHolder {
public ImageView card_image_1;
public TextView Package_offer_title;
public CardView Card;
public AttractionsViewHolderPackageOffer(View itemView) {
super(itemView);
Card = itemView.findViewById(R.id.att_po);
card_image_1 = itemView.findViewById(R.id.img_po);
Package_offer_title = itemView.findViewById(R.id.tex);
}
}
#SuppressLint("LongLogTag")
#Override
public void onBindViewHolder(AttractionsViewHolderPackageOffer holder, int position) {
ItemPOA currentItem = mFavList.get(position);
holder.Package_offer_title.setText(currentItem.get_Package_offer_title());
holder.Card.setOnClickListener(v -> {
DialogPOA dialog = new DialogPOA();
dialog.show(((AppCompatActivity) v.getContext()).getSupportFragmentManager(), "item");
Bundle bundle1 = new Bundle();
bundle1.putString("title_po", currentItem.get_Package_offer_title());
bundle1.putString("description_po", currentItem.get_Package_offer_description());
bundle1.putString("cost_po", currentItem.get_Package_offer_cost());
dialog.setArguments(bundle1);
});
holder.getAdapterPosition();
}
#Override
public int getItemCount() {
return mFavList.size();
}
}
I have a similar Adapter, but when called, everything works, that is, the problem is not in the DialogFragment, since everything works when called from another fragment.
Fragment that the CardView is in
public class FragmentAtt extends Fragment {
ArrayList<ItemPOA> mFavList;
String URL = "http://qqqqqqqqq.mcdir.ru/dbpo.php";
RecyclerView mRec;
RecyclerView.LayoutManager recyclerViewlayoutManager;
RecyclerView.Adapter recyclerViewadapter;
//ImageView GET_PO_IMG;
String GET_PO_TITLE = "title_po";
String GET_PO_DESCRIPTION = "description_po";
String GET_PO_COST = "cost_po";
RequestQueue requestQueue;
JsonArrayRequest jsonArrayRequest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_test_attraction, container, false);
TabLayout tabLayout = view.findViewById(R.id.tab);
ViewPager viewPager = view.findViewById(R.id.pager);
setupViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
return view;
}
#Override
public void onViewCreated(#NonNull final View view, #Nullable Bundle savedInstanceState) {
mRec = requireView().findViewById(R.id.rec_po);
mFavList = new ArrayList<>();
recyclerViewadapter = new AdapterAttractionsPackageOffer(mFavList);
recyclerViewlayoutManager = new LinearLayoutManager(getContext());
mRec.setHasFixedSize(true);
mRec.setLayoutManager(recyclerViewlayoutManager);
mRec.setAdapter(recyclerViewadapter);
JSON_DATA_WEB_CALL2_RINK();
//recyclerViewlayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
//SnapHelper snapHelper = new GravitySnapHelper(Gravity.START);
//snapHelper.attachToRecyclerView(mRec);
}
private void setupViewPager(ViewPager viewPager) {
PagerAdapter adapter = new PagerAdapter(getChildFragmentManager());
adapter.addFragment(new FragmentAttractionRecyclerView(), "Аттракционы");
adapter.addFragment(new FragmentAttractionRecyclerView(), "Видеоигры");
viewPager.setAdapter(adapter);
}
public void JSON_DATA_WEB_CALL2_RINK() {
jsonArrayRequest = new JsonArrayRequest(URL,
this::JSON_PARSE_DATA_AFTER_WEBCALL_RINK,
error ->
Log.e("Volley", error.toString())) {
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
long now = System.currentTimeMillis();
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = now;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString), cacheEntry);
} catch (UnsupportedEncodingException | JSONException e) {
return Response.error(new ParseError(e));
}
}
};
requestQueue = Volley.newRequestQueue(requireContext());
requestQueue.add(jsonArrayRequest);
}
public void JSON_PARSE_DATA_AFTER_WEBCALL_RINK(JSONArray array) {
mFavList.clear();
for (int i = 0; i < array.length(); i++) {
ItemPOA GetDataAdapter2 = new ItemPOA();
JSONObject json;
try {
json = array.getJSONObject(i);
GetDataAdapter2.set_Package_offer_title(json.getString(GET_PO_TITLE));
GetDataAdapter2.set_Package_offer_description(json.getString(GET_PO_DESCRIPTION));
GetDataAdapter2.set_Package_offer_cost(json.getString(GET_PO_COST));
} catch (JSONException e) {
e.printStackTrace();
}
mFavList.add(GetDataAdapter2);
}
recyclerViewadapter = new AdapterAttractionsPackageOffer(mFavList);
mRec.setAdapter(recyclerViewadapter);
}
}
An Adapter that has the same functionality, but why does it work, explain the difference?
public class AdapterSkatingRinkSchedule_2 extends RecyclerView.Adapter<AdapterSkatingRinkSchedule_2.SkatingRinkScheduleViewHolder> {
public ArrayList<ItemSkatingRinkSchedule_2> mSkatingRinkScheduleList;
public AdapterSkatingRinkSchedule_2(ArrayList<ItemSkatingRinkSchedule_2> SkatingRinkScheduleList) {
mSkatingRinkScheduleList = SkatingRinkScheduleList;
}
#NonNull
#Override
public SkatingRinkScheduleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_srs, parent, false);
return new SkatingRinkScheduleViewHolder(v);
}
public static class SkatingRinkScheduleViewHolder extends RecyclerView.ViewHolder {
public TextView number_srs, start_time_srs, end_time_srs, cost_1_srs, cost_2_srs;
public LinearLayout ll_main;
public SkatingRinkScheduleViewHolder(View itemView) {
super(itemView);
ll_main = itemView.findViewById(R.id.ll_main);
number_srs = itemView.findViewById(R.id.number_srs);
start_time_srs = itemView.findViewById(R.id.start_time_srs);
end_time_srs = itemView.findViewById(R.id.end_time_srs);
cost_1_srs = itemView.findViewById(R.id.cost_1_srs);
cost_2_srs = itemView.findViewById(R.id.cost_2_srs);
}
}
#SuppressLint("LongLogTag")
#Override
public void onBindViewHolder(SkatingRinkScheduleViewHolder holder, int position) {
ItemSkatingRinkSchedule_2 currentItem = mSkatingRinkScheduleList.get(position);
holder.number_srs.setText(currentItem.get_session_number());
holder.start_time_srs.setText(currentItem.get_session_start());
holder.end_time_srs.setText(currentItem.get_session_end());
holder.cost_1_srs.setText(currentItem.get_weekdays());
holder.cost_2_srs.setText(currentItem.get_weekends_and_holidays());
holder.ll_main.setOnClickListener(v -> {
DialogSkatingRinkSchedule dialogSRS = new DialogSkatingRinkSchedule();
dialogSRS.show(((AppCompatActivity) v.getContext()).getSupportFragmentManager(), "item");
Bundle bundle2 = new Bundle();
bundle2.putString("number", currentItem.get_session_number());
bundle2.putString("start", currentItem.get_session_start());
bundle2.putString("end", currentItem.get_session_end());
bundle2.putString("w", currentItem.get_weekdays());
bundle2.putString("wah", currentItem.get_weekends_and_holidays());
dialogSRS.setArguments(bundle2);
});
holder.getAdapterPosition();
}
#Override
public int getItemCount() {
return mSkatingRinkScheduleList.size();
}
}
java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to androidx.appcompat.app.AppCompatActivity
Here you are casting a context to an AppCompatActivity but actually Activity is not a Context
You have two options to solve this:
First option: Create a listener interface between the activity/fragment that holds the RecyclerView, implement it in that activity, and trigger its callback within the CardView onClickListener onClick() callback.
Second option: Change the constructor signature of the AdapterAttractionsPackageOffer adapter to accept a FragmentManager instance; save it as a class field like below, and reflect that on the instantiation of the adapter
public class AdapterAttractionsPackageOffer extends RecyclerView.Adapter<AdapterAttractionsPackageOffer.AttractionsViewHolderPackageOffer> {
public ArrayList<ItemPOA> mFavList;
private FragmentManager fragmentMgr;
public AdapterAttractionsPackageOffer(ArrayList<ItemPOA> favList, FragmentManager fManger) {
mFavList = favList;
fragmentMgr = fManger;
}
//......... suppressed code
#SuppressLint("LongLogTag")
#Override
public void onBindViewHolder(AttractionsViewHolderPackageOffer holder, int position) {
ItemPOA currentItem = mFavList.get(position);
holder.Package_offer_title.setText(currentItem.get_Package_offer_title());
holder.Card.setOnClickListener(v -> {
DialogPOA dialog = new DialogPOA();
dialog.show(fragmentMgr, "item");
Bundle bundle1 = new Bundle();
bundle1.putString("title_po", currentItem.get_Package_offer_title());
bundle1.putString("description_po", currentItem.get_Package_offer_description());
bundle1.putString("cost_po", currentItem.get_Package_offer_cost());
dialog.setArguments(bundle1);
});
holder.getAdapterPosition();
}
//......... suppressed code
}
I have an application project for news media using java programming, I
want to display images for categories from drawable into recylerview
that are based on json-api, is there any one who can help me?
How I do for load image from drawable and combine it with data from json-api into RecylerView can anyone provide specific code here
this is my AdapterCategory.java
public class AdapterCategory extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Category> items = new ArrayList<>();
private Context ctx;
private OnItemClickListener mOnItemClickListener;
private int c;
public interface OnItemClickListener {
void onItemClick(View view, Category obj, int position);
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mOnItemClickListener = mItemClickListener;
}
// Provide a suitable constructor (depends on the kind of dataset)
public AdapterCategory(Context context, List<Category> items) {
this.items = items;
ctx = context;
}
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView name;
public TextView post_count;
public LinearLayout lyt_parent;
public ImageView imageView;
public ViewHolder(View v) {
super(v);
name = (TextView) v.findViewById(R.id.name);
post_count = (TextView) v.findViewById(R.id.post_count);
imageView = (ImageView)v.findViewById(R.id.image_category);
lyt_parent = (LinearLayout) v.findViewById(R.id.lyt_parent);
//imageView.setImageResource(image_array.length);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_category, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(holder instanceof ViewHolder) {
final Category c = items.get(position);
ViewHolder vItem = (ViewHolder) holder;
vItem.name.setText(Html.fromHtml(c.title));
vItem.post_count.setText(c.post_count + "");
Picasso.with(ctx).load(imageUri).into(vItem.imageView);
vItem.lyt_parent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view, c, position);
}
}
});
}
}
public void setListData(List<Category> items){
this.items = items;
notifyDataSetChanged();
}
public void resetListData() {
this.items = new ArrayList<>();
notifyDataSetChanged();
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return items.size();
}
}
This is my FragmentCategory.java for display data
public class FragmentCategory extends Fragment {
private View root_view, parent_view;
private RecyclerView recyclerView;
private SwipeRefreshLayout swipe_refresh;
private AdapterCategory mAdapter;
private Call<CallbackCategories> callbackCall = null;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root_view = inflater.inflate(R.layout.fragment_category, null);
parent_view = getActivity().findViewById(R.id.main_content);
swipe_refresh = (SwipeRefreshLayout) root_view.findViewById(R.id.swipe_refresh_layout_category);
recyclerView = (RecyclerView) root_view.findViewById(R.id.recyclerViewCategory);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),3));
recyclerView.setHasFixedSize(true);
//set data and list adapter
mAdapter = new AdapterCategory(getActivity(), new ArrayList<Category>());
recyclerView.setAdapter(mAdapter);
// on item list clicked
mAdapter.setOnItemClickListener(new AdapterCategory.OnItemClickListener() {
#Override
public void onItemClick(View v, Category obj, int position) {
ActivityCategoryDetails.navigate((ActivityMain) getActivity(), v.findViewById(R.id.lyt_parent), obj);
}
});
// on swipe list
swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mAdapter.resetListData();
requestAction();
}
});
requestAction();
return root_view;
}
private void displayApiResult(final List<Category> categories) {
mAdapter.setListData(categories);
swipeProgress(false);
if (categories.size() == 0) {
showNoItemView(true);
}
}
private void requestCategoriesApi() {
API api = RestAdapter.createAPI();
callbackCall = api.getAllCategories();
callbackCall.enqueue(new Callback<CallbackCategories>() {
#Override
public void onResponse(Call<CallbackCategories> call, Response<CallbackCategories> response) {
CallbackCategories resp = response.body();
if (resp != null && resp.status.equals("ok")) {
displayApiResult(resp.categories);
} else {
onFailRequest();
}
}
#Override
public void onFailure(Call<CallbackCategories> call, Throwable t) {
if (!call.isCanceled()) onFailRequest();
}
});
}
private void onFailRequest() {
swipeProgress(false);
if (NetworkCheck.isConnect(getActivity())) {
showFailedView(true, getString(R.string.failed_text));
} else {
showFailedView(true, getString(R.string.no_internet_text));
}
}
private void requestAction() {
showFailedView(false, "");
swipeProgress(true);
showNoItemView(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
requestCategoriesApi();
}
}, Constant.DELAY_TIME);
}
#Override
public void onDestroy() {
super.onDestroy();
swipeProgress(false);
if(callbackCall != null && callbackCall.isExecuted()){
callbackCall.cancel();
}
}
private void showFailedView(boolean flag, String message) {
View lyt_failed = (View) root_view.findViewById(R.id.lyt_failed_category);
((TextView) root_view.findViewById(R.id.failed_message)).setText(message);
if (flag) {
recyclerView.setVisibility(View.GONE);
lyt_failed.setVisibility(View.VISIBLE);
} else {
recyclerView.setVisibility(View.VISIBLE);
lyt_failed.setVisibility(View.GONE);
}
((Button) root_view.findViewById(R.id.failed_retry)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
requestAction();
}
});
}
private void showNoItemView(boolean show) {
View lyt_no_item = (View) root_view.findViewById(R.id.lyt_no_item_category);
((TextView) root_view.findViewById(R.id.no_item_message)).setText(R.string.no_category);
if (show) {
recyclerView.setVisibility(View.GONE);
lyt_no_item.setVisibility(View.VISIBLE);
} else {
recyclerView.setVisibility(View.VISIBLE);
lyt_no_item.setVisibility(View.GONE);
}
}
private void swipeProgress(final boolean show) {
if (!show) {
swipe_refresh.setRefreshing(show);
return;
}
swipe_refresh.post(new Runnable() {
#Override
public void run() {
swipe_refresh.setRefreshing(show);
}
});
}
And this is my ModeCategory.java
public class Category implements Serializable {
public int id = -1;
public String slug = "";
public String type = "";
public String url = "";
public String title = "";
public String title_plain = "";
public String content = "";
public String excerpt = "";
public String date = "";
public String modified = "";
public String description = "";
public int parent = -1;
public int post_count = -1;
public Author author;
public List<Category> categories = new ArrayList<>();
public List<Comment> comments = new ArrayList<>();
public List<Attachment> attachments = new ArrayList<>();
public CategoryRealm getObjectRealm(){
CategoryRealm c = new CategoryRealm();
c.id = id;
c.url = url;
c.slug = slug;
c.title = title;
c.description = description;
c.parent = parent;
c.post_count = post_count;
return c;
}
}
I am creating an app where a list of hotels will be shown, all the data is coming from MySQL using JSON and PHP, I created the custom list view by extending the base adapter to a custom one, but I am not able to implement a OnItemClickListener for the listview, as i want to show the Hotel Name of that row in Toast whenever the user clicks on a row of list view. I tried various example available on internet, but i just doesn't work.
Adapter
public class CustomListAdapterHotel extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<WorldsBillionaires> billionairesItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapterHotel(Activity activity, List<WorldsBillionaires> billionairesItems) {
this.activity = activity;
this.billionairesItems = billionairesItems;
}
#Override
public int getCount() {
return billionairesItems.size();
}
#Override
public Object getItem(int location) {
return billionairesItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_hotel, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
//NetworkImageView thumbNail = (NetworkImageView) convertView.findViewById(R.id.thumbnail);
TextView hotel_name = (TextView) convertView.findViewById(R.id.hotel_name);
TextView zone = (TextView) convertView.findViewById(R.id.zone);
TextView contact_person = (TextView) convertView.findViewById(R.id.contact_person);
TextView contact_number = (TextView) convertView.findViewById(R.id.contact_number);
TextView btc_direct = (TextView) convertView.findViewById(R.id.btcdirect);
// getting billionaires data for the row
WorldsBillionaires m = billionairesItems.get(position);
// name
hotel_name.setText(String.valueOf(m.getHotel_Name()));
zone.setText(String.valueOf(m.getHotel_Zone()));
contact_person.setText(String.valueOf(m.getContact_Person()));
contact_number.setText(String.valueOf(m.getContact_Number()));
btc_direct.setText(String.valueOf(m.getBtc_Direct()));
return convertView;
}
}
Model
public class WorldsBillionaires {
private String hotel_name,hotel_zone,contact_person,contact_number,btc_direct;
public WorldsBillionaires(String hotel_name, String hotel_zone, String contact_person, String contact_number, String btc_direct) {
this.hotel_name=hotel_name;
this.hotel_zone=hotel_zone;
this.contact_person=contact_person;
this.contact_number=contact_number;
this.btc_direct=btc_direct;
}
public WorldsBillionaires() {
}
public String getZone() {
return zone;
}
public void setZone(String zone) {
this.zone = zone;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public void setThumbnailUrl(String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}
public String getHotel_Name() {
return hotel_name;
}
public void setHotel_Name(String hotel_name) {
this.hotel_name = hotel_name;
}
public String getHotel_Zone() {
return hotel_zone;
}
public void setHotel_Zone(String hotel_zone) {
this.hotel_zone = hotel_zone;
}
public String getContact_Person() {
return contact_person;
}
public void setContact_Person(String contact_person) {
this.contact_person = contact_person;
}
public String getContact_Number() {
return contact_number;
}
public void setContact_Number(String contact_number) {
this.contact_number = contact_number;
}
public String getBtc_Direct() {
return btc_direct;
}
public void setBtc_Direct(String btc_direct) {
this.btc_direct = btc_direct;
}
}
Main Activity
public class ShowHotel extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
// Billionaires json url
private ProgressDialog pDialog;
private List<WorldsBillionaires> worldsBillionairesList = new ArrayList<WorldsBillionaires>();
private ListView listView;
private CustomListAdapterHotel adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_hotel);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
listView = (ListView) findViewById(R.id.list);
adapter = new CustomListAdapterHotel(this, worldsBillionairesList);
listView.setAdapter(adapter);
pDialog = new ProgressDialog(this);
// Showing progress dialog before making http request
pDialog.setMessage("Loading...");
pDialog.show();
// Creating volley request obj
JsonArrayRequest billionaireReq = new JsonArrayRequest("http://192.168.247.1/AdminBihar/getHotel.php?zone="+methods.zone,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
WorldsBillionaires worldsBillionaires = new WorldsBillionaires();
worldsBillionaires.setHotel_Name(obj.getString("hotel_name"));
worldsBillionaires.setThumbnailUrl(obj.getString("image"));
worldsBillionaires.setHotel_Zone(obj.getString("zone"));
worldsBillionaires.setContact_Person(obj.getString("contact_person"));
worldsBillionaires.setContact_Number(obj.getString("contact_number"));
worldsBillionaires.setBtc_Direct(obj.getString("btc_direct"));
// adding Billionaire to worldsBillionaires array
worldsBillionairesList.add(worldsBillionaires);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(billionaireReq);
}
#Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
}
so after you get json data, in activity that shows your list do something like this:
public class DisplayListView extends AppCompatActivity {
ListView listView;
protected void onCreate(){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_list_view);
listView = (ListView) findViewById(R.id.listview);
hotelAdapter = new CustomListAdapterHotel (this, R.layout.row_layout);
listView.setAdapter(hotelAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Model stuff = (Model) hotelAdapter.getItem(position);
String hotelName = stuff.getHotel_Name();
Toast.makeText(getApplicationContext(), hotelName, Toast.LENGTH_SHORT).show();
}
});
there, this worked for me :)
I have a question about passing clicked cardview data to activity, and here the full story :
I have an Activity called "Details", which contains 2 TextViews in it's layout, Title & Description .
I have setup a fragment ( tab_1 ) which contain the recyclerview codes and the the items data, each item of those contain : title & description .
What i want :
When the user click the item, it will open the Details Activity, and change Details layout title, with clicked item title, and the same for description .
I've manged to create the other activity as an example, and made intent to start it, plus adding "addOnTouchlistener" thanks to Stackoverflow, i've found the way to make it .
So, how to make this alive? I've tried many ways of the available answers on Stackoverflow, but all of them not working, or not related to my request .
Here are my files :
itemsdata.java :
public class itemsdata {
int CatPic;
String title;
String Descr;
int Exapnd;
int expand_no;
tab_1.java ( fragment )
public class tab_1 extends Fragment implements SearchView.OnQueryTextListener {
private RecyclerView mRecyclerView;
public RecyclingViewAdapter adapter;
private Activity context;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.tab_1, container, false);
mRecyclerView = (RecyclerView)layout.findViewById(R.id.recycler_view);
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener
(getContext(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent i = new Intent(view.getContext(), DetailsActivity.class);
view.getContext().startActivity(i);
}
}));
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new RecyclingViewAdapter(getActivity(),Listed());
mRecyclerView.setAdapter(adapter);
return layout;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onQueryTextChange(String query) {
final List<itemsdata> filteredModelList = filter(Listed(), query);
adapter.animateTo(filteredModelList);
mRecyclerView.scrollToPosition(0);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
private List<itemsdata> filter(List<itemsdata> models, String query) {
query = query.toLowerCase();
final List<itemsdata> filteredModelList = new ArrayList<>();
for (itemsdata model : models) {
final String text = model.title.toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
public List<itemsdata> Listed()
{
//Titles Strings
String sys_title1 = getString(R.string.system_item_title_1);
String sys_title2 = getString(R.string.system_item_title_2);
String sys_title3 = getString(R.string.system_item_title_3);
//Description Strings
String sys_descr1 = getString(R.string.system_item_desc_1);
String sys_descr2 = getString(R.string.system_item_desc_2);
String sys_descr3 = getString(R.string.system_item_desc_3);
//Adding New Cards
List<itemsdata> data = new ArrayList<>();
//Categories Icons New Items ** Make It The Same
int[] icons = {
R.drawable.facebook_icon ,
R.drawable.twitter_icon ,
R.drawable.twitter_icon
};
//Expand Button New Items
int[] expandbutton = {
R.drawable.expanded ,
R.drawable.expanded ,
R.drawable.expanded
};
//UnExpand Button New Items
int[] unexpandbutton = {
R.drawable.ca_expand ,
R.drawable.ca_expand ,
R.drawable.ca_expand
};
//Titles New Items
String[] titles = {
sys_title1 ,
sys_title2 ,
sys_title3
};
//Description New Items
String[] Description = {
sys_descr1 ,
sys_descr2 ,
sys_descr3
};
for(int i = 0;i<titles.length && i < icons.length && i < Description.length && i < unexpandbutton.length && i < expandbutton.length ; i++)
{
itemsdata current = new itemsdata();
current.CatPic = icons[i];
current.title = titles[i];
current.Descr = Description[i];
current.expand_no = unexpandbutton[i];
current.Exapnd = expandbutton[i];
data.add(current);
}
return data;
}
}
Details Activity :
public class DetailsActivity extends AppCompatActivity{
TextView title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
title = (TextView)findViewById(R.id.details_title);
}
EDIT : I've made it, i have added a button which open the fragment, and passed the data, in the Adapter, but i want it via tab_1.java, not the Adapter, i mean i want to click on the item to open the fragment, not on a button, here a snap from my Adapter code ( i've added it in OnBindViewHolder )
I've setup a OnClick and implemented the Vew.setOnClick ..etc, but when i click the item, nothing happen.
#Override
public void onBindViewHolder(final MyRecycleViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(),DetailsActivity.class);
v.getContext().startActivity(i);
}
});
//Referencing Data
final itemsdata currentobject = mdata.get(position);
//Referencing Items
holder.ProbTitle.setText(currentobject.title);
holder.ProbDescr.setText(currentobject.Descr);
holder.CategoryPic.setImageResource(currentobject.CatPic);
holder.ExpandButton.setImageResource(currentobject.Exapnd);
holder.ExpandNoButton.setImageResource(currentobject.expand_no);
//What Happen When You Click Expand Button .
holder.ExpandButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(), DetailsActivity.class);
i.putExtra("TitleKey",holder.ProbTitle.getText().toString());
v.getContext().startActivity(i);
}
}
);
public static class MyRecycleViewHolder extends RecyclerView.ViewHolder
{
SwipeLayout swipeLayout;
//Defining Items .
TextView ProbTitle;
ImageButton ExpandButton;
TextView ProbDescr;
ImageButton ExpandNoButton;
ImageView CategoryPic;
/*
TextView Card_Star;
TextView Card_UnStar;
*/
TextView Card_Share;
//Referencing Resources
public MyRecycleViewHolder(final View itemView) {
super(itemView);
ProbTitle = (TextView) itemView.findViewById(R.id.prob_title);
CategoryPic = (ImageView) itemView.findViewById(R.id.cat_pic);
ProbDescr = (TextView) itemView.findViewById(R.id.prob_descr);
ExpandButton = (ImageButton) itemView.findViewById(R.id.expand_button);
ExpandNoButton = (ImageButton) itemView.findViewById(R.id.expand_no_button);
/*
Card_Star = (TextView) itemView.findViewById(R.id.card_star);
Card_UnStar = (TextView) itemView.findViewById(R.id.card_unstar);
*/
Card_Share = (TextView) itemView.findViewById(R.id.card_share);
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
}
create an Interface inside your adapter containing methods. And while implementing your Adapter, those methods will be implemented in your activity and you can perform whatever action you want.
public class Adapter extends RecyclerView.Adapter<MyRecycleViewHolder> {
public interface Callbacks {
public void onButtonClicked(String titleKey);
}
private Callbacks mCallbacks;
public Adapter() {
}
#Override
public MyRecycleViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_details, null);
return new MyRecycleViewHolder(v);
}
#Override
public void onBindViewHolder(final MyRecycleViewHolder holder, final int i) {
holder.ExpandButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCallbacks != null) {
mCallbacks.onButtonClicked(holder.ProbTitle.getText().toString());
}
}
});
}
#Override
public int getItemCount() {
return;
}
public void setCallbacks(Callbacks callbacks) {
this.mCallbacks = callbacks;
}
}
you may try do this on your onItemClick()
Intent i = new Intent(view.getContext(), DetailsActivity.class);
i.putExtra("title", yourTitle);
i.putExtra("description", yourDescription);
view.getContext().startActivity(i);
and when oncreate in your DetailActivity,do this
String title = getIntent().getStringExtra("title");
String description = getIntent().getStringExtra("description");
so you can pass title and description to DetailActivity
IMO, you implement setOnClickListener inside Adapter of RecyclerView. You can refer to my following sample code, then apply its logic to your code. Hope it helps!
public class MyRVAdapter extends RecyclerView.Adapter<MyRVAdapter.ViewHolder> {
Context mContext;
List<String> mStringList;
public MyRVAdapter(Context mContext, List<String> mStringList) {
this.mContext = mContext;
this.mStringList = mStringList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (TextView) v.findViewById(R.id.textView2);
Bundle bundle = new Bundle();
bundle.putString("key1", textView1.getText().toString());
bundle.putString("key2", textView2.getText().toString());
passToAnotherActivity(bundle);
}
});
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// do something...
}
#Override
public int getItemCount() {
if (mStringList != null) {
return mStringList.size();
}
return 0;
}
private void passToAnotherActivity(Bundle bundle) {
if (mContext == null)
return;
if (mContext instanceof MainActivity) {
MainActivity activity = (MainActivity) mContext;
activity.passToAnotherActivity(bundle); // this method must be implemented inside `MainActivity`
}
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View itemView) {
super(itemView);
// do something...
}
#Override
public void onClick(View v) {
}
}
}
First of all make your "itemsdata" object to implement Parcelable. You can check it here . In your onItemClick method you pass the object to your Details activity using intent.putExtra("key",listOfDataItems.get(position));
In your DetailsActivity you can get your custom object with getParcelable("key")
All above methods worked, but kinda long, so this one worked for me :
Cardview cardview;
cardView = (CardView)itemView.findViewById(R.id.cv);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent (view.getContext(), DetailsActivity.class);
i.putExtra("TitleKey",ProbTitle.getText().toString());
i.putExtra("DescrKey",ProbDescr.getText().toString());
view.getContext().startActivity(i);
}
});
And in Details.java :
TextView title;
TextView Descr;
title = (TextView)findViewById(R.id.details_title);
Descr = (TextView)findViewById(R.id.details_descr);
String titleresult = result.getExtras().getString("TitleKey");
String Descrresult = result.getExtras().getString("DescrKey");
title.setText(titleresult);
Descr.setText(Descrresult);
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" />