Website Scraping html class identification issues - android-studio

I want to scrape MAL for character imgurl to later display using Picasso and name of character but am having troubles accessing the correct class files.
Here is the website under inspect. TYSM in advance.
Inspect MAL
Here is my CharacterList class which identifies the HTML classes
private RecyclerView recyclerView;
private ParseAdapter adapter;
private ArrayList<ParseItem> parseItems = new ArrayList<>();
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_watch_list);
configureBackButton();
progressBar = findViewById(R.id.progressBar);
recyclerView = findViewById(R.id.recyclerView_character);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new ParseAdapter(parseItems, this);
recyclerView.setAdapter(adapter);
Content content = new Content();
content.execute();
}
private class Content extends AsyncTask<Void, Void,Void>{
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
progressBar.setAnimation(AnimationUtils.loadAnimation(CharacterList.this, android.R.anim.fade_in));
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressBar.setVisibility(View.GONE);
progressBar.setAnimation(AnimationUtils.loadAnimation(CharacterList.this, android.R.anim.fade_out));
adapter.notifyDataSetChanged();
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected Void doInBackground(Void... voids) {
try{
//website url
String url = "https://myanimelist.net/character.php";
Document doc = Jsoup.connect(url).get();
Elements data = doc.select("tr.people");
int size = data.size();
for (int i = 0; i < size; i++){
String imgUrl = data.select("a.mr8.ml12.fl-l")
.select("img")
.eq(i)
.attr("src");
String title = data.select("tr.mt24.di-ib.information")
.select("a.fw-b.fs14")
.eq(i)
.text();
parseItems.add(new ParseItem(imgUrl, title));
Log.d("items", "img: " +imgUrl + " .title: " + title);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I believe my ParseAdapter and ParseItem are working but just in case here they are
public class ParseAdapter extends RecyclerView.Adapter<ParseAdapter.ViewHolder> {
private ArrayList<ParseItem> parseItems;
private Context context;
public ParseAdapter(ArrayList<ParseItem> parseItems, Context context){
this.parseItems = parseItems;
this.context = context;
}
#NonNull
#Override
public ParseAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.parse_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ParseAdapter.ViewHolder holder, int position) {
ParseItem parseItem = parseItems.get(position);
holder.textView.setText(parseItem.getTitle());
Picasso
//with vs get()
.with(this.context)
.load(parseItem.getImgurl())
.into(holder.imageView);
}
#Override
public int getItemCount() {
return parseItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView textView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView_character);
textView = itemView.findViewById(R.id.textView_character);
}
}
}
public class ParseItem {
private String imgurl;
private String title;
public ParseItem(){
}
public ParseItem(String imgurl, String title) {
this.imgurl = imgurl;
this.title = title;
}
public String getImgurl() {
return imgurl;
}
public void setImgurl(String imgurl) {
this.imgurl = imgurl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}}

I figured it out nevermind. Here is the class identification part in case anyone is stuck later on.
Elements data = doc.select("td.people");
int size = data.size();
for (int i = 0; i < size; i++){
String imgUrl = data.select("a.fl-l.ml12.mr8")
.select("img")
.eq(i)
.attr("data-src");
String title = data.select("div.information.di-ib.mt24")
.select("a.fs14.fw-b")
.eq(i)
.text();

Related

How can I see all data with RecyclerView?

I cannot show all datas to RecyclerView.I keep getting this error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference
at com.cdirect.weatherapp.MyLocations.onCreate(MyLocations.java:50)
MyLocations.java: 50:
rcView.setAdapter(adapter);
MyLocations.java code:
public class MyLocations extends AppCompatActivity {
BottomNavigationView altNav;
RecyclerView rcView;
ArrayList<Locations> locationsList;
DatabaseReference dbRef;
Adapter adapter;
#Override
public void onBackPressed() {
super.onBackPressed();
startActivity(new Intent(MyLocations.this,MainActivity.class));
finish();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbRef = FirebaseDatabase.getInstance().getReference("Locations");
altNav = (BottomNavigationView) findViewById(R.id.altNav);
rcView = findViewById(R.id.rvLocations);
locationsList = new ArrayList<>();
adapter = new Adapter(MyLocations.this, locationsList);
rcView.setAdapter(adapter); //ERROR LINE
rcView.setLayoutManager(new LinearLayoutManager(this));
Adapter.java codes:
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
ArrayList<Locations> locationsArrayList;
Context context;
public Adapter (Context context, ArrayList<Locations> locationsArrayList){
this.locationsArrayList=locationsArrayList;
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.recycler_view_row,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Locations loc = locationsArrayList.get(position);
holder.location.setText(loc.getLocation());
holder.temperature.setText(loc.getTemp());
}
#Override
public int getItemCount() {
return locationsArrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
TextView location, temperature;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
location = itemView.findViewById(R.id.tvLocation);
temperature= itemView.findViewById(R.id.tvTemp);
}
}
}
Locations.java code:
public class Locations {
String location;
String temp;
String id;
public Locations(String location, String temp, String id) {
this.location = location;
this.temp = temp;
this.id = id;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
I cannot solve where is the problem. Can you help me?

how to get all values added to recyclerview and send it to ion lib

so im trying to get recyclerview data list added and send it to ion lib when i use method below i only get one element as ill have to change string inside for() to String fav =null ouside of for() and log.d only shows the last result. i need get all so i can send to senddata() to ion lib
FavModelClass
private String fav;
private String user_id;
public FavModelClass(String fav, String user_id) {
this.fav = fav;
this.user_id = user_id;
}
public String getFav() {
return fav;
}
public void setFav(String fav) {
this.fav = fav;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
}
adapter
public class FavAdapter extends
RecyclerView.Adapter<FavAdapter .MyViewHolder> {
private List<FavModelClass> favModelClassList;
private Context beddingContext;
public FavAdapter (List<FavModelClass> favModelClassList, Context
beddingContext) {
this.favModelClassList= favModelClassList;
this.beddingContext = beddingContext;
}
#NonNull
#Override
public FavAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup
parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.amenitylayout,parent,false);
FavAdapter .MyViewHolder holder = new FavAdapter .MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull FavAdapter.MyViewHolder holder, int i) {
final FavModelClassdata = favModelClassList.get(i);
holder.ac_bedding_type.setText(data.getFav()+" "+"MAX:"+data.getUser_id());
holder.delete_entry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeAt(holder.getAdapterPosition());
}
});
}
public void removeAt(int position) {
favModelClassList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, favModelClassList.size());
}
#Override
public int getItemCount() {
return favModelClassList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView ac_bedding_type;
private ImageButton delete_entry;
public MyViewHolder(#NonNull View v) {
super(v);
ac_bedding_type = v.findViewById(R.id.ac_amenity_name);
delete_entry = v.findViewById(R.id.delete_amenity_entry);
}
}
}
Main activity
fav_recycler = findViewById(R.id.fave_recycler);
GridLayoutManager layoutManager1 = new GridLayoutManager(getApplicationContext(), 2,GridLayoutManager.VERTICAL, false);
fav_recycler.setHasFixedSize(true);
fav_recycler.setLayoutManager(layoutManager1);
favModelClassList= new ArrayList<>();
addfavamenity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
favModelClassList.add(new FavModelClass(
amenityET.getText().toString(),
user_idET.getText().toString()
));
amenityET.setText("");
user_idET.setText("");
FavAdapter adapter = new FavAdapter (favModelClassList, getApplicationContext());
adapter.notifyDataSetChanged();
fav_recycler.setAdapter(adapter);
for (int i = 0; i < favModelClassList.size(); i++) {
final FavModelClassList data = favModelClassList.get(i);
final String fav= data.getFav();
final String user_id = data.getUser_id();
Log.d(TAG, "onClick: "+ fav);
}
}
});
ArrayList d = new ArrayList();
for (int i = 0; i < favModelClassList.size(); i++) {
final FavModelClassList data = favModelClassList.get(i);
d.add(data.getFav());
}
Log.d(TAG, "onClick: " + d);

