I need to pass data from recyclerView adapter to main activity on click on image of recyclerview. Can someone help?
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoHolder> {
private ArrayList<Video> mData;
private ArrayList<Video> mData2;
private Activity mACtivity;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
}
#Override
public VideoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.anteprima_list_item, parent, false);
//view.setOnClickListener(mOnClickListener);
return new VideoHolder(view);
}
#Override
public void onBindViewHolder(VideoHolder holder, int position) {
Video video = mData.get(position);
final Video video2 = mData2.get(position);
holder.setTitolo(video.getTitolo());
holder.setSottoTitolo(video.getSottotitolo());
holder.setData(video.getData());
holder.setData(video.getData());
/* holder.setAddress(restaurant.getAddress());
holder.setCost("Average cost for 2: " + restaurant.getCurrency() + restaurant.getCost());
holder.setRating(restaurant.getRating());*/
Glide.with(mACtivity)
.load(video2.getPic())
.into(holder.restaurantImageView);
holder.restaurantImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// handle click event here
System.out.println("PIC"+video2.getPic());
}
});
}
#Override
public int getItemCount() {
if (mData == null)
return 0;
return mData.size();
}
public class VideoHolder extends RecyclerView.ViewHolder {
ImageView restaurantImageView;
TextView restaurantNameTextView;
TextView restaurantAddressTextView;
TextView restaurantRatingTextView;
TextView costTextView;
TextView distanceTextView;
LinearLayout linearlayout;
public VideoHolder(View itemView) {
super(itemView);
linearlayout=(LinearLayout) itemView.findViewById((R.id.linearlayout));
restaurantImageView = (ImageView) itemView.findViewById(R.id.imageview_restaurant);
restaurantNameTextView = (TextView) itemView.findViewById(R.id.textview_restaurant_name);
restaurantAddressTextView = (TextView) itemView.findViewById(R.id.restaurant_address_textview);
distanceTextView = (TextView) itemView.findViewById(R.id.restaurant_distance_textview);
/* costTextView = (TextView) itemView.findViewById(R.id.cost_for_two_textview);
restaurantRatingTextView = (TextView) itemView.findViewById(R.id.rating);*/
}
public void setTitolo(String titolo) {
restaurantNameTextView.setText(titolo);
}
public void setSottoTitolo(String sottotitolo) {
restaurantAddressTextView.setText(sottotitolo);
}
public void setData(String data) {
distanceTextView.setText(data);
}
/* public void setPic(String pic) {
distanceTextView.setText(pic);
}
public void setCost(String cost) {
costTextView.setText(cost);
}
public void setDistance(String distance) {
distanceTextView.setText(distance);
}*/
}
}
Create a listener Interface and let your MainActivity implement it. That way you can call your callback method in your onClick method.
Interface:
public interface OnImageClickListener {
void onImageClick(String imageData);
}
MainActivity:
public class MainActivity implements OnImageClickListener {
#Override
public void onImageClick(String imageData) {
// handle image data
}
//...
}
Your VideoAdapter:
//...
private OnImageClickListener onImageClickListener;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity, OnImageClickListener onImageClickListener) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
this.onImageClickListener = onImageClickListener;
}
//...
#Override
public void onBindViewHolder(VideoHolder holder, int position) {
//...
holder.restaurantImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onImageClickListener.onImageClick(video2.getPic());
}
});
//...
}
//...
If you want to pass value from onclick to your Parent activity, use onMethodCallback in your MainActivity:
public class MainActivity extends Activity implements AdapterCallback {
private MyAdapter mMyAdapter;
#Override
public void onMethodCallback(String yourValue) {
// get your value here
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mMyAdapter = new MyAdapter(this);
}
}
In your Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback mAdapterCallback;
public MyAdapter(Context context) {
try {
this.mAdapterCallback = ((AdapterCallback) context);
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.");
}
}
#Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mAdapterCallback.onMethodCallback();
}
});
}
public static interface AdapterCallback {
void onMethodCallback(String yourValue);
}
}
If you are working with kotlin, the solution is much simpler.
Original Answer here
pass the lamda val itemClick: (Int) -> Unit to your adapter.
class MyRecyclerViewAdapter(params , val itemClick: (Int) -> Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
internal inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...
itemView.setOnClickListener( {itemClick(layoutPosition)} )
}
}
In your Activity use the returned value position
val myAdapter = MyRecyclerViewAdapter(params) { position ->
// do something
}
Write interface in your adapter like bellow :
interface clickItemListener {
void onItemClick(String order);
}
And your constructor should be :
privat clickItemListener clickItemListeners;
public VideoAdapter(ArrayList<Video> data, ArrayList<Video> data2, Activity activity, clickItemListener clickItemListeners) {
this.mData = data;
this.mData2 = data2;
this.mACtivity = activity;
this.clickItemListeners = clickItemListeners;
}
Then you can pass to Activity :
yourLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickItemListeners.onItemClick(yourValue);
}
});
And implement your interface in your activity like bellow :
public class yourActivity extends AppCompatActivity implements
YourAdapter.clickItemListener{
#Override
public void onItemClick(String order) {
//You can get your value here
}
}
Remember that you should pass activity to adapter like bellow :
YourAdapter adapter = new YourAdapter (... , ... , ... , activity.this);
Related
There is a holder
public class ClientTivarHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView texttovarname,texttovarprice;
public RoundedImageView imageTovar;
public CardView cardTovar;
public ItemClickListener itemClickListener;
private Dialog dialog;
private Context context;
public ClientTivarHolder(View itemView){
super(itemView);
texttovarname=itemView.findViewById(R.id.texttovrnme);
texttovarprice=itemView.findViewById(R.id.pricetexttovar);
imageTovar=itemView.findViewById(R.id.tovarImage);
cardTovar=itemView.findViewById(R.id.tovarcard);
}
public void setItemClickListner(ItemClickListener listner){this.itemClickListener=listner;}
#Override
public void onClick(View view){
itemClickListener.onClick(view,getAdapterPosition(),false);
}
}
There is an adapter
public class TovarsAdapter {
private String TovarName,TovarOpisanie,TovarPrice,TovarImage,ShopPhone,ShopUid;
public TovarsAdapter(){
}
public TovarsAdapter(String tovarName, String tovarOpisanie, String tovarPrice, String tovarImage, String shopPhone, String shopUid) {
this. TovarName = tovarName;
this. TovarOpisanie = tovarOpisanie;
this. TovarPrice = tovarPrice;
this. TovarImage = tovarImage;
this. ShopPhone = shopPhone;
this. ShopUid = shopUid;
}
public String getTovarName() {
return TovarName;
}
public void setTovarName(String tovarName) {
TovarName = tovarName;
}
public String getTovarOpisanie() {
return TovarOpisanie;
}
public void setTovarOpisanie(String tovarOpisanie) {
TovarOpisanie = tovarOpisanie;
}
public String getTovarPrice() {
return TovarPrice;
}
public void setTovarPrice(String tovarPrice) {
TovarPrice = tovarPrice;
}
public String getTovarImage() {
return TovarImage;
}
public void setTovarImage(String tovarImage) {
TovarImage = tovarImage;
}
public String getShopPhone() {
return ShopPhone;
}
public void setShopPhone(String shopPhone) {
ShopPhone = shopPhone;
}
public String getShopUid() {
return ShopUid;
}
public void setShopUid(String shopUid) {
ShopUid = shopUid;
}
}
And the interface class ItemClickListener
public interface ItemClickListener {
void onClick(View view, int position, boolean isLongClick);
}
Activate itself where I want to implement it
public class TovarActivity extends AppCompatActivity {
private DatabaseReference tovars;
private RecyclerView recyclerView;
private String uid,srav;
RecyclerView.LayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tovar);
layoutManager=new GridLayoutManager(this,2);
Log.d("Uid",getIntent().getExtras().get("ShopUid").toString());
recyclerView=(RecyclerView) findViewById(R.id.tovarrec);
tovars= FirebaseDatabase.getInstance().getReference().child("Tovars");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerOptions<TovarsAdapter> options=new FirebaseRecyclerOptions.Builder<TovarsAdapter>()
.setQuery(tovars.orderByChild("ShopUid").equalTo(getIntent().getExtras().get("ShopUid").toString()),TovarsAdapter.class).build();
FirebaseRecyclerAdapter<TovarsAdapter, ClientTivarHolder> adapter=new FirebaseRecyclerAdapter<TovarsAdapter, ClientTivarHolder>(options) {
#Override
protected void onBindViewHolder( #androidx.annotation.NonNull ClientTivarHolder holder, int position, #androidx.annotation.NonNull TovarsAdapter model) {
holder.texttovarprice.setText(model.getTovarPrice());
holder.texttovarname.setText(model.getTovarOpisanie());
holder.texttovarname.setHint(model.getShopUid());
Transformation transformation=new RoundedTransformationBuilder().borderColor(Color.WHITE).borderWidthDp(3).cornerRadius(12).oval(false).build();
Picasso.get().load(model.getTovarImage()).transform(transformation).into(holder.imageTovar);
}
#Override
public ClientTivarHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_tovars,parent,false);
ClientTivarHolder holder=new ClientTivarHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
}
Problem: I don’t know how to make a listener on a separate item send a hint from it with a uid to receive certain information in the bottomsheetdialogfragmemt. I tried to make a fragment manager in the holder but it didn't work out. How can I solve my problem?
tried to make fragment manager inside holder but didn't work
i have recycler adapter like this
public class ShopUsersAdapter extends RecyclerView.Adapter<ShopUsersAdapter.MyViewHolder> implements View.OnClickListener {
private List<ShopUsersRecyclerModel> user_list;
private Context context;
private AdminCheckLocActivity activity;
private AdapterCallback mAdapterCallback;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView user;
public TextView type;
private ImageButton btn_loc;
public MyViewHolder(View view) {
super(view);
user = (TextView) view.findViewById(R.id.txt_text);
type =(TextView)view.findViewById(R.id.txt_count);
btn_loc=(ImageButton)view.findViewById(R.id.btn_loc);
}
}
#Override
public ShopUsersAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.map_pop_up_item, parent, false);
context=parent.getContext();
itemView.setOnClickListener(this);
return new ShopUsersAdapter.MyViewHolder(itemView);
}
#Override
public void onClick(View v) {
}
public ShopUsersAdapter(List<ShopUsersRecyclerModel> user_list, AdminCheckLocActivity activity) {
this.user_list = user_list;
this.activity=activity;
this.mAdapterCallback = ((AdapterCallback) context);
}
#Override
public void onBindViewHolder(final ShopUsersAdapter.MyViewHolder holder, int position) {
final ShopUsersRecyclerModel user = user_list.get(position);
holder.user.setText(user.getUser_info());
if (user.getUser_type()==3){holder.type.setText("TV Pro.");}
if (user.getUser_type()==4){holder.type.setText("B. Esya Pro.");}
holder.btn_loc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mAdapterCallback.onMethodCallback(user.getUser_info());
}
});
}
#Override
public int getItemCount() {
return user_list.size();
}
public interface AdapterCallback {
void onMethodCallback(String userName);
}
}
but i get error
NullPointer at
mAdapterCallback.onMethodCallback(user.getUser_info());
my activity code;
#Override
public void onMethodCallback(final String userName) {
Toast.makeText(this,userName,Toast.LENGTH_LONG).show();
}
and i implement this like ;
implements ShopUsersAdapter.AdapterCallback
userInfo data is not null, i check this. but i need this callback all of my recyclers please help me.
I suggest changing your adapter's constructor to directly receive a callback:
public ShopUsersAdapter(List<ShopUsersRecyclerModel> user_list, AdminCheckLocActivity activity, AdapterCallback callback) {
this.user_list = user_list;
this.activity=activity;
this.mAdapterCallback = callback;
}
You can also make sure your callback isn't null when you're utilizing it:
holder.btn_loc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// This should be optional for your case
// but it can be useful if you're ever in a situation
// where the callback isn't always available
if(mAdapterCallback != null){
mAdapterCallback.onMethodCallback(user.getUser_info());
}
}
});
And within your Activity, make sure to pass in the callback as an argument when you create your Adapter instance:
// Use 'this' since your Activity implements the callback
ShopUsersAdapter adapter = new ShopUsersAdapter(myList, myActivity, this);
I have an Adapter (A ViewHolder) Class, and when a Button is pressed I'd like to update a TextView of the Home() activity, preferrably without launching the activity immediatly.
The code in the Adapter:
public class GameViewAdapter extends RecyclerView.Adapter<GameViewAdapter.GameViewHolder> {
public static Object OnItemClickListener;
private ArrayList<GameItem> mGameList;
private OnItemClickListener mListener;
public static MyCallback callback;
public GameViewAdapter(ArrayList<GameItem> mGameList, GameViewAdapter.OnItemClickListener mListener, MyCallback callback) {
this.mGameList = mGameList;
this.mListener = mListener;
this.callback = callback;
}
#Override
public GameViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
Context context = viewGroup.getContext();
View v = LayoutInflater.from(context).inflate(R.layout.game_entry, viewGroup, false);
GameViewHolder GVH = new GameViewHolder(v, mListener);
return GVH;
}
#Override
public void onBindViewHolder(#NonNull GameViewHolder gameViewHolder, int position) {
gameViewHolder.bind(mGameList.get(position));
}
#Override
public int getItemCount() {
return mGameList.size();
}
class GameViewHolder extends RecyclerView.ViewHolder {
private ImageView itemCover;
private TextView itemTitle;
private TextView itemDescription;
private PopupWindow popupWindow;
private ImageView popUpImage;
private TextView PopUpTitle;
private EditText customAmount;
private Button add;
private Button addcustom;
private Button exit;
public GameViewHolder(View itemView, GameViewAdapter.OnItemClickListener mListener) {
super(itemView);
setupViews(itemView);
}
public void bind(final GameItem gameItem) {
Glide.with(this.itemCover).load(gameItem.getCover()).into(this.itemCover);
this.itemTitle.setText(gameItem.getTitle());
this.itemDescription.setText(gameItem.getDescription());
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showPopUp(itemView, gameItem);
}
});
}
private void setupViews(View itemView) {
addcustom = itemView.findViewById(R.id.addcustom);
popUpImage = itemView.findViewById(R.id.popupimg);
PopUpTitle = itemView.findViewById(R.id.popuptitle);
customAmount = itemView.findViewById(R.id.gameamount);
itemCover = itemView.findViewById(R.id.GameCover);
itemTitle = itemView.findViewById(R.id.GameTitle);
itemDescription = itemView.findViewById(R.id.GameAmount);
exit = itemView.findViewById(R.id.exit);
}
private void showPopUp(final View itemView, final GameItem gameItem) {
//Declaration
final View popupView = LayoutInflater.from(itemView.getContext()).inflate(R.layout.popup, null);
final PopupWindow popupWindow = new PopupWindow(popupView, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
final ImageView popupItemCover = popupView.findViewById(R.id.popupimg);
final TextView popupItemTitle = popupView.findViewById(R.id.popuptitle);
//Set Data
Glide.with(popupItemCover).load(gameItem.getCover()).into(popupItemCover);
popupItemTitle.setText(gameItem.getTitle());
popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
//ExitButton
exit = popupView.findViewById(R.id.exit);
exit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popupWindow.dismiss();
}
});
add = popupView.findViewById(R.id.addaverage);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
Toast.makeText(popupView.getContext(), String.valueOf(gameItem.getTime()), Toast.LENGTH_SHORT).show();
}
});
}
}
public interface MyCallback {
void onDataChanged(Integer gameTime);
}
public interface OnItemClickListener {
void onGameClick(int position);
}
}
And I have implemented this in the Main Activity:
public void onDataChanged(int gameTime) {
// it will fire when you call your callback.onDataChanged(); in your adapter
// here can change your textview
GameTime.setText(Integer.valueOf(gameTime));
}
}
I've tried to use BroadcastReceiver as well, with no success.
Thank you!
EDIT:
When adding the callback my App crashes with following traceback:
java.lang.NullPointerException: Attempt to invoke interface method 'void com.reogen.gametime.Adapters.GameViewAdapter$MyCallback.onDataChanged(java.lang.String)' on a null object reference
at com.reogen.gametime.Adapters.GameViewAdapter$GameViewHolder$3.onClick(GameViewAdapter.java:127)
Line 127 is: callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
You can create observable like:
in your Adapter create:
public interface IMyCallback {
void onDataChanged(int gameTime);
}
Global field in Adapter:
private IMyCallback callback
Inside constructor of Adapter
public MyAdapter(... , IMyCallback callback) {
...
this.callback = callback;
}
Now your activity make implements IMyCallback and override method onDataChanged.
And when you create your adapter send as callback YourActivity.this.
finnaly you need to make like:
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
}
after this call you will get update in your override method onDataChanged in your activity class. enjoy
------------ Update -----------
in your activity, when you will implements interface you will get method like
#Override
public void onDataChanged(int gameTime) {
// it will fire when you call your callback.onDataChanged(); in your adapter
// here can change your textview
textview.setText(String.valueOf(gameTime));
}
I am trying to set the data for recycler view to display from an AsyncTask. I am calling the method setdataEntries from the postExecute of inner class AsyncTask. But the android studio is showing me error could not find the method.
Adapter class
public class EntryAdapter extends RecyclerView.Adapter<EntryAdapter.ViewHolder> {
List<UserTuple> entries;
final private itemClickListener mOnClickListener;
public interface itemClickListener{
void onItemClick(UserTuple utuple);
}
public EntryAdapter(itemClickListener clickhandler) {
mOnClickListener = clickhandler;
}
public void setdataEntries(List<UserTuple> Data) {
entries = Data;
notifyDataSetChanged();
}
#Override
public EntryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.singleusertuple,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(EntryAdapter.ViewHolder holder, int position) {
holder.Username.setText(entries.get(position).getUsername());
holder.Password.setText(entries.get(position).getPassword());
}
#Override
public int getItemCount() {
return entries.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView Username;
private TextView Password;
private CardView card;
public ViewHolder(View itemView) {
super(itemView);
Username = itemView.findViewById(R.id.susername);
Password=itemView.findViewById(R.id.pass);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
UserTuple ut=new UserTuple(entries.get(adapterPosition).getUsername(),entries.get(adapterPosition).getPassword());
mOnClickListener.onItemClick(ut);
}
}
}
Calling Activity
public class Usertuple extends AppCompatActivity implements EntryAdapter.itemClickListener {
private RecyclerView recyclerView ;
private RecyclerView.Adapter adapater;
private SnapHelper snapHelper;
private List<UserTuple> entries;
private ProgressBar mLoadingIndicator;
private Bundle extras;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logins);
extras = getIntent().getExtras();
//String site= extras.getString("sitename");
mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);
Log.i("Logins","Size of returned list "+entries.size());
recyclerView = findViewById(R.id.recycleview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
adapater = new EntryAdapter(this);
recyclerView.setAdapter(adapater);
snapHelper= new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
dataView();
}
public void dataView() {
String site= extras.getString("sitename");
recyclerView.setVisibility(View.VISIBLE);
new FetchDataTask().execute(site);
}
#Override
public void onItemClick(UserTuple utuple) {
}
private String key(){
SharedPreferences sharedPref = getSharedPreferences(
"User", this.MODE_PRIVATE);
final String passphrase = sharedPref.getString("userid", "none");
return passphrase;
}
public void showerror(){
recyclerView.setVisibility(View.GONE);
Toast.makeText(this,"Error in retrieving",Toast.LENGTH_SHORT).show();
}
public setdata(List<UserTuple> data){
adapater.setdataEntries(data);
}
public class FetchDataTask extends AsyncTask<String, Void, List<UserTuple>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mLoadingIndicator.setVisibility(View.VISIBLE);
}
#Override
protected List<UserTuple> doInBackground(String... params) {
/* If there's no zip code, there's nothing to look up. */
if (params.length == 0) {
return null;
}
String site = params[0];
try {
AppDatabase db = Room.databaseBuilder(getApplicationContext(),AppDatabase.class, "production")
.build();
entries =db.entryDao().getSpecific(site);
for(UserTuple ut : entries){
Log.i("password",ut.getPassword());
String st = new Decryption().decrypt(ut.getPassword(),key());
Log.i("After decryption",st);
ut.setPassword(st);
}
return entries;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(List<UserTuple> Data) {
mLoadingIndicator.setVisibility(View.INVISIBLE);
if (Data != null) {
adapater.setdataEntries(Data);
} else {
showerror();
}
}
}
}
I want the database calls to be a background task. I don't want the activity to freeze waiting for database calls. Any ideas? Thanks
Declare adapter like
private EntryAdapter adapter;
instead of
private RecyclerView.Adapter adapater;
because RecyclerView.Adapter class does not have any method named setdataEntries but only EntryAdapter class has this method so only the object of type EntryAdapter can call setdataEntries method.
Or you can use down-casting as
((EntryAdapter)adapater).setdataEntries(data);
I have multiple ViewHolders that work as separated views inside a vertical RecyclerView. I'm practicing with the new Architecture Components ViewModel.
Inside my ViewModel I have a couple of MutableLiveData lists that i want to observe, but how can I call
ViewModelProviders.of((AppCompatActivity)getActivity()).get(FilterViewModel.class)
and
mFilterViewModel.getCountries().observe(this, new Observer<ArrayList<TagModel>>() {
#Override
public void onChanged(#Nullable ArrayList<TagModel> tagModels) {
}
});
without leaking the activity or save the activity inside the adapter?
my ViewModel
public class FilterViewModel extends ViewModel {
private final MutableLiveData<ArrayList<TagModel>> mCountries;
private final MutableLiveData<ArrayList<TagModel>> mSelectedCountryProvinceList;
private final MutableLiveData<ArrayList<TagModel>> mDistanceList;
public FilterViewModel(){
mCountries = new MutableLiveData<>();
mSelectedCountryProvinceList = new MutableLiveData<>();
mDistanceList = new MutableLiveData<>();
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mCountries.setValue(object.getCountries());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 5){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(5,"parent");
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mSelectedCountryProvinceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 6){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(6,"parent");
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mDistanceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == 51){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(51,"parent");
}
public void selectCountry(final TagModel country){
TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() {
#Override
public void update(TagSearchList object) {
mSelectedCountryProvinceList.setValue(object.toList());
}
#Override
public void update(int id, TagSearchList object) {
if (id == country.getId()){
TagStore.getInstance().unSubcribe(this);
update(object);
}
}
#Override
public void error(String error) {
}
}).get(country.getId(),"parent");
}
public LiveData<ArrayList<TagModel>> getCountries(){
return mCountries;
}
public LiveData<ArrayList<TagModel>> getDistances(){
return mDistanceList;
}
public LiveData<ArrayList<TagModel>> getProvinces(){
return mSelectedCountryProvinceList;
}
I am using Room Persistence library. Below is my code for recyclerview adapter using MVVM.
You can see CartViewModel and I have initialized it into the constructor. The constructor gets the context from the activity, and I have cast it into FragmentActivity.
private CartViewModel cartViewModel;
public CartListAdapter(Context context, List<CartModel> cartModels) {
this.context = context;
this.cartModels = cartModels;
cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class);
}
Here is my full adapter class. I hope it will help.
public class CartListAdapter extends RecyclerView.Adapter<CartListAdapter.CartListViewHolder> {
private static final String TAG = "CartListAdapter";
private Context context;
private List<CartModel> cartModels;
private Double totalQuantity = 0.0;
private CartViewModel cartViewModel;
public CartListAdapter(Context context, List<CartModel> cartModels) {
this.context = context;
this.cartModels = cartModels;
cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class);
}
#NonNull
#Override
public CartListViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CartListViewHolder(LayoutInflater.from(context).inflate(R.layout.list_all_cart_item,parent,false));
}
#Override
public void onBindViewHolder(#NonNull CartListViewHolder holder, int position) {
CartModel cartModel = cartModels.get(position);
Glide.with(context)
.load(cartModel.getPPICLocate())
.into(holder.cartItemImage);
holder.tvCartProductName.setText(cartModel.getProductName());
holder.tvCartProductCategory.setText(cartModel.getPCategorySubID());
holder.tvCartProductPrice.setText(cartModel.getPPriceSales());
holder.etCartProductQuantity.setText(cartModel.getPQuantity());
holder.btnCartPQtIncrease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString());
totalQuantity = totalQuantity+1;
cartModel.setPQuantity(totalQuantity.toString());
updateCart(cartModel);
}
});
holder.btnCartPQtDecrease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString());
totalQuantity = totalQuantity-1;
cartModel.setPQuantity(totalQuantity.toString());
updateCart(cartModel);
}
});
}
#Override
public int getItemCount() {
return cartModels.size();
}
public class CartListViewHolder extends RecyclerView.ViewHolder{
private ImageView cartItemImage;
private TextView tvCartProductName,tvCartProductCategory,tvCartProductPrice,
etCartProductQuantity,tvCartProductPrevPrice;
private ImageButton btnCartPQtIncrease,btnCartPQtDecrease;
public CartListViewHolder(#NonNull View itemView) {
super(itemView);
cartItemImage= itemView.findViewById(R.id.cartItemImage);
tvCartProductName= itemView.findViewById(R.id.tvCartProductName);
tvCartProductCategory= itemView.findViewById(R.id.tvCartProductCategory);
tvCartProductPrice= itemView.findViewById(R.id.tvCartProductPrice);
etCartProductQuantity= itemView.findViewById(R.id.etCartProductQuantity);
tvCartProductPrevPrice= itemView.findViewById(R.id.tvCartProductPrevPrice);
btnCartPQtIncrease= itemView.findViewById(R.id.btnCartPQtIncrease);
btnCartPQtDecrease= itemView.findViewById(R.id.btnCartPQtDecrease);
}
}
public void addItems(List<CartModel> cartModels) {
this.cartModels = cartModels;
notifyDataSetChanged();
}
private void updateCart(CartModel cartModel){
String tqt = String.valueOf(cartModel.getPQuantity());
Log.d(TAG, "updateQuantity: "+tqt);
/*cartRepository.updateCartRepo(cartModel);*/
cartViewModel.updateCartItemVM(cartModel);
}
}
You could create an OnClickListener interface instead, then implement the onClick method (defined in your interface) in your fragment or activity where you have access to your view model.
My solution to this issue is;
create a new variable(ViewModel) for the layout (fragment or activity layout)
in your activity or fragment get the instance of your viewModel with ViewModelProviders
hold the data which fills your recyclerView in MutableLiveData and observe it and fill the adapter of recyclerView with the value you observed
here you mut be careful not to create adapter instance in observe method.
if you create it in observe method, it will make leaks