Activity A has a recycler view, which has each row as a post, now each post has a comment count textview which launches a comment activity where user can see comments and also add comments.
Now question is, after adding a comment how do I update the comment count in that particular row of recycler view in Activity A when comment Activity finishes or pressing back button to get back on posts page. But I don't want to reload the recycler view again as it will distract the user from the current location.
Please guide me in the right direction. Below is my Recyclerview adapter code snippet.
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
int viewType = getItemViewType(position);
final Posts posts = postsList.get(position);
final viewHolderPost viewHolderPost = (viewHolderPost) viewHolder;
viewHolderPost.commentcount_wrap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), CommentViewerActivity.class);
intent.putExtra("post_id", posts.getPost_id());
v.getContext().startActivity(intent);
}
});
}
Okay here is what I would do:
Create common object (preferably Repository), where I would store list of Posts with Comments in memory.
When clicking on Post, I would call startActivityForResult method from PostActivity to open CommentActivity
After adding/deleting/editing the comment in CommentActivity I would update the list in Repository and finish activity with proper result
In PostActivity I would override onActivityResult method to check if the CommentActivity finished with result that will tell me to refresh list in RecyclerView
If so, I would get the updated list from repository in PostActivity and update it in Adapter
You can use startActivityForResult instead of startActivity
Ref: https://developer.android.com/reference/android/app/Activity#startActivityForResult(android.content.Intent,%20int,%20android.os.Bundle)
So when the CommentActivity is finish, the previous activity will receive a callback that is the result of CommentActivity, you will handle that result and update your recyclerview's adapter.
Hope that help. :)
You could notify the Adapter that there is a change at the particular position.
check: adapter.notifyItemChanged(1)
-edit-
On your Activity A add this.
override fun onResume() {
super.onResume()
if(lastPosition != -1)
recycler_test.adapter?.notifyItemChanged(lastPosition)
}
And your adapter should provide a callback like this.
recycler_test.adapter = CustomAdapter(Controller.shared.myList){ positionClicked ->
//This block of code will be called every time a user clicked a comment.
lastPosition = positionClicked
val intent = Intent(applicationContext, ActivityB::class.java)
intent.putExtra("position", positionClicked)
startActivity(intent)
}
Related
I'm stuck by a problem and I don't know how too resolve it.
I want to click on my item in my recycler view, and at this click the layout with the recylcer view will be closed, and my mainActivity will be refresh with the data of the item who i have click on.
you start new activity to get Data but here you start a normal intent you need to start Activity For Result like
startActivityForResult(intent,REQUEST_CODE);
or new Way
ActivityResultLauncher<Intent> result = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if(result.getResultCode() == RESULT_OK){
String data = result.getData().getStringExtra("Data");
// here your data come from next Activity
}
}
});
then call result by
result.launch(Intent);
and in other Activity activity
you need to call
setResult(RESULT_OK,Intent);
finish();
this intent hold your data and will return to previous activity with it
After 2 hours in the sauce I have resolve that and I'm very happy.
The problem with the setResult() and the finish() but if you apply this code
((StructureEnFeuActivity)context).setResult(RESULT_OK, intent);
((StructureEnFeuActivity)context).finish();
You will not have the probleme with "static".
So I'm happy.
And thank you for all.
I'am trying to delete a card having in recyclerview. The problem is when i click the delete button in my card the changes does not reflect the next activity. When i click Delete Button the textview and the imageview must change accordingly. But that is not happening.
this is my onclick in viewHolder. I have used Interface. :
public void onClick(View view)
{
//get data from array list
if(view.getId()==R.id.cont_root){
if(itemClickCallback!=null) {
itemClickCallback.onRootClick(getAdapterPosition());
}
}
else{
delete(getAdapterPosition());
}
}
}
This is my delete Method in the adapter :
public void delete( int position){
listData.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, getItemCount()-1);
}
This is my code when a Cardview is clicked .Card's name is Root.
public void onRootClick(int p) {
//adapter.setItemClickCallback(this);
adapter.notifyItemChanged(p);
ListItem item =(ListItem)listData.get(p);
Intent i = new Intent(this,SecondActivity.class);
Bundle extras=new Bundle();
extras.putString(EXTRA_QUOTE, item.getTitle());
extras.putInt(EXTRA_ATTR,item.getImageResID());
i.putExtra(BUNDLE_EXTRAS,extras);
startActivity(i);
}
Note : i have not used interface method for deleting the element.
Please help. Iam new to Recyclerview. :(
You have to use the Methodes which relate to "what user is seeing" I can call them (Layout side Methods) and they are :
getLayoutPosition()
findViewHolderForLayoutPosition(int)
The first one returns the view position in accordance to the Layout it self and not the adapter
and the second one returns the ViewHolder for the item in the given position of the data set
In your code you are using what i can call (Adapter side Method)
getAdapterPosition()
any changes using The (adapter side Methods) will not be reflected to Layout untill you use (the Layout side Methods)
Hope This helps
I want to thank you in advance for the solution to my question.
I have a custom adapter for my listview. the list item has an imageView(1), a progressBar(3), and a download button(2).
When the download button for each list item is clicked, I grab vital details of the listitem such as the position of the view, the resourceid of the button, the resource id of imageview and the resource id of progress bar, then i make an parcealable object of class "Download".
Download download = new Download();
download.setUrl(url);
download.setButtonResource(this.downloadBt.getId());
download.setCreativeWork(creativeWork);
download.setDownloadBt(this.downloadBt);
download.setProgressBarResource(this.progressBar.getId());
download.setProgressBar(this.progressBar);
download.setContext(activity);
download.setViewResource(view.getId());
Intent intent = new Intent(activity, BroadcastService.class);
intent.putExtra("download", download);
Log.e("download button", url);
activity.startService(intent);
I start a service which does the download and reports back using a broadcast. When this broadcast message is received I want to update the progress bar.
My problem is how to get the progress bar concerned from my mainactivity which receives the message. How do I reference this?
I am currently using a parcelable object to pass the resource id for the progressbar, all the way from the adapter to the service, then to the receiving activity(mainActivity) using the intent's putExtra(), then I do this at the mainActivity
Download download = (Download)intent.getParcelableExtra("download");
ProgressBar progressBar = (ProgressBar)findViewById(download.getProgressBarResource());`
The issue here is that always only returns the first item of the list, regardless of which listitem is clicked. I would want to get each unique listitem and update the progress bar and the download button. Thanks
I am assuming that you show this layout in a ListView or RecyclerView. First thing that need to do is, add a field for index in your Download class to identify the position in the list from where that button was pressed. Next, pass the index from your getView() or onBindViewHolder() to the function that creates the Download object and add that index to the object.
When you receive the when you broadcast any update from your Service, do include the index value. Now, in your code in your activity where you receive the broadcast value, extract the value of index and the progress. Now, you could write something like this to update the progress of that view in the list:
int index = ... //some value you received in broadcast
int progress = ...//some value you received in broadcast
View view = listView.getChildAt(index);
if (view != null) {
ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
if (progressBar != null) {
progressBar.setProgress(progress);
}
}
This can be one of the solution to your problem
First You need to pass progress value to the adapter that may be zero in start.
Implement setOnItemClickListener for your listview
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
//now point to your item position and do your stuff here
}
});
When ever you receive broadcast for download progress. Just update your ListView by Nullifying previous items with new items containing download progress values.
Not sure if this is what you looking for...
In you adapter. do below.. (I take a sample from my project which do a delete card from the list, when the delete button is clicked)
In getView function inside adapter.
Card card = list.get(position);
viewHolder.imgDelete.setTag(card);// --> i set the whole card info to tag
outside the adapter.
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = v.getId();
if (id == R.id.iv_delete_card) {
//System.out.println("---> Card: " + tag);
//delete card
Object tag = v.getTag();
if (tag != null && tag instanceof Card) {
promptDeleteCard((Card) tag);
}
}
}
When onActivityResult() is called after a user returns to the original activity I update the data for the RecyclerView and call notifyDataSetChanged() but onBindViewHolder() is not being called and the RecyclerView does not update.
If I run the same code to update the Recylerview from an onClick() trigger the RecyclerView does update properly. It's only when the updating code is called from onActivityResult() that the RecylerView does not update.
I tried updating the RecylerView by running the update method using the runOnUiThread() method but that didn't fix the issue. I have also tried all the relevant notify methods (i.e. notifyDataSetChanged() etc. ) of the RecyclerView.Adapter but I will just refer to the notifyDataSetChanged for simplicity.
Here is a basic reproduction of the problem:
//This code is in the Adapter, it removes an item from the arrayList and updates the RecylerView.
protected void refreshData(int position){
arrayListData.remove(position);
notifyDataSetChanged ();
}
//This code is in the ViewHolder. When refreshData() is called via the onClick() here the **RecylerView does successfully update**
#Override
public void onClick(View v) {
if (shouldRefreshData == true) {
refreshData(getAdapterPosition());
} else {
Intent secondActivity = new Intent(context, SecondActivity.class);
((Activity)context).startActivityForResult(secondActivity, Adapter.REQUEST_CODE);
}
}
//I set the result code is in the Second Activity like this
setResult(Adapter.REQUEST_CODE, usefulIntent);
//This code is in the original activity, it successfully runs, and the refreshData() method is called and I can see the data has been removed via log statements in the refreshData() method but the onBindViewHolder() method is never called
#Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
if (requestCode == Adapter.REQUEST_CODE) {
....
adapter.refreshData(positionRetrievedFromTheDataIntent);
}
}
Seeing as the refreshData() method does properly update the RecyclerView when it's called via an onClick() trigger it seems that that method is configured properly. I tried adding delay to the onActivityResult which would give the RecylervView time load any data before running the refreshData() method but that didn't fix the issue.
Can anyone see any problems in my code or tell me how to fix this problem?
I have looked over other SO questions but I couldn't find an applicable solution to this problem.
Thanks in advance
Ensure that you have called the:
finish();
after the setResult:
setResult(Adapter.REQUEST_CODE, usefulIntent);
In order to trigger the onActivityResult.
Also if the:
notifyDataSetChanged();
isn't working consider to reset the
setAdapter();
I have a listview in android that is filterable by a searchview in the action bar.
Each item in the list is clickable, and takes you to a different photo. What I did for this was:
//inside setOnItemClickListener...
String itemPosition = item.get(position).getItemURL();
Intent i = new Intent(this, NextActivity.class);
i.putExtra("key", itemPosition.toString());
startActivity(i);
It works great if I don't use the search function.. But once you try filtering the list, it loads the photo of the item that used to be in the same position.
My question/s: is there a way to tell android to refresh the positions upon filtering? I figured that if the positions refreshed along with the list, it would work okay.
Also, is there a better way to do what I am doing?
Full code: ad is a custom baseadapter that takes in context, list, implements Filterable
ad = new GridViewAdapter(this, item);
SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(ad);
swingBottomInAnimationAdapter.setAbsListView(activity_gridview_gv);
assert swingBottomInAnimationAdapter.getViewAnimator() != null;
swingBottomInAnimationAdapter.getViewAnimator().setInitialDelayMillis(DELAY);
activity_gridview_gv.setAdapter(swingBottomInAnimationAdapter);
activity_gridview_gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String itemPosition = item.get(position).getItemURL();
Intent i = new Intent(this, NextActivity.class);
i.putExtra("key", itemPosition.toString());
startActivity(i);
}
});
You can try this.
Write list getter and setter in your adapter.
Set new filtered list to adapter and perform
notifyDataSetChanged();
While everyone's answer is correct to some degree, it seems that I had a different issue at hand. The question is still valid and I will post my solution.
My problem wasn't with the adapter not being refreshed.
It was with the List "item" not being updated once the adapter is notified of the changes. See:
String itemPosition = item.get(position).getItemURL();
I never really updated "item". In fact, I was calling the old, unfiltered list! What happens next is the filter does work and update the list, but I end up using the old list "item". Therefore linking me to the former object in the same position.
The solution: Get the item's position on click.
Inside onItemClick:
MainGridItem filteredItem = (MainGridItem) ad.getItem(position);
String itemPosition = filteredItem.get(position).getItemURL();
What this does is get the position of the clicked item. Now, you end up with the correct position upon clicking.
Also, please let me know if there is a better way of doing what I did.