ViewPager2 adapter item layout flattened

I'm facing an issue with my viewpager2 adapter. The adapter contains a share button which starts an new activity with a create chooser Intent. The problem is if swipe down or press the android back button the current item layout is flattened or sometime it changes the current item to the next one.
However if go through the sharing process completely the app works fine.
ViewPager2.JAVA*
public class StreamPostDetailAdapter extends RecyclerView.Adapter<StreamPostDetailAdapter.TestPagerViewHolder> {
public Context mContext;
public List<Post> mPost;
private FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
String mUid ;
public IpagerAdapter mListener;
private CommentAdapter commentAdapter;
private List<Comment> commentList;
public StreamPostDetailAdapter(Context mContext, List<Post> mPost, IpagerAdapter mListener) {
this.mListener = mListener;
this.mContext = mContext;
this.mPost = mPost;
mUid = firebaseUser.getUid();
}
#NonNull
#Override
public TestPagerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_post_swipe_item, parent, false);
return new TestPagerViewHolder(view,mListener);
}
#Override
public void onBindViewHolder(#NonNull TestPagerViewHolder holder, int position) {
Post post = mPost.get(holder.getBindingAdapterPosition());
String post_publisher = post.getPublisher();
String post_id = post.getPostid() ;
String post_image = post.getPostimage() ;
String post_timeStamp = post.getTimestamp();
String tag_list = post.getTagList();
String postTitle = post.getDescription();
boolean personal = post.getPersonal_tattoo();
commentList = new ArrayList<>();
commentAdapter = new CommentAdapter(mContext,commentList);
GlideApp.with(mContext).load(post_image)
.placeholder(R.mipmap.loading_img_placeholder)
.into(holder.image_post);
holder.title.setText(post.getDescription());
if (post.getTagList().equals("")) {
holder.tagList.setVisibility(View.GONE);
} else {
holder.tagList.setVisibility(View.VISIBLE);
holder.tagList.setText(post.getTagList());
}
holder.comment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.bsCommentsController(post_id, holder.commentRv);
BottomSheetBehavior.from(holder.bsComments).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
holder.like.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.like.getTag().equals("like")) {
FirebaseDatabase.getInstance().getReference().child("Likes")
.child(post_id)
.child(mUid).setValue(true);
} else {
FirebaseDatabase.getInstance().getReference().child("Likes")
.child(post_id)
.child(mUid).removeValue();
}
}
});
holder.image_profile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences.Editor editor = mContext.getSharedPreferences("PREFS", Context.MODE_PRIVATE).edit();
editor.putString("id", post_publisher);
editor.apply();
Intent intent = new Intent(mContext,HomeActivity.class);
intent.putExtra("origin","ViewPager");
mContext.startActivity(intent);
((StreamPostDetailActivity)mContext).finish();
}
});
holder.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mContext instanceof SavedPostActivity) {
mListener.removePost(post_id,post_image,position);
}
if (holder.save.getTag().equals("save")) {
FirebaseDatabase.getInstance().getReference().child("Saved").child(firebaseUser.getUid())
.child(post_id).setValue(true);
} else {
FirebaseDatabase.getInstance().getReference().child("Saved").child(firebaseUser.getUid())
.child(post_id).removeValue();
}
}
});
holder.share_post.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BitmapDrawable drawable = (BitmapDrawable)holder.image_post.getDrawable();
Bitmap bitmap = drawable.getBitmap();
String path = MediaStore.Images.Media.insertImage(mContext.getContentResolver(), bitmap, UUID.randomUUID().toString() + ".jpeg", "drawing");
Uri uri = Uri.parse(path);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_STREAM,uri);
intent.putExtra(Intent.EXTRA_TEXT, "Playstore Link : put app link in store ");
mContext.startActivity(Intent.createChooser(intent,"Share2"));
}
});
if (mContext instanceof SearchTattooDetailsActivity) {
holder.btn_post_options.setVisibility(View.GONE);
}else {
holder.btn_post_options.setVisibility(View.VISIBLE);
holder.btn_post_options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showMoreOptions(holder.btn_post_options, post_publisher, mUid, post_id, post_image, position, postTitle
, tag_list, personal);
}
});
}
// Add a new comment
holder.sendComment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!holder.comment_bar_edt.getText().toString().equals("")){
mListener.addComment(post_id, holder.comment_bar_edt.getText().toString());
holder.comment_bar_edt.setText("");
holder.comment_bar_edt.clearFocus();
}
}
});
holder.commentRv.setHasFixedSize(true);
holder.commentRv.setAdapter(commentAdapter);
}
#Override
public int getItemCount() {
return mPost.size();
}
private void showMoreOptions(ImageButton btn_post_options, String post_publisher, String mUid, String post_id, String post_image,int posItem, String postTitle, String tagList, boolean personal) {
PopupMenu popupMenu = new PopupMenu(mContext,btn_post_options, Gravity.END);
if (!post_publisher.equals(mUid)) {
popupMenu.getMenu().add(Menu.NONE,0,0,"Report post");
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
if (id == 0){
Toast.makeText(mContext, "CreateReportPost/UserNewCategoryRequestEmail", Toast.LENGTH_SHORT).show();
} else if (id == 1) {
//not working
Intent intentEdit = new Intent(mContext, EditPostActivity.class);
intentEdit.putExtra("title",postTitle);
intentEdit.putExtra("imageUrl", post_image);
intentEdit.putExtra("tagList", tagList );
intentEdit.putExtra("personal", personal );
intentEdit.putExtra("postId", post_id);
intentEdit.putExtra("posEditedPost", posItem);
((Activity)mContext).finish();
mContext.startActivity(intentEdit);
}
return false;
}
});
popupMenu.show();
}
//View Holder Class
public static class TestPagerViewHolder extends RecyclerView.ViewHolder {
public ImageView image_profile, image_post, like, comment, save,share_post;
public TextView username, likes, comments, title, time,tagList;
public ImageButton btn_post_options;
public IpagerAdapter mListener;
//Comments Bottom sheet
EditText comment_bar_edt;
public RecyclerView commentRv ;
ImageView sendComment,userImgComment;
public ConstraintLayout bsComments;
public LinearLayoutManager layoutManager;
public TestPagerViewHolder(#NonNull View itemView, IpagerAdapter mListener) {
super(itemView);
this.mListener = mListener;
image_post = itemView.findViewById(R.id.post_image);
image_profile = itemView.findViewById(R.id.image_profile);
like = itemView.findViewById(R.id.like_ic);
share_post= itemView.findViewById(R.id.share_post);
comment = itemView.findViewById(R.id.comment_ic);
save = itemView.findViewById(R.id.save);
username = itemView.findViewById(R.id.username);
likes = itemView.findViewById(R.id.likes);
comments = itemView.findViewById(R.id.comments);
tagList = itemView.findViewById(R.id.tagList);
title = itemView.findViewById(R.id.title);
time = itemView.findViewById(R.id.time);
btn_post_options = itemView.findViewById(R.id.post_options);
bsComments= itemView.findViewById(R.id.bsComments);
comment_bar_edt = itemView.findViewById(R.id.comment_bar_edt);
sendComment = itemView.findViewById(R.id.sendComment);
commentRv = itemView.findViewById(R.id.comments_rv);
BottomSheetBehavior.from(bsComments).setState(BottomSheetBehavior.STATE_HIDDEN);
}
}
public interface IpagerAdapter {
void removePost(String post_id, String post_image, int position);
void bsCommentsController(String post_id, RecyclerView commentRecyclerView);
void addComment(String post_id,String comment_txt);
}
public void removeItem(int position) {
if (position > -1 && position < mPost.size()) {
mPost.remove(position);
notifyDataSetChanged();
notifyItemRemoved(position);
}
}
}
#Francis,
Since It has been a while, I just remember that I've made changes in how I handled the BottomSheet which was containing the Comments RecyclerView. I extracted it from the StreamPostDetailAdapter (ViewPager2) and moved it to the corresponding activity. Therefore I have only one BottomSheet for all viewpager2 items. Then recyclerView data (comments fetch from firebase) is updated using interface listener methods to populate each items.
You will find the code of the ViewPager2 below:
public class StreamPostDetailAdapter extends RecyclerView.Adapter<StreamPostDetailAdapter.TestPagerViewHolder> {
public Context mContext;
public List<Post> mPost;
private FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
String mUid ;
public IpagerAdapter mListener;
private CommentAdapter commentAdapter;
private List<Comment> commentList;
public StreamPostDetailAdapter(Context mContext, List<Post> mPost, IpagerAdapter mListener) {
this.mListener = mListener;
this.mContext = mContext;
this.mPost = mPost;
mUid = firebaseUser.getUid();
}
#NonNull
#Override
public TestPagerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_post_swipe_item, parent, false);
return new TestPagerViewHolder(view,mListener);
}
#Override
public void onBindViewHolder(#NonNull TestPagerViewHolder holder, int position) {
Post post = mPost.get(holder.getBindingAdapterPosition());
String post_publisher = post.getPublisher();
String post_id = post.getPostid() ;
String post_image = post.getPostimage() ;
String post_timeStamp = post.getTimestamp();
String tag_list = post.getTagList();
String postTitle = post.getDescription();
boolean personal = post.getPersonal_tattoo();
GlideApp.with(mContext).load(post_image)
.placeholder(R.mipmap.loading_img_placeholder)
.into(holder.image_post);
holder.title.setText(post.getDescription());
if (post.getTagList().equals("")) {
holder.tagList.setVisibility(View.GONE);
} else {
holder.tagList.setVisibility(View.VISIBLE);
holder.tagList.setText(post.getTagList());
}
publisherInfo(holder.image_profile, holder.username, post_publisher);
asLiked(post_id, holder.like);
nLikes(holder.likes, post_id);
//getComments(post_id, holder.comments);
isSaved(post_id, holder.save);
getTimeAgo(holder.time, post_timeStamp);
holder.comment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.openBsComment();
}
});
holder.like.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.like.getTag().equals("like")) {
FirebaseDatabase.getInstance().getReference().child("Likes")
.child(post_id)
.child(mUid).setValue(true);
} else {
FirebaseDatabase.getInstance().getReference().child("Likes")
.child(post_id)
.child(mUid).removeValue();
}
}
});
holder.image_profile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences.Editor editor = mContext.getSharedPreferences("PREFS", Context.MODE_PRIVATE).edit();
editor.putString("id", post_publisher);
editor.apply();
Intent intent = new Intent(mContext,HomeActivity.class);
intent.putExtra("origin","ViewPager");
mContext.startActivity(intent);
((StreamPostDetailActivity)mContext).finish();
}
});
holder.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mContext instanceof SavedPostActivity) {
mListener.removePost(post_id,post_image,position);
}
if (holder.save.getTag().equals("save")) {
FirebaseDatabase.getInstance().getReference().child("Saved").child(firebaseUser.getUid())
.child(post_id).setValue(true);
} else {
FirebaseDatabase.getInstance().getReference().child("Saved").child(firebaseUser.getUid())
.child(post_id).removeValue();
}
}
});
holder.share_post.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BitmapDrawable drawable = (BitmapDrawable)holder.image_post.getDrawable();
Bitmap bitmap = drawable.getBitmap();
mListener.sharePost(bitmap);
}
});
if (mContext instanceof TaggedTattooDetailsActivity) {
holder.btn_post_options.setVisibility(View.GONE);
}else {
holder.btn_post_options.setVisibility(View.VISIBLE);
holder.btn_post_options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showMoreOptions(holder.btn_post_options, post_publisher, mUid, post_id, post_image, position, postTitle
, tag_list, personal);
}
});
}
// Add a new comment
}
#Override
public int getItemCount() {
return mPost.size();
}
private void showMoreOptions(ImageButton btn_post_options, String post_publisher, String mUid, String post_id, String post_image,int posItem, String postTitle, String tagList, boolean personal) {
PopupMenu popupMenu = new PopupMenu(mContext,btn_post_options, Gravity.END);
if (!post_publisher.equals(mUid)) {
popupMenu.getMenu().add(Menu.NONE,0,0,"Report post");
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
if (id == 0){
Toast.makeText(mContext, "CreateReportPost/UserNewCategoryRequestEmail", Toast.LENGTH_SHORT).show();
} else if (id == 1) {
//not working
Intent intentEdit = new Intent(mContext, EditPostActivity.class);
intentEdit.putExtra("title",postTitle);
intentEdit.putExtra("imageUrl", post_image);
intentEdit.putExtra("tagList", tagList );
intentEdit.putExtra("personal", personal );
intentEdit.putExtra("postId", post_id);
intentEdit.putExtra("posEditedPost", posItem);
((Activity)mContext).finish();
mContext.startActivity(intentEdit);
}
return false;
}
});
popupMenu.show();
}
//View Holder Class
public static class TestPagerViewHolder extends RecyclerView.ViewHolder {
public ImageView image_profile, image_post, like, comment, save,share_post;
public TextView username, likes, comments, title, time,tagList;
public ImageButton btn_post_options;
public IpagerAdapter mListener;
//Comments Bottom sheet
public LinearLayoutManager layoutManager;
public TestPagerViewHolder(#NonNull View itemView, IpagerAdapter mListener) {
super(itemView);
this.mListener = mListener;
image_post = itemView.findViewById(R.id.post_image);
image_profile = itemView.findViewById(R.id.image_profile);
like = itemView.findViewById(R.id.like_ic);
share_post= itemView.findViewById(R.id.share_post);
comment = itemView.findViewById(R.id.comment_ic);
save = itemView.findViewById(R.id.save);
username = itemView.findViewById(R.id.username);
likes = itemView.findViewById(R.id.likes);
comments = itemView.findViewById(R.id.comments);
tagList = itemView.findViewById(R.id.tagList);
title = itemView.findViewById(R.id.title);
time = itemView.findViewById(R.id.time);
btn_post_options = itemView.findViewById(R.id.post_options);
}
}
public interface IpagerAdapter {
void removePost(String post_id, String post_image, int position);
void openBsComment();
void sharePost(Bitmap postImage);
}
private void getComments(String postid, TextView comments) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Comments").child(postid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.getChildrenCount() != 0) {
comments.setText(" " + snapshot.getChildrenCount());
} else {
comments.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void getTimeAgo(TextView time, String stamp_post) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");;
Log.i(TAG, "timestamp value in format date: "+ stamp_post);
try {
long timeStamp = sdf.parse(stamp_post).getTime();
long now = System.currentTimeMillis();
CharSequence ago = DateUtils.getRelativeTimeSpanString(timeStamp, now, DateUtils.MINUTE_IN_MILLIS);
Log.i(TAG, "timestamp milli value is: " + timeStamp);
time.setText(ago);
} catch (ParseException e) {
e.printStackTrace();
}
}
private void asLiked(String postid, final ImageView imageView) {
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Likes").child(postid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.child(firebaseUser.getUid()).exists()) {
imageView.setImageResource(R.drawable.liked);
imageView.setTag("liked");
} else {
imageView.setImageResource(R.drawable.ic_like);
imageView.setTag("like");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void nLikes(final TextView likes, String postid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Likes").child(postid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
likes.setText(" "+ snapshot.getChildrenCount());
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void isSaved(String postid, final ImageView imageView) {
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Saved").child(firebaseUser.getUid());
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.child(postid).exists()) {
imageView.setImageResource(R.drawable.ic_bookmark_colored);
imageView.setTag("saved");
} else {
imageView.setImageResource(R.drawable.ic_save_post);
imageView.setTag("save");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void publisherInfo(ImageView image_profile, TextView username, String userid) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("App_users")
.child(userid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
User user = snapshot.getValue(User.class);
Glide.with(mContext.getApplicationContext()).load(user.getimageUrl()).into(image_profile);
username.setText(user.getUsername());
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
public void removeItem(int position) {
if (position > -1 && position < mPost.size()) {
mPost.remove(position);
notifyDataSetChanged();
notifyItemRemoved(position);
}
}
}

CardView with RelativeLayout not updating properly after click

I am trying to change one of my textview(Status) when clicked but it just removes the current text and displays my original text's text.
The textview currently display either "Not Taken" or "Pending" depending on what data is retrieved from my db.
My pop up dialog fragment code that shows the card items in a recyclerview.
public class FragmentLocationPopup extends DialogFragment {
View mView;
TextView tvSelectedBranch;
RecyclerView mScheduleList;
ScheduleAdapter mAdapter;
RecyclerView.LayoutManager mLayoutManager;
String TAG = "DialogFragment";
ArrayList<Schedule> scheduleList;
VariablesHolder variablesHolder;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_location_popup, container, false);
createScheduleList();
buildRecyclerView();
return mView;
}
public void createScheduleList(){
scheduleList = new ArrayList<>();
tvSelectedBranch = mView.findViewById(R.id.tvSelectedBranch);
variablesHolder = (VariablesHolder) getActivity().getApplicationContext();
String selectedBranch = variablesHolder.getSelectedBranch();
tvSelectedBranch.setText(selectedBranch);
Log.d(TAG, "Selected branch = "+selectedBranch);
Call<List<Schedule>> call = RetrofitClient.getInstance().getApiDate().getSchedule();
call.enqueue(new Callback<List<Schedule>>() {
#Override
public void onResponse(Call<List<Schedule>> call, Response<List<Schedule>> response) {
List<Schedule> schedules = response.body();
for (Schedule schedule : schedules) {
if(schedule.getBranchID().equals(variablesHolder.getBranchID())) {
scheduleList.add(new Schedule(schedule.getWorkScheduleFromDateTime(), schedule.getWorkScheduleToDateTime(),schedule.getWorkScheduleStatus()));
Log.d(TAG, "onResponse: " + schedule.getWorkScheduleFromDateTime() + " and " + schedule.getWorkScheduleToDateTime() + " and "+schedule.getWorkScheduleStatus());
}
}
}
#Override
public void onFailure(Call<List<Schedule>> call, Throwable t) {
}
});
String asd = ""+variablesHolder.getBranchIdList();
Log.d(TAG, "onCreateView: "+asd);
}
public void buildRecyclerView(){
mScheduleList = mView.findViewById(R.id.rvScheduleList);
mScheduleList.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(mView.getContext());
mAdapter = new ScheduleAdapter(scheduleList);
mScheduleList.setLayoutManager(mLayoutManager);
mScheduleList.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ScheduleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
changeItem(position, "Clicked");
}
});
}
public void changeItem(int position, String text){
scheduleList.get(position).changeText1(text);
mAdapter.notifyItemChanged(position);
Log.d(TAG, "changeItem: "+position+" / "+text);
}
}
My schedule class (I only use 3 variables in it at the moment) workfromtime, worktotime, and workstatus
public class Schedule {
private String workScheduleID;
private Date workScheduleFromDateTime;
private Date workScheduleToDateTime;
private String workScheduleStatus;
private String workDescriptionID;
private String branchID;
private String staffID;
private String managerID;
private String workScheduleBidDateTime;
public Schedule(Date workScheduleFromDateTime, Date workScheduleToDateTime,String workScheduleStatus) {
this.workScheduleFromDateTime = workScheduleFromDateTime;
this.workScheduleToDateTime = workScheduleToDateTime;
this.workScheduleStatus = workScheduleStatus;
}
public void changeText1(String workScheduleStatus){
this.workScheduleStatus = workScheduleStatus;
}
public String getWorkScheduleID(){return workScheduleID;}
public Date getWorkScheduleFromDateTime(){return workScheduleFromDateTime;}
public Date getWorkScheduleToDateTime(){return workScheduleToDateTime;}
public String getWorkScheduleStatus(){return workScheduleStatus;}
public String getWorkDescriptionID(){return workDescriptionID;}
public String getBranchID(){return branchID;}
public String getStaffID(){return staffID;}
public String getManagerID(){return managerID;}
public String getWorkScheduleBidDateTime(){return workScheduleBidDateTime;}
}
Adapter class
public class ScheduleAdapter extends RecyclerView.Adapter<ScheduleAdapter.ScheduleViewHolder> {
private static final String TAG = "ScheduleAdapter";
private ArrayList<Schedule> mScheduleList;
private OnItemClickListener mListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public static class ScheduleViewHolder extends RecyclerView.ViewHolder{
public TextView FromTime,ToTime,ScheduleStatus,Tester;
public ScheduleViewHolder(#NonNull final View itemView, final OnItemClickListener listener) {
super(itemView);
FromTime = itemView.findViewById(R.id.tvFromTime);
ToTime = itemView.findViewById(R.id.tvToTime);
ScheduleStatus = itemView.findViewById(R.id.tvStatus);
Tester = itemView.findViewById(R.id.tvTest);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(position);
}
}
}
});
}
}
public ScheduleAdapter(ArrayList<Schedule> scheduleList ){
mScheduleList = scheduleList;
}
#NonNull
#Override
public ScheduleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.schedule_item,parent,false);
ScheduleViewHolder svh = new ScheduleViewHolder(mView, mListener);
return svh;
}
#Override
public void onBindViewHolder(#NonNull ScheduleViewHolder holder, int position) {
Schedule currentSchedule = mScheduleList.get(position);
Log.d(TAG, "onBindViewHolder: "+currentSchedule.getWorkScheduleFromDateTime() + " and "+currentSchedule.getWorkScheduleToDateTime());
String FromTimeRegion = currentSchedule.getWorkScheduleFromDateTime().toString().replace("GMT 2020","");
String ToTimeRegion = currentSchedule.getWorkScheduleToDateTime().toString().replace("GMT 2020","");
String status = currentSchedule.getWorkScheduleStatus();
Log.d(TAG, "onBindViewHolder: "+status);
if(status.toLowerCase().equals("pending")) {
holder.ScheduleStatus.setText("Pending");
holder.ScheduleStatus.setTextColor(Color.parseColor("#FFFF00"));
}
if(status.toLowerCase().equals("not taken")) {
holder.ScheduleStatus.setText("Not Taken");
holder.ScheduleStatus.setTextColor(Color.parseColor("#7FFF00"));
}
holder.FromTime.setText("From: "+FromTimeRegion);
holder.ToTime.setText("To: "+ToTimeRegion);
}
#Override
public int getItemCount() {
return mScheduleList.size();
}
}
Please advice.
I found out that it is caused by this part of my code.
if(status.toLowerCase().equals("pending")) {
holder.ScheduleStatus.setText("Pending");
holder.ScheduleStatus.setTextColor(Color.parseColor("#FFFF00"));
}
if(status.toLowerCase().equals("not taken")) {
holder.ScheduleStatus.setText("Not Taken");
holder.ScheduleStatus.setTextColor(Color.parseColor("#7FFF00"));
}
holder.FromTime.setText("From: "+FromTimeRegion);
holder.ToTime.setText("To: "+ToTimeRegion);
Just had to edit which comes first.

