Related
I am developing Android app which obtains information about restaurants from server and shows them in RecyclerView. When first package of information is obtained from server, everything works as expected, but, when I change search criteria and request new package of information from server, RecyclerView becomes blank. I used Toasts to debug what is coming from server and I am convinced that data is properly formatted. Also, variables that are used for accepting the data are also properly handled in code, according to my observations. Do you maybe know why my RecyclerView is empty when second package of data should be shown? Here is the code.
AfterLoginActivity.java
public class AfterLoginActivity extends AppCompatActivity {
/* interface main elements */
LinearLayout afterLoginLayout;
LinearLayout restaurantListLayout;
EditText restaurantEditText;
Button findRestaurantButton;
LoadingDialog loadingDialog;
AlphaAnimation loadingAnimation;
RecyclerView restaurantsRecyclerView;
int recycler_set = 0;
Button signOutButton;
GoogleSignInClient mGoogleSignInClient;
MyAdapter myAdapter = null;
/* server-client communication data */
public static String UploadUrl = "https://gdedakliknem.com/klopator.php";
public static String[] received;
String restaurants[] = new String[40];
String logos_as_strings[] = new String[40];
Bitmap logos[] = new Bitmap[40];
int num_of_elements = 0;
int data_received = 0;
/* user data */
String person_email;
String person_name;
String restaurant;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_after_login);
/* interface main elements */
afterLoginLayout = findViewById(R.id.afterLoginLayout);
restaurantListLayout = findViewById(R.id.restaurantListLayout);
restaurantEditText = findViewById(R.id.restaurantEditText);
findRestaurantButton = findViewById(R.id.findRestaurantButton);
restaurantsRecyclerView = findViewById(R.id.restaurantsRecyclerView);
signOutButton = findViewById(R.id.signOutButton);
loadingAnimation = new AlphaAnimation(1F, 0.8F);
loadingDialog = new LoadingDialog(AfterLoginActivity.this);
/* UPDATING INTERFACE ELEMENTS */
/* execution thread */
final Handler handler = new Handler();
final int delay = 2000; // 1000 milliseconds == 1 second
handler.postDelayed(new Runnable() {
public void run() {
/* check if recycler view is set */
if(recycler_set == 0){
/* if not, check if there is data to fil it with */
if(data_received == 1){
/* convert received strings to images */
for(int i = 0; i < num_of_elements; i++){
logos[i] = stringToBitmap(logos_as_strings[i]);
}
/* fill interface elements */
loadingDialog.dismissDialog();
myAdapter = new MyAdapter(AfterLoginActivity.this, restaurants, logos, num_of_elements);
restaurantsRecyclerView.setAdapter(myAdapter);
restaurantsRecyclerView.setLayoutManager(new LinearLayoutManager(AfterLoginActivity.this));
afterLoginLayout.setVisibility(View.GONE);
restaurantListLayout.setVisibility(View.VISIBLE);
recycler_set = 1;
}
}
handler.postDelayed(this, delay);
}
}, delay);
/* catch restaurant name from user's entry */
findRestaurantButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
restaurant = restaurantEditText.getText().toString();
if(!restaurant.isEmpty()){
view.startAnimation(loadingAnimation);
loadingDialog.startLoadingDialog();
sendRequest();
} else{
Toast.makeText(AfterLoginActivity.this, "Unesite naziv restorana!", Toast.LENGTH_LONG).show();
}
}
});
/* enable signing out */
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
signOutButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.signOutButton:
signOut();
break;
}
}
});
/* obtaining email */
GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(this);
if (acct != null) {
person_email = acct.getEmail();
person_name = acct.getDisplayName();
}
}
#Override
public void onBackPressed() {
afterLoginLayout.setVisibility(View.VISIBLE);
restaurantsRecyclerView.setVisibility(View.GONE);
data_received = 0;
recycler_set = 0;
}
private void signOut() {
mGoogleSignInClient.signOut()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(AfterLoginActivity.this, "Signed out", Toast.LENGTH_LONG).show();
finish();
}
});
}
public void sendRequest(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, UploadUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String Response = jsonObject.getString("response");
if (Response.equals("Restaurant not found")){
loadingDialog.dismissDialog();
Toast.makeText(getApplicationContext(), "Uneti restoran ne postoji u sistemu! Proverite da li ste dobro napisali naziv", Toast.LENGTH_LONG).show();
} else{
received = Response.split(";");
if (received.length > 0){
data_received = 1;
num_of_elements = received.length / 2;
//Toast.makeText(getApplicationContext(), "num of elements: " + num_of_elements, Toast.LENGTH_LONG).show();
for(int i = 0; i < num_of_elements; i++){
logos_as_strings[i] = received[i*2];
restaurants[i] = received[i*2+1];
//Toast.makeText(getApplicationContext(), "restaurants: " + restaurants, Toast.LENGTH_LONG).show();
}
} else{
loadingDialog.dismissDialog();
Toast.makeText(getApplicationContext(), "Greška u prijemu", Toast.LENGTH_LONG).show();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(final VolleyError error) {
//volleyError = error;
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
//Toast.makeText(getApplicationContext(), "get params", Toast.LENGTH_LONG).show();
Map<String, String> params = new HashMap<>();
params.put("control", "find_restaurant");
params.put("restaurant", restaurant);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(AfterLoginActivity.this);
requestQueue.add(stringRequest);
}
public static Bitmap stringToBitmap(String encodedString) {
try {
byte[] encodeByte = Base64.decode(encodedString, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
} catch (Exception e) {
e.getMessage();
return null;
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
String restaurants[];
Bitmap logos[];
Context context;
int num_of_elements;
public MyAdapter(Context ct, String rests[], Bitmap lgs[], int num){
context = ct;
restaurants = rests;
logos = lgs;
num_of_elements = num;
Toast.makeText(context, Integer.toString(restaurants.length), Toast.LENGTH_LONG).show();
for(int i = 0; i < restaurants.length; i++){
Toast.makeText(context, restaurants[i], Toast.LENGTH_SHORT).show();
}
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.restaurant_item_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int position) {
holder.restaurantNameTextView.setText(restaurants[position]);
holder.restaurantLogoImageView.setImageBitmap(logos[position]);
holder.restaurantItemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, AfterPickingRestaurantActivity.class);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
logos[position].compress(Bitmap.CompressFormat.PNG, 50, bs);
intent.putExtra("byteArray", bs.toByteArray());
intent.putExtra("picked_restaurant_name", restaurants[position]);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
/*
int i = 0;
if (restaurants != null){
while(restaurants[i] != null){
i++;
}
} else{
i = restaurants.length;
}
return i;
*/
return num_of_elements;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView restaurantNameTextView;
ImageView restaurantLogoImageView;
LinearLayout restaurantItemLayout;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
restaurantNameTextView = itemView.findViewById(R.id.restaurantNameTextView);
restaurantLogoImageView = itemView.findViewById(R.id.restaurantLogoImageView);
restaurantItemLayout = itemView.findViewById(R.id.restaurantItemLayout);
}
}
Add this lines after getting new data
myAdapter.notifyDataSetChanged()
Your Adapter Already set with RecyclerView in OnCreate Method.
so when'er you click on findRestaurantButton you just get Resturent data from server but collected data not pass in adapter so thats why to getting blank adapter..
Just put this line in your onResponse after set data in array..
myAdapter.notifyDataSetChanged()
I found out where is the mistake. If you take a look at the section where overriding of back button click is happening, I by mistake set to GONE recyclerView itself:
restaurantsRecyclerView.setVisibility(View.GONE);
instead of LinearLayout in which recyclerView is contained. Desired action was:
restaurantListLayout.setVisibility(View.GONE);
P.S. Everything works without calling notifyDataSetChanged(), I just create a new instance of myAdapater each time when I receive new data. I hope Garbage Collector is doing its job :)
Thanks everyone on help!
I already knew how the RecyclerView with different types of view works but this time I'm trying to add the Native Advance Admob ads to my RecyclerView. I followed theseYoutube Tutorials but there was an error printed to my logcat after the app crushed.
Logcat
java.lang.ClassCastException: com.google.android.gms.internal.ads.zzaeh cannot be cast to mgb.com.sdalyricsplus.Database.Entities.SongsEntity
at mgb.com.sdalyricsplus.newAdapters.DisplayItemAdapter.onBindViewHolder(DisplayItemAdapter.java:98)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
I reviewed the tutorial many times hoping that I've missed something that causes the error but it seems that I followed the tutorial correctly.
Here are my Codes
DisplayItemActivity
public class DisplayItemActivity extends AppCompatActivity{
public static final int NUMBER_OF_AD = 5;
AdLoader adLoader;
FastScrollRecyclerView recyclerView;
Global global;
RoomViewModel model;
List<Object> recyclerViewItems = new ArrayList<>();
List<UnifiedNativeAd> nativeAds = new ArrayList<>();
DisplayItemAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_songs);
MobileAds.initialize(this,"ca-app-pub-2493911630710964~1147957926");
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
global = (Global)getApplication();
model = ViewModelProviders.of(this).get(RoomViewModel.class);
adapter = new DisplayItemAdapter(getLayoutInflater());
recyclerView.setAdapter(adapter);
recyclerViewItems.addAll(model.selectAll());
loadNativeAds();
}
private void loadNativeAds() {
AdLoader.Builder builder = new AdLoader.Builder(this, getResources().getString(R.string.native_advance));
adLoader = builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
nativeAds.add(unifiedNativeAd);
if (!adLoader.isLoading()) {
insertAdToList();
}
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
if (!adLoader.isLoading()) {
insertAdToList();
}
}
}).build();
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_AD);
}
private void insertAdToList() {
int offset = recyclerViewItems.size() / (nativeAds.size() + 1);
int index = 0;
for (UnifiedNativeAd ad : nativeAds) {
recyclerViewItems.add(index,ad);
index = index + offset;
}
adapter.setList(recyclerViewItems);
}
}
And my Adapter
DisplayItemAdapter
public class DisplayItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int MENU_ITEM_VIEW_TYPE = 0;
private final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
private List<Object> recyclerViewItems = new ArrayList<>();
private Global global;
private String searchTxt = "";
private final String newline = System.getProperty("line.separator");
private ClickSongItemListener clickSongItemListener;
private ChangeFavoriteListener changeFavoriteListener;
private LayoutInflater layoutInflater;
public DisplayItemAdapter(LayoutInflater layoutInflater) {
this.layoutInflater = layoutInflater;
}
public void setList(List<Object> list) {
this.recyclerViewItems = list;
notifyDataSetChanged();
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
global = (Global) ((Activity)parent.getContext()).getApplication();
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
View adView = LayoutInflater.from(parent.getContext()).inflate(R.layout.native_ad_view,parent,false);
return new UnifiedNativeAdViewHolder(adView);
case MENU_ITEM_VIEW_TYPE :
default:
View songitem = LayoutInflater.from(parent.getContext()).inflate(R.layout.gospel_song_item,parent,false);
return new SongItemViewHolder(songitem);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE :
UnifiedNativeAdViewHolder nativeAdViewHolder = (UnifiedNativeAdViewHolder)holder;
UnifiedNativeAd unifiedNativeAd = (UnifiedNativeAd) recyclerViewItems.get(position);
// poulateNativeAdView(unifiedNativeAd,((UnifiedNativeAdViewHolder)holder).getAdView());
FrameLayout frameLayout =
nativeAdViewHolder.view.findViewById(R.id.ad_frame_placement);
UnifiedNativeAdView adView = (UnifiedNativeAdView) layoutInflater
.inflate(R.layout.ad_unified, null);
populateUnifiedNativeAdView(unifiedNativeAd, adView);
frameLayout.removeAllViews();
frameLayout.addView(adView);
break;
case MENU_ITEM_VIEW_TYPE :
default:
SongItemViewHolder songItemViewHolder = (SongItemViewHolder)holder;
setSongViews(songItemViewHolder, (SongsEntity)recyclerViewItems.get(position));
}
}
private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView) {
// Set the media view.
adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));
// Set other ad assets.
adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
adView.setBodyView(adView.findViewById(R.id.ad_body));
adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
adView.setIconView(adView.findViewById(R.id.ad_app_icon));
adView.setPriceView(adView.findViewById(R.id.ad_price));
adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
adView.setStoreView(adView.findViewById(R.id.ad_store));
adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
// The headline and mediaContent are guaranteed to be in every UnifiedNativeAd.
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
adView.getMediaView().setMediaContent(nativeAd.getMediaContent());
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
if (nativeAd.getBody() == null) {
adView.getBodyView().setVisibility(View.INVISIBLE);
} else {
adView.getBodyView().setVisibility(View.VISIBLE);
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
}
if (nativeAd.getCallToAction() == null) {
adView.getCallToActionView().setVisibility(View.INVISIBLE);
} else {
adView.getCallToActionView().setVisibility(View.VISIBLE);
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
}
if (nativeAd.getIcon() == null) {
adView.getIconView().setVisibility(View.GONE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(
nativeAd.getIcon().getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// This method tells the Google Mobile Ads SDK that you have finished populating your
// native ad view with this native ad.
adView.setNativeAd(nativeAd);
// Get the video controller for the ad. One will always be provided, even if the ad doesn't
// have a video asset.
VideoController vc = nativeAd.getVideoController();
// Updates the UI to say whether or not this ad has a video asset.
if (vc.hasVideoContent()) {
// videoStatus.setText(String.format(Locale.getDefault(),
// "Video status: Ad contains a %.2f:1 video asset.",
// vc.getAspectRatio()));
// Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
// VideoController will call methods on this object when events occur in the video
// lifecycle.
vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() {
#Override
public void onVideoEnd() {
// Publishers should allow native ads to complete video playback before
// refreshing or replacing them with another ad in the same UI location.
super.onVideoEnd();
}
});
} else {
}
}
private void setSongViews(SongItemViewHolder viewHolder, SongsEntity note) {
Context context = viewHolder.itemView.getContext();
if (note.getMedia_extension().equals("audio")) {
Glide.with(context)
.load(R.drawable.music_icon)
.thumbnail(00.1f)
.into(viewHolder.iv_thumbnail);
}else if (note.getGenre().toLowerCase().contains("karaoke")) {
File file = new File(context.getExternalFilesDir(null)+"/.file"+note.getId());
if (file.exists()) {
Glide.with(context)
.setDefaultRequestOptions(new RequestOptions().placeholder(R.drawable.karaoke_icon))
.load(file)
.thumbnail(00.1f)
.into(viewHolder.iv_thumbnail);
}else {
Glide.with(context)
.setDefaultRequestOptions(new RequestOptions().placeholder(R.drawable.karaoke_icon))
.load(note.getMedia_url())
.thumbnail(00.1f)
.into(viewHolder.iv_thumbnail);
}
}else {
Glide.with(context)
.load(R.drawable.lyrics_icon)
.thumbnail(00.1f)
.into(viewHolder.iv_thumbnail);
}
viewHolder.title.setText(global.capitalize(note.getTitle()));
viewHolder.artist.setText(global.capitalize(note.getArtist()));
viewHolder.category.setText(note.getGenre());
viewHolder.favorite.setOnCheckedChangeListener(null);
viewHolder.favorite.setChecked(note.getFavorites());
viewHolder.views.setText(note.getFavorite_counter() <2 ? note.getFavorite_counter()+" heart" : note.getFavorite_counter()+" hearts");
String MY_ID = "JUntYdabhUh5XtMhfCIXXwNbsdW2";
if (!note.getUploader_id().equals(MY_ID))
Glide.with(context)
.setDefaultRequestOptions(new RequestOptions().placeholder(R.mipmap.sda_logo).diskCacheStrategy(DiskCacheStrategy.ALL))
.load(note.getUploader_photo_url())
.into(viewHolder.user_logo);
else
Glide.with(context)
.load(R.mipmap.sda_logo)
.into(viewHolder.user_logo);
String lyrics = note.getLyrics().toLowerCase();
String searchFilter = searchTxt.toLowerCase();
if (searchTxt.isEmpty()) {
viewHolder.phrase_end.setText(note.getLyrics());
viewHolder.phrase.setText("");
} else
if (lyrics.contains(searchFilter) && (lyrics.indexOf(searchFilter)) + searchTxt.length() <= lyrics.length()) {
viewHolder.phrase.setText(searchTxt);
String filter = note.getLyrics().substring(lyrics.indexOf(searchFilter) + searchFilter.length());
assert newline != null;
viewHolder.phrase_end.setText(filter.replaceAll(newline, " "));
}else {
viewHolder.phrase_end.setText(note.getLyrics());
viewHolder.phrase.setText("");
}
viewHolder.favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (changeFavoriteListener != null) {
changeFavoriteListener.onChange(buttonView.getContext(),note,isChecked);
}
}
});
}
private void poulateNativeAdView(UnifiedNativeAd unifiedNativeAd, UnifiedNativeAdView adView) {
((TextView)adView.getHeadlineView()).setText(unifiedNativeAd.getHeadline());
((TextView)adView.getBodyView()).setText(unifiedNativeAd.getBody());
((TextView)adView.getCallToActionView()).setText(unifiedNativeAd.getCallToAction());
NativeAd.Image icon = unifiedNativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
}else {
((ImageView)adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (unifiedNativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
}else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView)adView.getPriceView()).setText(unifiedNativeAd.getPrice());
}
if (unifiedNativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
}else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView)adView.getStoreView()).setText(unifiedNativeAd.getStore());
}
if (unifiedNativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
}else {
adView.getStarRatingView().setVisibility(View.VISIBLE);
((RatingBar)adView.getStarRatingView()).setRating(unifiedNativeAd.getStarRating().floatValue());
}
if (unifiedNativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
}else {
adView.getAdvertiserView().setVisibility(View.VISIBLE);
((TextView)adView.getAdvertiserView()).setText(unifiedNativeAd.getAdvertiser());
}
adView.setNativeAd(unifiedNativeAd);
}
#Override
public int getItemCount() {
return recyclerViewItems.size();
}
public class SongItemViewHolder extends RecyclerView.ViewHolder {
TextView title, phrase,phrase_end;
TextView artist;
TextView category;
ToggleButton favorite;
LinearLayout layoutWrapper;
LinearLayout phrase_layout;
TextView views;
CircleImageView user_logo;
ImageView iv_thumbnail;
public SongItemViewHolder(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.text_view_title);
iv_thumbnail = itemView.findViewById(R.id.iv_thumbnail);
artist = itemView.findViewById(R.id.text_view_artist);
phrase = itemView.findViewById(R.id.phrase);
phrase_end = itemView.findViewById(R.id.phrase_end);
category = itemView.findViewById(R.id.text_view_category);
favorite = itemView.findViewById(R.id.toggleButton_favorite);
layoutWrapper = itemView.findViewById(R.id.layout_wrapper);
phrase_layout = itemView.findViewById(R.id.phrase_layout);
views = itemView.findViewById(R.id.tv_view_status);
user_logo = itemView.findViewById(R.id.user_logo);
}
}
private class UnifiedNativeAdViewHolder extends RecyclerView.ViewHolder {
private View view;
public UnifiedNativeAdViewHolder(View view) {
super(view);
this.view = view;
}
}
}
the logcat says that com.google.android.gms.internal.ads.zzaeh cannot be cast to mgb.com.sdalyricsplus.Database.Entities.SongsEntity and the error was pointed to the viewbindholder
case MENU_ITEM_VIEW_TYPE :
default:
SongItemViewHolder songItemViewHolder = (SongItemViewHolder)holder;
setSongViews(songItemViewHolder, (SongsEntity)recyclerViewItems.get(position)); // this line
my suspect is the viewtype. Maybe the view type was not correctly assigned.
I tried this code also but the error still there.
#Override
public int getItemViewType(int position) {
if (position % DisplayItemActivity.NUMBER_OF_AD == 0) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}else {
return MENU_ITEM_VIEW_TYPE;
}
}
can someone help me to find the cause of the error?
You need to merge your SongItem and UnifiedNativeAd to become 1 single data source.
Make a new object class name SongAdsData to merge your Song object and Ads from Admob into 1 single object like below:
public class SongAdsData {
public int getType() {
return type;
}
public UnifiedNativeAd getAds() {
return ads;
}
public Post getSong() {
return Song;
}
public int type; // 1 is ads and 2 is songs
public UnifiedNativeAd ads;
public Song song; // here is ur Song object as usual
}
In your adapter, modify it as below:
public class SongAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int UNIFIED_ADS_VIEW = 1;
private static final int SONG_ITEM_VIEW = 2;
private List<SongAdsData> songAdsDataList;
//here your onBindViewHolder,here your refer to item of `songAdsDataList`
// here your onCreateViewHolder
public void setSongAdsDataList(List<SongAdsData> songAdsDataForRecyclerView) {
this.songAdsDataList = songAdsDataForRecyclerView;
notifyDataSetChanged();
}
// Here is the function that insert the ads to RecyclerView
public void insertAdToRecyclerView(List<UnifiedNativeAds> nativeAds) {
int offset = songAdsDataList.size() / (nativeAds.size() + 1);
int index = 0;
for (UnifiedNativeAd ad : nativeAds) {
SongAdsData adsData = new SongAdsData();
adsData.song = null;
adsData.ads = ad;
adsData.type = 1; //1 for ads,2 for song
songAdsDataList.add(index,adsData);
index = index + offset;
}
notifyDataSetChanged();
}
#Override
public int getItemViewType (int position) {
if(songAdsDataList.get(position).getType() == 1){ // So here you compare the type of the object it the position
return UNIFIED_ADS;
}else{
return SONG_ITEM_VIEW;
}
}
#Override
public int getItemCount() {
if(songAdsDataList != null){
return songAdsDataList.size();
}else{
return 0;
}
}
}
So finally in your DisplayItemActivity
I not sure how you get your SongItem(your data from server or somewhere else),but the idea is transform your SongItem into SongAdsData that we created in the step one,
Example like this:
private void displaySongFromYourServer(List<Songs> songs) {
List<SongAdsData> songAdsDataList = new ArrayList<>();
for(Songs song : songs){
SongAdsData data = new SongAdsData();
data.ads = null;
data.song = song;
data.type = 2;
songAdsDataList.add(data);
}
songAdapter.setSongAdsDataList(songAdsDataList);
}
So by now,your Song item will become SongAdsData. At the same time, your UnifiedNativeAd object also need to transform become SongAdsData, therefore we need to
move all thing inside insertAdToList into SongAdapter(See the insertAdToRecyclerView in Song adapter above),so the it can refer to the same List of the recyclerView.
Therefore in your insertAdToList of DisplayItemActivity should become like this:
private void insertAdToList() {
songAdapter.insertAdsToRecyclerView(nativeAds); //called to the function inside songAdapter.
}
Hope you get the idea.
You need to override getItemViewType(int position) to check the instance of your Object in order to return the right view type:
#Override
public int getItemViewType(int position) {
if (this.recyclerViewItems.get(position) instanceof UnifiedNativeAd) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}else {
return MENU_ITEM_VIEW_TYPE;
}
}
So I have two classes. I'm trying to send integer data from one class to the other with a get method (getInputTime). The variable I'm returning inside the get method has a value. But when I use the get method inside of the other class called TimeActivity it just returns 0.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private static final String TAG = "CustomAdapter";
private ArrayList<Integer> mWorkTW = new ArrayList<>();
private ArrayList<Integer> mWorkET = new ArrayList<>();
private ArrayList<Integer> mRestTW = new ArrayList<>();
private ArrayList<Integer> mRestET = new ArrayList<>();
private Context mContext;
private int numberOfIntervals;
public CustomAdapter() {
}
public CustomAdapter(Context context, ArrayList<Integer> mWorkTW, ArrayList<Integer> mWorkET, ArrayList<Integer> mRestTW, ArrayList<Integer> mRestET, int numberOfIntervals) {
this.mWorkTW = mWorkTW;
this.mWorkET = mWorkET;
this.mRestTW = mRestTW;
this.mRestET = mRestET;
this.mContext = context;
this.numberOfIntervals = numberOfIntervals;
//this.inputTimeIntegerWET = inputTimeIntegerWET;
Log.d(TAG, "CustomAdapter: " + numberOfIntervals);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View customView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.time_row, viewGroup, false);
ViewHolder holder = new ViewHolder(customView, new InputTextListener());
return holder;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, final int i) {
Log.d(TAG, "onBindViewHolder: called");
viewHolder.workTextView.setText(R.string.work_text_view);
viewHolder.restTextView.setText(R.string.rest_text_view);
viewHolder.workEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
viewHolder.workEditText.setHint("");
else
viewHolder.workEditText.setHint(mWorkET.get(viewHolder.getAdapterPosition()));
}
});
viewHolder.restEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
viewHolder.restEditText.setHint("");
else
viewHolder.restEditText.setHint(mRestET.get(viewHolder.getAdapterPosition()));
}
});
}
#Override
public int getItemCount() {
Log.d(TAG, "" + numberOfIntervals);
return numberOfIntervals;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public InputTextListener inputTextListener;
TextView workTextView;
EditText workEditText;
TextView restTextView;
EditText restEditText;
ConstraintLayout parentLayout;
public ViewHolder(#NonNull View itemView, InputTextListener inputTextListener) {
super(itemView);
workTextView = itemView.findViewById(R.id.workTextView);
workEditText = itemView.findViewById(R.id.workEditText);
restTextView = itemView.findViewById(R.id.restTextView);
restEditText = itemView.findViewById(R.id.restEditText);
parentLayout = itemView.findViewById(R.id.parentLayout);
this.inputTextListener = inputTextListener;
workEditText.addTextChangedListener(inputTextListener);
}
}
class InputTextListener implements TextWatcher {
String inputTimeString;
int inputTime;
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
public HashMap<String, Integer> getHashMap() {
return hashMap;
}
public InputTextListener() {
}
public void setHashMap(HashMap<String, Integer> hashMap) {
this.hashMap = hashMap;
}
public int getInputTime() {
return inputTime;
}
public void setInputTime(int inputTime) {
this.inputTime= inputTime;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try {
Log.d(TAG, "onTextChanged: I've made it to here!");
inputTimeString = s.toString().trim();
inputTime = Integer.parseInt(inputTimeString);
setInputTime(inputTime);
// hashMap.put("EDITTEXT VALUE", inputTime);
Log.d(TAG, "onTextChanged: " + inputTime);
int bla = inputTime + 2;
Log.d(TAG, "onTextChanged: " + bla);
Log.d(TAG, "onTextChanged: " + hashMap.containsKey("EDITTEXT VALUE"));
Log.d(TAG, "onTextChanged: " + hashMap.get("EDITTEXT VALUE"));
Log.d(TAG, "onTextChanged: "+ getInputTime());
//setHashMap(hashMap);
} catch (NumberFormatException NFE) {
mWorkET = null;
}
}
#Override
public void afterTextChanged(Editable s) {
}
}
}
public class TimeActivity extends AppCompatActivity {
public static final String TAG = TimeActivity.class.getSimpleName();
private int numberOfIntervals;
private ArrayList<Integer> WTV = new ArrayList<>();
private ArrayList<Integer> WET = new ArrayList<>();
private ArrayList<Integer> RTV = new ArrayList<>();
private ArrayList<Integer> RET = new ArrayList<>();
private int inputTime;
// private String yusuf = "5";
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.custom_menu, menu);
Drawable continueImageDrawable = menu.findItem(R.id.continueItem).getIcon();
continueImageDrawable.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
//Every non-transparent pixel will be turned into white.
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.continueItem:
CustomAdapter a = new CustomAdapter();
CustomAdapter.InputTextListener i = a.new InputTextListener();
//HashMap<String, Integer> hashMap = i.getHashMap();
//inputTime = hashMap.get("EDITTEXT VALUE");
inputTime = i.getInputTime();
// Log.d(TAG, "onOptionsItemSelected: " + hashMap.get("EDITTEXT VALUE"));
//Log.d(TAG, "onOptionsItemSelected: " + hashMap.containsKey("EDITTEXT VALUE"));
Log.d(TAG, "onOptionsItemSelected: " + inputTime);
retrieveInputTime(inputTime);
break;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
Log.d(TAG, "onCreate: Started");
View timeRowLayout = findViewById(R.id.parentLayout);
Intent intent = getIntent();
numberOfIntervals = intent.getIntExtra("Interval Count", numberOfIntervals);
Log.d(TAG, "" + numberOfIntervals);
initializeViews();
}
private void retrieveInputTime(int inputTime) {
Log.d(TAG, "retrieveInputTime: " + inputTime);
Intent intent2 = new Intent(this, ClockActivity.class);
if (inputTime > 0) {
intent2.putExtra("Input Time", inputTime);
startActivity(intent2);
Log.d(TAG, "retrieveInputTime: The data has been retrieved" + inputTime);
} else {
Toast.makeText(this, "Must enter a whole number 2", Toast.LENGTH_SHORT).show();
}
}
private void initializeViews() {
Log.d(TAG, "initializeViews: Preparing views");
//Make sure they can change through the R.strings
WTV.add(R.string.work_text_view);
WET.add(R.string.default_time_value);
RTV.add(R.string.rest_text_view);
RET.add(R.string.default_time_value);
initializeRecyclerView();
}
private void initializeRecyclerView() {
Log.d(TAG, "initializeRecyclerView: Initialize RecyclerView");
RecyclerView intervalRecyclerView = findViewById(R.id.intervalRecyclerView);
CustomAdapter adapter = new CustomAdapter(this, WTV, WET, RTV, RET, numberOfIntervals);
intervalRecyclerView.setAdapter(adapter);
intervalRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
I expect for the getInputTime method to return the correct value inside the TimeActivity class
I see you use getInputTime() in two places:
inside onTextChanged() it is preceded by setInputTime() so it should has value there
inside onOptionsItemSelected() it is called right after creating a new object via InputTextListener(). No initialization is done besides calling the default constructor. inputTime should be 0 at this point.
The CustomAdapater instance that you are referring to in onOptionsItemSelected isn't the same as the one you are initializing for your recyclerView in onCreate.
Look:
CustomAdapter a = new CustomAdapter();
CustomAdapter.InputTextListener i = a.new InputTextListener();
inputTime = i.getInputTime();
You are creating new instance of CustomAdapter then creating new instance of InputTextListener (zero connection between these objects so far), calling getInputTime() on that object will obviously return 0, since it's the default value of int in java.
Anyway, I can't really see the point for using recyclerView in your code.
First of all I want to thank everyone for trying to help solve the problem but I finally solved. The solution is to make the inputTime variable inside the InputTextListener class static. But since it's an inner class I had to make the InputTextListener class it's own class. If you have any thoughts or questions just comment down below.
I have a list of threads which I have paginated to use an endless scroll the issue I'm having (well my users) is an OutOfMemoryError: Failed to allocate a [x] byte allocation with [y] free bytes and [z] until OOM. the x, y and z attribute is different per user but the cause of the bug is always in the same place and it's when I refresh the posts. I'm completely out of my depth here as I have no idea how to optimise my code or make it so this doesn't happen. As it's the biggest crash on my app at the moment. I've posted my PostFragment below please see the refreshPosts(ArrayList<Posts> newObjects) method as this is where the crash is happening.
public class PostFragment extends Fragment implements View.OnClickListener {
private View mRootView;
private GridLayoutManager mLayoutManager;
private ThreadItem mThreads;
private PostItem mPost;
private PostAdapter mAdapter;
private PostResponse mData;
private EmoticonResponse mEmoticon;
private PostFeedDataFactory mDataFactory;
private EmoticonFeedDataFactory mEmoticonDataFactory;
private static PostFragment mCurrentFragment;
private int REQUEST_CODE;
//Flip
private boolean isFlipped = false;
private Animation flipAnimation;
#BindView(R.id.postsRecyclerView)
RecyclerView mRecyclerView;
#BindView(R.id.toolbarForPosts)
Toolbar mToolbar;
#BindView(R.id.threadText)
TextView mThreadText;
#BindView(R.id.flipText)
TextView mFlipTextView;
#BindView(R.id.shareText)
TextView mShareTextView;
#BindView(R.id.replyText)
TextView mReplyTextView;
#BindView(R.id.scrimColorView)
View mBackgroundView;
#BindView(R.id.fabMenu)
FloatingActionButton mFabMenu;
#BindView(R.id.flipFab)
FloatingActionButton mFlipFab;
#BindView(R.id.shareFab)
FloatingActionButton mShareFab;
#BindView(R.id.replyFab)
FloatingActionButton mReplyFab;
//Collapsing Toolbar
#BindView(R.id.postParentAppBarLayout)
AppBarLayout postAppBarLayout;
#BindView(R.id.postCollapseToolbar)
CollapsingToolbarLayout postCollapseToolbarLayout;
#BindView(R.id.mainImageContainer)
ViewGroup mainContainer;
//Back to top
#BindView(R.id.backToTopButton)
Button mBackToTop;
public static boolean isFromReply;
//FAB
private boolean mIsFabOpen = false;
private Animation fab_open, fab_close, rotate_forward, rotate_backward;
//Pagination
private int mCurrentPage = 1;
private ArrayList<Posts> postList = new ArrayList<>();
private boolean mIsLoading = false;
private boolean mIsLastPage = false;
public static PostFragment newInstance(#NonNull ThreadItem threadItem) {
Bundle args = new Bundle();
args.putParcelable("ThreadItem", Parcels.wrap(threadItem));
mCurrentFragment = new PostFragment();
mCurrentFragment.setArguments(args);
isFromReply = false;
return mCurrentFragment;
}
public static PostFragment newPostInstance(#NonNull PostItem postItem) {
Bundle args = new Bundle();
args.putParcelable("PostItemFromCompose", Parcels.wrap(postItem));
mCurrentFragment = new PostFragment();
mCurrentFragment.setArguments(args);
isFromReply = true;
return mCurrentFragment;
}
public PostFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.fragment_post, container, false);
if (savedInstanceState == null) {
ButterKnife.bind(this, mRootView);
initUI();
}
return mRootView;
}
private void initUI() {
//UI Setup
mLayoutManager = new GridLayoutManager(getActivity(), 1);
mRecyclerView.setLayoutManager(mLayoutManager);
mDataFactory = new PostFeedDataFactory(getActivity());
mEmoticonDataFactory = new EmoticonFeedDataFactory(getActivity());
TextView textThreadTopic = (TextView) mRootView.findViewById(R.id.threadTopic);
TextView textNumPosts = (TextView) mRootView.findViewById(R.id.numPosts);
//FAB onClick Set-Up
mFabMenu.setOnClickListener(this);
mShareFab.setOnClickListener(this);
mReplyFab.setOnClickListener(this);
mFlipFab.setOnClickListener(this);
//FAB Animation Set up
fab_open = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.fab_open);
fab_close = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.fab_close);
rotate_forward = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.rotate_forward);
rotate_backward = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.rotate_backward);
//Toolbar
((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(false);
mToolbar.setNavigationIcon(R.drawable.ic_back_white);
mToolbar.invalidate();
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().finish();
}
});
//Load Parcel
Intent intent = getActivity().getIntent();
mThreads = Parcels.unwrap(getArguments().getParcelable("ThreadItem"));
mPost = Parcels.unwrap(getArguments().getParcelable("PostItemFromCompose"));
if (mThreads != null) {
if (mThreads.getName() != null) {
mThreadText.setText(mThreads.getName());
}
if (mThreads.getTopic_name() != null) {
textThreadTopic.setText(mThreads.getTopic_name());
}
if (mThreads.getNum_posts() != null) {
int numPosts = Integer.parseInt(mThreads.getNum_posts());
if (numPosts > 1000) {
textNumPosts.setText("1K");
} else {
textNumPosts.setText(mThreads.getNum_posts());
}
}
}
postAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0) {
postCollapseToolbarLayout.setTitle("Threads");
mainContainer.setVisibility(View.INVISIBLE);
isShow = true;
} else if (isShow) {
postCollapseToolbarLayout.setTitle("");
isShow = false;
mainContainer.setVisibility(View.VISIBLE);
}
}
});
flipAnimation =
AnimationUtils.loadAnimation(getActivity().getApplicationContext(), R.anim.flip);
loadData(true, 1);
}
private void loadData(final boolean firstLoad, int readDirection) {
if (isFromReply) {
if (mPost.getThread_id() != null) {
mDataFactory.getPostFeed(mPost.getThread_id(), readDirection, mCurrentPage,
new PostFeedDataFactory.PostFeedDataFactoryCallback() {
#Override
public void onPostDataReceived(PostResponse response) {
mData = response;
if (mData.getItems() != null) {
for (int i = 0; i < mData.getItems().size(); i++) {
Posts singlePost = response.getItems().get(i);
postList.add(singlePost);
}
if (firstLoad) {
mIsLoading = false;
mData.getItems().clear();
mData.getItems().addAll(postList);
mEmoticonDataFactory.getEmoticonFeed(
new EmoticonFeedDataFactory.EmoticonFeedDataFactoryCallback() {
#Override
public void onEmoticonDataReceived(EmoticonResponse response) {
mEmoticon = response;
populateUIWithData();
}
#Override
public void onEmoticonDataFailed(Exception exception) {
}
});
} else {
mIsLoading = false;
refreshPosts(postList);
}
if (mData.getItems().size() > 0) {
if (Integer.valueOf(mData.getTotalPosts()) >= response.getItems().size()) {
mCurrentPage++;
} else {
mIsLastPage = true;
}
}
}
}
#Override
public void onPostDataFailed(Exception exception) {
customToast("Error: " + exception.toString());
}
});
}
} else {
if (mThreads.getId() != null)
mDataFactory.getPostFeed(mThreads.getId(), readDirection, mCurrentPage,
new PostFeedDataFactory.PostFeedDataFactoryCallback() {
#Override
public void onPostDataReceived(PostResponse response) {
mData = response;
if (mData.getItems() != null) {
for (int i = 0; i < mData.getItems().size(); i++) {
Posts singlePost = response.getItems().get(i);
postList.add(singlePost);
}
if (firstLoad) {
mIsLoading = false;
mData.getItems().clear();
mData.getItems().addAll(postList);
mEmoticonDataFactory.getEmoticonFeed(
new EmoticonFeedDataFactory.EmoticonFeedDataFactoryCallback() {
#Override
public void onEmoticonDataReceived(EmoticonResponse response) {
mEmoticon = response;
populateUIWithData();
}
#Override
public void onEmoticonDataFailed(Exception exception) {
}
});
} else {
mIsLoading = false;
refreshPosts(postList);
}
if (mData.getItems().size() > 0) {
if (Integer.valueOf(mData.getTotalPosts()) >= response.getItems().size()) {
mCurrentPage++;
} else {
mIsLastPage = true;
}
}
}
}
#Override
public void onPostDataFailed(Exception exception) {
customToast("Error: " + exception.toString());
}
});
}
}
private void populateUIWithData() {
ImageButton moreOptionsButton = (ImageButton) mRootView.findViewById(R.id.moreOptions);
moreOptionsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(v.getContext(), v);
popupMenu.inflate(R.menu.thread_options);
popupMenu.getMenu();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.watch:
WatchedThreadsRequestData watchedThreadsRequestData = new WatchedThreadsRequestData(getActivity());
watchedThreadsRequestData.setWatchedThread(mThreads.getId(), new WatchedThreadsRequestData.WatchedThreadsFeedback() {
#Override
public void onWatchedRequestReceived(ThreadResponse response) {
customToast("Thread watched");
}
#Override
public void onWatchedRequestFailed(Exception exception) {
customToast("Thread wasn't watched: " + exception.toString());
}
});
return true;
case R.id.shareThread:
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_TEXT, mThreads.getName() + " - " + Constants.LIVE_URL +
"talk/" + mThreads.getTopic_url() + '/' + mThreads.getThread_url());
sharingIntent.setType("text/plain");
getActivity().startActivity(Intent.createChooser(sharingIntent, "Share via"));
return true;
case R.id.hideThread:
customToast("Hide: coming soon");
return true;
default:
customToast("Somethings Wrong");
return true;
}
}
});
setForceShowIcon(popupMenu);
popupMenu.show();
}
});
if (mAdapter == null) {
mAdapter = new PostAdapter(getActivity(), mData, mEmoticon);
mRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.setData(mData.getItems());
mAdapter.notifyDataSetChanged();
}
mRecyclerView.addOnScrollListener(paginationListener);
}
public static void setForceShowIcon(PopupMenu popupMenu) {
try {
Field[] fields = popupMenu.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popupMenu);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private RecyclerView.OnScrollListener paginationListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
boolean hasEnded = newState == SCROLL_STATE_IDLE;
if (hasEnded) {
mFabMenu.show();
mFabMenu.setClickable(true);
} else {
if (mIsFabOpen)
closeMenu();
mFabMenu.hide();
mFabMenu.setClickable(false);
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
if (!mIsLoading && !mIsLastPage) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount) {
loadMoreItems();
}
}
//Back to top
if (mLayoutManager.findLastVisibleItemPosition() == totalItemCount - 1) {
mBackToTop.setVisibility(View.VISIBLE);
mBackToTop.setClickable(true);
mBackToTop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mLayoutManager.scrollToPositionWithOffset(0,0);
}
});
} else {
mBackToTop.setVisibility(View.GONE);
mBackToTop.setClickable(false);
}
}
};
private void loadMoreItems() {
if (!isFlipped) {
mIsLoading = true;
loadData(false, 1);
} else {
mIsLoading = true;
loadData(false, -1);
}
}
private void refreshPosts(ArrayList<Posts> newObjects) {
postList.addAll(newObjects);
populateUIWithData();
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.fabMenu:
animateFAB();
break;
case R.id.shareFab:
share();
break;
case R.id.replyFab:
reply();
break;
case R.id.flipFab:
flip();
break;
}
}
public void animateFAB() {
if (mIsFabOpen) {
closeMenu();
} else {
mFabMenu.startAnimation(rotate_forward);
mReplyFab.startAnimation(fab_open);
mShareFab.startAnimation(fab_open);
mFlipFab.startAnimation(fab_open);
mReplyFab.setClickable(true);
mShareFab.setClickable(true);
mFlipFab.setClickable(true);
mFlipTextView.setVisibility(View.VISIBLE);
mShareTextView.setVisibility(View.VISIBLE);
mReplyTextView.setVisibility(View.VISIBLE);
mBackgroundView.setVisibility(View.VISIBLE);
mIsFabOpen = true;
}
}
private void closeMenu() {
mFabMenu.startAnimation(rotate_backward);
mReplyFab.startAnimation(fab_close);
mShareFab.startAnimation(fab_close);
mFlipFab.startAnimation(fab_close);
mReplyFab.setClickable(false);
mShareFab.setClickable(false);
mFlipFab.setClickable(false);
mFlipTextView.setVisibility(View.INVISIBLE);
mShareTextView.setVisibility(View.INVISIBLE);
mReplyTextView.setVisibility(View.INVISIBLE);
mBackgroundView.setVisibility(View.INVISIBLE);
mIsFabOpen = false;
}
private void reply() {
PreferenceConnector.writeString(getActivity().getApplicationContext(), "threadID", mThreads.getId());
PreferenceConnector.writeString(getActivity().getApplicationContext(), "threadTitle", mThreads.getName());
if (PreferenceConnector.readString(getActivity(), "authToken") == null ||
PreferenceConnector.readString(getActivity(), "authToken").equalsIgnoreCase("skip")) {
final AlertDialog.Builder loginDialog = new AlertDialog.Builder(getActivity());
loginDialog.setTitle("Please log in");
loginDialog.setMessage("You need to be logged in to reply");
loginDialog.setPositiveButton("Log in", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getActivity().getApplicationContext(), LoginActivity.class);
startActivity(intent);
}
});
loginDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
loginDialog.show();
} else {
closeMenu();
Intent intent = new Intent(getActivity().getApplicationContext(), NewPostActivity.class);
intent.putExtra("Threads", Parcels.wrap(mThreads));
getActivity().finish();
startActivityForResult(intent, REQUEST_CODE);
}
}
private void share() {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_TEXT, mThreads.getName() + " - " + Constants.LIVE_URL +
"talk/" + mThreads.getTopic_url() + '/' + mThreads.getThread_url());
sharingIntent.setType("text/plain");
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
private void flip() {
if (!isFlipped) {
mAdapter.clearAll();
isFlipped = true;
mRecyclerView.startAnimation(flipAnimation);
loadData(false, -1);
closeMenu();
} else {
mAdapter.clearAll();
isFlipped = false;
mRecyclerView.startAnimation(flipAnimation);
loadData(true, 1);
closeMenu();
}
}
private void customToast(String toastMessage) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) getActivity().findViewById(R.id.toastContainer));
TextView customToastText = (TextView) layout.findViewById(R.id.customToastText);
customToastText.setText(toastMessage);
Toast toast = new Toast(getActivity().getApplicationContext());
toast.setGravity(Gravity.BOTTOM, 0, 25);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
}
#Override
public void onResume() {
super.onResume();
if (mData != null && mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (mIsFabOpen) {
closeMenu();
} else {
getActivity().finish();
}
return true;
}
return false;
}
});
}
public void updateView() {
mAdapter.notifyDataSetChanged();
}
}
Thanks in advance once again.
Your problem basically boils down to this:
private void refreshPosts(ArrayList<Posts> newObjects) {
postList.addAll(newObjects);
populateUIWithData();
}
The list can only get bigger, never smaller. If the server has lots and lots of posts, then OutOfMemory is pretty much inevitable.
One approach to solving this problem is to use an LRU (Least Recently Used) cache. There is a utility class you can use: android.util.LruCache.
An LRU Cache is essentially a Map. Items are stored with a key, like an ID. With an LRU cache, you put new items in, but once a pre-determined limit is reached, old items start getting pushed out to make room for new items.
This will save memory, but make a lot more management code for you.
Your adapter, instead of having a list of posts, will just have a list of the post IDs. This should be much easier on memory.
As the user scrolls and you collect more posts, you add the post ID to the list, and map the post into the LRU cache using the post ID.
When you bind to the list item view, you look up the post using the post's ID in the LRU cache.
If it's there, great. That's called a cache hit. Bind the post to the
list item view.
If not, then you have a cache miss. You have some work to do.
Start a server request to retrieve the post by ID. I see your current code just retrieves blocks of posts, so you'll need some new server code here.
When the request completes, put the post in the LRU cache and let the adapter know your item has changed using adapter.notifyItemChanged(). Unless the user has scrolled beyond it, the RecyclerView should try to bind with the list item view again. This time, you should get a cache hit.
This is the basic idea. I'd write some code, but I still have a lot of questions since I can't see your model classes, data factories, and adapter class.
Once you have it working, you have to tune the limit on the cache so that it's low enough not to overrun memory, but high enough that your hit/miss ratio isn't close to zero.
BTW, I noticed that you are making the mistake of creating a new adapter and handing it to the RecyclerView each time you get a block of posts. You should create your adapter once, keep a reference to it and update it. Have a method that adds a block of posts then calls notifyDataSetChanged().
Another idea for conserving memory is to use text compression. If the problem is more a result of a large average size of the post rather than a large number of posts, you might explore this idea in addition to the LRU cache.
The concept is that you could take posts over a certain size, write them into a buffer using a ZipOutputStream then save the buffer in memory. When it's time to display the post, you read the buffer with a ZipInputStream to uncompress the text. Here the issue is performance as the compression/decompression is pretty CPU-intensive. But if the problem is really long posts, this approach might be something to consider.
An even better approach: Only save the first part of the post as an "overview" display in the list. When the user clicks on the list item, retrieve the entire post from the server and display that in another page.
i have an activity with recyclerview that extends fragment activity.
When an item is clicked from a recyerview, i want to get the title and display it as a pop up message.
i tried several ways but noting works. cam some one help me to do this TNX.
PickupActivity
public class PickupActivity extends AppCompatActivity implements View.OnClickListener{
private Toolbar toolbar;
private navigationDrawerFragment drawerFragment;
ApplicationEnvironmentURL applicationEnvironment;
ProgressDialog pDialog;
Context context;
String BASEURL;
String FilteredData;
String AllAgents;
public String ProfileId;
public String companyId;
public String profileToken;
private com.github.clans.fab.FloatingActionButton pik_fab1;
private com.github.clans.fab.FloatingActionButton pik_fab2;
private com.github.clans.fab.FloatingActionButton pik_fab3;
private com.github.clans.fab.FloatingActionButton pik_fab4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Dashboard");
setContentView(R.layout.activity_pickup);
applicationEnvironment = new ApplicationEnvironmentURL(this.context);
context = this.getApplicationContext();
toolbar = (Toolbar) findViewById(R.id.app_bar_dashboard);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (navigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setup(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), toolbar);
pik_fab1 = (com.github.clans.fab.FloatingActionButton) findViewById(R.id.pickup_delete);
pik_fab2 = (com.github.clans.fab.FloatingActionButton) findViewById(R.id.pickup_close);
pik_fab3 = (com.github.clans.fab.FloatingActionButton) findViewById(R.id.pickup_assignto);
pik_fab4 = (com.github.clans.fab.FloatingActionButton) findViewById(R.id.pickup_pickup);
pik_fab1.setOnClickListener(this);
pik_fab2.setOnClickListener(this);
pik_fab3.setOnClickListener(this);
pik_fab4.setOnClickListener(this);
SharedPreferences prefs = getSharedPreferences("zupportdesk", MODE_PRIVATE);
String islogged = prefs.getString("islogged", "Not defined");
String userid = prefs.getString("userid", "Not defined");
profileToken = prefs.getString("profileToken", "Not defined");
companyId = prefs.getString("companyId", "Not defined");
String companyName = prefs.getString("companyName", "Not defined");
ProfileId = prefs.getString("ProfileId", "Not defined");
Log.d("islogged : ", islogged);
Log.d("userid : ", userid);
Log.d("profileToken : ", profileToken);
Log.d("companyId : ", companyId);
Log.d("companyName : ", companyName);
Log.d("ProfileId : ", ProfileId);
getTickets(ProfileId, companyId, profileToken);
View newTicket = findViewById(R.id.newtic);
newTicket.setOnClickListener(onClickListener);
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.pickup_pickup:
Log.d("Fab_clicked", "Pickup Ticket");
pickupTicketMessage("Are you sure you want to pickup the selected tickets?", "Confirm?");
break;
case R.id.pickup_close:
Log.d("Fab_clicked", "close tickets");
closeTicketMessage("Are you sure you want to close the selected tickets?", "Confirm?");
break;
case R.id.pickup_delete:
Log.d("Fab_clicked", "close tickets");
DeleteTicketMessage("Are you sure you want to delete the selected tickets?", "Confirm?");
break;
case R.id.pickup_assignto:
Log.d("Fab_clicked", "Assign to Agent");
try {
assignTicketstMessage("Select an agent");
} catch (JSONException e) {
e.printStackTrace();
}
break;
}
}
/* Multiple Button on click event handle */
private View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(final View v) {
switch(v.getId()){
case R.id.newtic:
// Create a login URl, before starting anything
if(isNetworkAvailable()){
Intent intentTicket = new Intent(PickupActivity.this, NewTicket.class);
startActivity(intentTicket);
} else {showErrorMessage("Please check your internet connection.", "No Connectivity!"); }
break;
}
}
};
public void getTickets(String profileId, String companyId, String profileToken) {
if (isNetworkAvailable()) {
try {
setFilteredDataURL(companyId, profileId);
FilteredData = new getFilteredData().execute(profileToken).get();
// adding the filtered data to shared preferences for further use.
//adding user data to shared preferences.
SharedPreferences.Editor editor = getSharedPreferences("zupportdesk", MODE_PRIVATE).edit();
editor.putString("FilteredData", FilteredData);
editor.commit();
Log.d("ZF-Filtered_Data", FilteredData);
setTicketsURL(profileId, companyId);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
new getNewTickets().execute(profileToken);
} else {
showErrorMessage("Please check your internet connection.", "No Connectivity!");
}
}
private void PickupTicket() throws JSONException {
JSONObject jsonObject = new JSONObject();
JSONArray TicketsArray = new JSONArray();
List<Integer> selected_item = new ArrayList<>();
for (PickupTicketsItemObject ticket : PickupActivityFragment.support_ticket) {
if (ticket.isSelected()) {
selected_item.add(Integer.valueOf(ticket.getTicket_id()));
TicketsArray.put(Integer.valueOf(ticket.getTicket_id()));
}
}
Log.d("pickup_ticket_size", String.valueOf(selected_item.size()));
if(selected_item.size() < 1){
Log.d("pickup_ticket_size", "empty");
//Show Error Message
}else {
Log.d("pickup_ticket_size", "have tickets");
jsonObject.put("TicketID", TicketsArray);
jsonObject.put("ProfileId", ProfileId);
jsonObject.put("CompanyID", companyId);
setPickupTicketURI();
Log.d("ZF-PickupTicket", String.valueOf(jsonObject));
new TicketPickupRequest().execute(String.valueOf(jsonObject), profileToken);
}
}
private void showSuccessMessage(String data, String title){
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(data)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// restart Activity
finish();
startActivity(getIntent());
}
})
.setIcon(R.drawable.notification_success)
.show();
}
private void assignTicketstMessage(String title) throws JSONException {
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(title);
final List<String> agentList = new ArrayList<String>();
final List<String> agentProfileIDList = new ArrayList<String>();
if(AllAgents != null && !AllAgents.isEmpty() && !AllAgents.equals("null")) {
JSONArray jsonarray = new JSONArray(AllAgents);
int count = jsonarray.length();
Log.d("Full Agents", String.valueOf(count));
for (int k = 0; k < jsonarray.length(); k++) {
JSONObject jsonobject5 = jsonarray.getJSONObject(k);
Log.d("Agent object ", String.valueOf(jsonobject5));
agentList.add(jsonobject5.getString("FirstName"));
agentProfileIDList.add(jsonobject5.getString("ProfileId"));
}
String[] types = new String[agentList.size()];
for (int j = 0; j < agentList.size(); j++) {
types[j] = agentList.get(j);
}
b.setItems(types, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Selected_no ", String.valueOf(which));
Log.d("Selected_agent ", String.valueOf(agentList.get(which)));
Log.d("Selected_profile_id ", String.valueOf(agentProfileIDList.get(which)));
dialog.dismiss();
assignTicketstMessage2(String.valueOf(agentList.get(which)), String.valueOf(agentProfileIDList.get(which)));
}
});
b.show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
Intent i = new Intent(getApplicationContext(),Settings.class);
startActivity(i);
return true;
}
if(id == R.id.home){
NavUtils.navigateUpFromSameTask(this);
}
//noinspection SimplifiableIfStatement
if (id == R.id.notification){
Intent i = new Intent(getApplicationContext(), Notifications.class);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private void showErrorMessage(String data, String title) {
new AlertDialog.Builder(this.context)
.setTitle(title)
.setMessage(data)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.setIcon(R.drawable.notification_red)
.show();
}
private void showErrorMessageNoInbox(String data, String title) {
new AlertDialog.Builder(this.context)
.setTitle(title)
.setMessage(data)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
Intent i = new Intent(getApplicationContext(), Login.class);
startActivity(i);
}
})
.setIcon(R.drawable.notification_red)
.show();
}
public HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
......................... More
PickupActivityFragment
public class PickupActivityFragment extends Fragment {
public static ArrayList<PickupTicketsItemObject> support_ticket;
public static RecyclerView Ticketslist;
PickupActivity pick_up_activity;
public PickupActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_pickup_fragment, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
pick_up_activity = new PickupActivity();
Ticketslist = (RecyclerView) view.findViewById(R.id.pickup_list);
Ticketslist.setLayoutManager(new LinearLayoutManager(getActivity()));
Ticketslist.setHasFixedSize(true);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
pick_up_activity = new PickupActivity();
}
}
PickupTicketsAdapter
public class PickupTicketsAdapter extends RecyclerView.Adapter<PickupTicketsAdapter.ViewHolder> {
ArrayList<PickupTicketsItemObject> all_tickets;
public PickupTicketsAdapter(List<PickupTicketsItemObject> tickets) {
this.all_tickets = new ArrayList<>(tickets);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_pick_tickets, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.bindData(all_tickets.get(position));
//in some cases, it will prevent unwanted situations
holder.checkbox.setOnCheckedChangeListener(null);
//if true, your checkbox will be selected, else unselected
holder.checkbox.setChecked(all_tickets.get(position).isSelected());
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
all_tickets.get(holder.getAdapterPosition()).setSelected(isChecked);
}
});
}
#Override
public int getItemCount() {
return all_tickets.size();
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public ImageView priority;
public TextView sts_open;
public TextView sts_overdue;
public TextView tkt_from;
public TextView tkt_subject;
public TextView tkt_assignedto;
public TextView tkt_created_date;
public TextView txt_ticket_id;
public CheckBox checkbox;
public ViewHolder(View v) {
super(v);
checkbox = (CheckBox) v.findViewById(R.id.pick_checkbox);
priority = (ImageView) v.findViewById(R.id.priority_status_icon);
sts_open= (TextView) v.findViewById(R.id.tv_Tk_opn_status);
sts_overdue = (TextView) v.findViewById(R.id.tv_Tk_overdue);
tkt_from = (TextView) v.findViewById(R.id.tv_Tk_from);
tkt_subject = (TextView) v.findViewById(R.id.tv_Tk_subject);
tkt_assignedto = (TextView) v.findViewById(R.id.tv_Tk_Assignedto);
tkt_created_date = (TextView) v.findViewById(R.id.tv_Tk_Created_date);
txt_ticket_id = (TextView) v.findViewById(R.id.tv_Tk_TicketID);
}
public void bindData(PickupTicketsItemObject ticket) {
priority.setImageResource(ticket.getStatus_priority());
sts_open.setText(ticket.getStatus_open());
sts_overdue.setText(ticket.getStatus_overdue());
tkt_from.setText(ticket.getTicket_from());
tkt_subject.setText(ticket.getTicket_subject());
tkt_assignedto.setText(ticket.getTicket_assignedto());
tkt_created_date.setText(ticket.getTicket_created_date());
txt_ticket_id.setText(ticket.getTicket_id());
}
}
}
PickupTicketsItemObject
public class PickupTicketsItemObject {
private int status_priority;
private String status_open;
private String status_overdue;
private String ticket_from;
private String ticket_subject;
private String ticket_assignedto;
private String ticket_created_date;
private String ticket_id;
private boolean isSelected;
public PickupTicketsItemObject(){
}
public int getStatus_priority() {
return status_priority;
}
public String getStatus_open() {
return status_open;
}
public String getStatus_overdue() {
return status_overdue;
}
public String getTicket_from() {
return ticket_from;
}
public String getTicket_subject() {
return ticket_subject;
}
public String getTicket_assignedto() {
return ticket_assignedto;
}
public String getTicket_created_date(){return ticket_created_date;}
public String getTicket_id(){return ticket_id;}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
public void setStatus_priority(int status_priority) {
this.status_priority = status_priority;
}
public void setStatus_open(String status_open) {
this.status_open = status_open;
}
public void setStatus_overdue(String status_overdue) {
this.status_overdue = status_overdue;
}
public void setTicket_from(String ticket_from) {
this.ticket_from = ticket_from;
}
public void setTicket_subject(String ticket_subject) {
this.ticket_subject = ticket_subject;
}
public void setTicket_assignedto(String ticket_assignedto) {
this.ticket_assignedto = ticket_assignedto;
}
public void setTicket_created_date(String ticket_created_date) {
this.ticket_created_date = ticket_created_date;
}
public void setTicket_id(String ticket_id) {
this.ticket_id = ticket_id;
}
}
public void onBindViewHolder(.....)
for particular TextView and use AlertDialog to show message inside adapter.
All you need to do is make changes in your adapter class
In your ViewHolder class, declare a CardView object as well.
Then in the onBindViewHolder method you can set the holder.cardview.onClickListener
You can use alert dialog builder for showing popups