behavior explanation: Using LiveData to update adapter with DiffUtil

I am updating my recyclerview by using LiveData as below:
viewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
viewModel.getPurchaseList().observe(getViewLifecycleOwner(), new Observer<List<ProductsObject>>() {
#Override
public void onChanged(#Nullable List<ProductsObject> productsObjects) {
adapter.submitList(productsObjects);
//adapter.notifyDataSetChanged();
}
});
And I am using a FloatActionButton to change the value of my MutableLiveData as below:
FloatingActionButton fab = view.findViewById(R.id.cart_fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewModel.setPurchasePrice(0, 101.2);
}
});
All the data gets changed and onChanged is called as expected, but it only updates my recyclerview when I enable the adapter.notifyDataSetChanged();
If I create a new ProductsObject inside the FAB and submit a new list, the recyclerview gets updated without calling adapter.notifyDataSetChanged(); as below:
FloatingActionButton fab = view.findViewById(R.id.cart_fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//viewModel.setPurchaseAmount(0, 101.2);
ProductsObject prod = new ProductsObject("6666", 5, 152.2, "new product");
List<ProductsObject> prodList = new ArrayList<>();
prodList.add(prod);
adapter.submitList(prodList);
}
});
I appreciate if anyone could explain why.
Here is my adapter:
public class CartFragAdapter extends RecyclerView.Adapter<CartFragAdapter.CartFragViewHolder> {
private static final String TAG = "debinf PurchaseAdap";
private static final DiffUtil.ItemCallback<ProductsObject> DIFF_CALLBACK = new DiffUtil.ItemCallback<ProductsObject>() {
#Override
public boolean areItemsTheSame(#NonNull ProductsObject oldProduct, #NonNull ProductsObject newProduct) {
Log.i(TAG, "areItemsTheSame: old is "+oldProduct.getCode()+" ; new is "+newProduct.getCode());
return oldProduct.getCode().equals(newProduct.getCode());
}
#Override
public boolean areContentsTheSame(#NonNull ProductsObject oldProduct, #NonNull ProductsObject newProduct) {
Log.i(TAG, "areContentsTheSame: old is "+oldProduct.getPrice()+" ; new is "+newProduct.getPrice());
return oldProduct.getPrice() == newProduct.getPrice();
}
};
private AsyncListDiffer<ProductsObject> differ = new AsyncListDiffer<ProductsObject>(this, DIFF_CALLBACK);
#NonNull
#Override
public CartFragViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_purchase, parent, false);
return new CartFragViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CartFragViewHolder holder, int position) {
final ProductsObject purchaseList = differ.getCurrentList().get(position);
holder.mCode.setText(purchaseList.getCode());
holder.mPrice.setText(String.valueOf(purchaseList.getPrice()));
holder.mDescription.setText(purchaseList.getDescription());
}
#Override
public int getItemCount() {
Log.i(TAG, "getItemCount");
return differ.getCurrentList().size();
}
public void submitList(List<ProductsObject> products){
Log.i(TAG, "submitList: products.size is "+products.size());
differ.submitList(products);
}
public class CartFragViewHolder extends RecyclerView.ViewHolder {
public TextView mCode, mPrice, mDescription;
public CartFragViewHolder(#NonNull View itemView) {
super(itemView);
mCode = (TextView) itemView.findViewById(R.id.item_productCode);
mPrice = (TextView) itemView.findViewById(R.id.item_productPrice);
mDescription = (TextView) itemView.findViewById(R.id.item_productDescription);
}
}
}
And here is my ViewModel:
public class MyViewModel extends ViewModel {
MutableLiveData<List<ProductsObject>> purchaseList = new MutableLiveData<>();
public LiveData<List<ProductsObject>> getPurchaseList() {
return purchaseList;
}
public void setPurchasePrice(int position, double price) {
List<ProductsObject> itemList = purchaseList.getValue();
if (itemList != null && itemList.get(position) != null) {
Log.i("debinf ViewModel", "setPurchaseAmount: "+itemList.get(position).getPrice());
itemList.get(position).setPrice(price);
purchaseList.postValue(itemList);
}
}
}
AsyncListDiffer saves only the reference of the list. This means that if you submit a modified list instead of submitting a new list, AsncListDiffer won't be able to detect any difference because both the previous list and the new list are referencing the same list with the same items.
To fix this you need to create a new list and new item. Change MyViewModel#setPurchasePrice as below:
public void setPurchasePrice(int position, double price) {
List<ProductsObject> itemList = purchaseList.getValue();
if (itemList != null && itemList.get(position) != null) {
List<ProductsObject> newList = new ArrayList<>();
for (int i = 0; i < itemList.size(); i++) {
ProductsObject prevProd = itemList.get(i);
if (i != position) {
newList.add(prevProd);
} else {
ProductsObject newProd = new ProductsObject(..., price, ...);
newList.add(newProd);
}
}
purchaseList.postValue(newList);
}
}

Resources