Recycler view open new activity - java

I implement another activity which needs to be open when click on card but i getting Error:(56, 48) error: incompatible types: anonymous Callback JSONResponse cannot be converted to Context even if i convert to JSONResponse then there is another error. Problem is in that JSONResponse but i can't solve it.
DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<AndroidVersion> android;
Context ctx;
public DataAdapter(ArrayList<AndroidVersion> android, Context ctx)
{
this.android = android;
this.ctx = ctx;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_row, viewGroup, false);
return new ViewHolder(view,ctx,android);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
viewHolder.tv_name.setText(android.get(i).getName());
viewHolder.tv_version.setText(android.get(i).getVer());
viewHolder.tv_api_level.setText(android.get(i).getApi());
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private TextView tv_name,tv_version,tv_api_level;
ArrayList<AndroidVersion> android = new ArrayList<AndroidVersion>();
Context ctx;
public ViewHolder(View view, Context ctx, ArrayList<AndroidVersion> android)
{
super(view);
this.android = android;
this.ctx = ctx;
view.setOnClickListener(this);
tv_name = (TextView)view.findViewById(R.id.tv_name);
tv_version = (TextView)view.findViewById(R.id.tv_version);
tv_api_level = (TextView)view.findViewById(R.id.tv_api_level);
}
#Override
public void onClick(View v) {
int i = getAdapterPosition();
AndroidVersion android = this.android.get(i);
Intent intent = new Intent(this.ctx, ContactDetails.class);
intent.putExtra("name_id",android.getName());
intent.putExtra("version_id",android.getVer());
intent.putExtra("api_level_id",android.getApi());
((Context) this.ctx).startActivity(intent);}
}
}
JSONResponse.java
public class JSONResponse {
private AndroidVersion[] android;
public AndroidVersion[] getAndroid() {
return android;}
}
mainActivity when i write this getting error
main

First issue,
to this:
adapter = new DataAdapter(data,MainActivity.this);
is giving error because: if you put this inside a callback, you are refering to the onResponse scope, you cannot use this, because is outside scope, for that reason you have to you use MainActivity.this or getApplicationContext();

Related

getActivity() in adapter

I'm loading ads in onClick of RecyclerView's adapter.
In fragment it is perfectly working in this code:
interstitialAd.loadAd(GDPR.getAdRequest(getActivity()));
But in adapter it is not working in these method I tried:
mInterstitialAd.loadAd(GDPR.getAdRequest(context));
I also tried this but it is not working:
mInterstitialAd.loadAd(GDPR.getAdRequest(this));
GDPR.getAdRequest's code is:
public static AdRequest getAdRequest(Activity activity) {
return new AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter.class, GDPR.getBundleAd(activity))
.build();
}
this is adapter's code:
public class VideosAdapter extends RecyclerView.Adapter<VideosAdapter.VideosViewHolder> {
private Context context;
private Video[] data;
private int layout;
private InterstitialAd mInterstitialAd;
public VideosAdapter(Context context, Video[] data, int layout) {
this.context = context;
this.data = data;
this.layout = layout;
}
#NonNull
#Override
public VideosViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(layout,null);
return new VideosViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull VideosViewHolder holder, final int position) {
final Video selectedItem = data[position];
holder.videoTitle.setText(selectedItem.getVideoTitle());
holder.videoCategoryTitle.setText(selectedItem.getCategoryName());
if (selectedItem.getVideoType().equals("0")){
String thumbImg = Constants.SERVER_IMG_FIRST + selectedItem.getVideoThumb();
Glide.with(context).load(Uri.parse(thumbImg)).into(holder.videoThumb);
}else {
// Get V and display img
Uri uri = Uri.parse(selectedItem.getVideoUrl());
String videoId = uri.getQueryParameter("v");
String thumbYtImg = Constants.YOUTUBE_IMG_FIRST + videoId + Constants.YOUTUBE_IMG_BACK;
Glide.with(context).load(Uri.parse(thumbYtImg)).into(holder.videoThumb);
}
String thumbCat = Constants.SERVER_IMG_FIRST + selectedItem.getCategoryThumb();
Glide.with(context).load(Uri.parse(thumbCat)).into(holder.videoCategoryThumb);
holder.videoInfoBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Constants.SETTINGS.getAdmob().equals("1")){
Constants.ADS_COUNT++;
if (Constants.ADS_COUNT>=Integer.valueOf(Constants.SETTINGS.getAdmobIntrestitialAdDisplayAfter())){
Constants.ADS_COUNT = 0;
mInterstitialAd = new InterstitialAd(context);
mInterstitialAd.setAdUnitId(Constants.SETTINGS.getAdmobIntrestitialId());
mInterstitialAd.loadAd(GDPR.getAdRequest(context));
mInterstitialAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
if(mInterstitialAd.isLoaded()){
mInterstitialAd.show();
}
}
#Override
public void onAdFailedToLoad(int errorCode) {
// Code to be executed when an ad request fails.
toDoOnInfoBtnClicked(position,data);
}
#Override
public void onAdClosed() {
// Code to be executed when the interstitial ad is closed.
toDoOnInfoBtnClicked(position,data);
}
});
}else{
toDoOnInfoBtnClicked(position,data);
}
}else{
toDoOnInfoBtnClicked(position,data);
}
}
});
}
#Override
public int getItemCount() {
return data.length;
}
public class VideosViewHolder extends RecyclerView.ViewHolder {
TextView videoTitle,videoCategoryTitle;
public VideosViewHolder(#NonNull View itemView) {
super(itemView);
videoTitle = itemView.findViewById(R.id.video_title);
videoCategoryTitle = itemView.findViewById(R.id.video_category_title);
}
}
}
It's just because you are sending Context object to the method getAdRequest(Activity activity) which needs Activity object. So you can fix it in 2 ways
Change adapter to take Activity not Context. like below
public class VideosAdapter extends RecyclerView.Adapter<VideosAdapter.VideosViewHolder> {
private Activity activity;
..
public VideosAdapter(Activity activity, Video[] data, int layout) {
this.activity = activity;
...
}
The second way to fix this is, change getAdRequest(Activity activity), like below
public static AdRequest getAdRequest(Context context) {
return new AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter.class, GDPR.getBundleAd(context))
.build();
}
But in the second way, I am not sure if GDPR.getBundleAd() can take context. So better to go with 1st way
3rd way is to typecast context as Activity as you commented. Like
mInterstitialAd.loadAd(GDPR.getAdRequest((Activity) context));
But there is one problem in this approach. As the constructor of your adapter take Context parameter, any Activity which using this adapter can create the object like new VideosAdapter(activity, ...) BUT can create the object like new VideosAdapter(applicationContext, ...) or new VideosAdapter(objectOfcontext, ...). So in the last 2 cases, you will get a typecast exception.
You should pass an Activity object to your adapter. otherwise you'll face with that error.
use like this :
adapter = new VideosAdapter(YourActivity.this,yourData,R.layout.some_layout);

How can I get a variable from RecyclerView Adapter passed to MainActivity?

I was just playing around with some code, learning new things, when I ran into this problem... I'm trying to pass a variable from my RecylcerViewAdapter to a method in MainActivity, but I just can't seem to accomplish it.
I tried a lot of different thing with interfaces and casting, but nothing did the trick. Since I'm fairly new to all of this, maybe I'm making a trivial mistake somewhere?
My Interface:
public interface AdapterCallback {
void onMethodCallback(int id);
}
This is my adapter class:
public class PostAdapter extends RecyclerView.Adapter<PostAdapter.ViewHolder> {
private List<Post> postList;
private Context context;
private AdapterCallback listener;
public PostAdapter() {
}
public PostAdapter(List<Post> postList, Context context) {
this.postList = postList;
this.context = context;
}
public void setListener(AdapterCallback listener) {
this.listener = listener;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycler_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, final int position) {
viewHolder.tvTitle.setText(postList.get(position).getTitle());
viewHolder.tvBody.setText(new StringBuilder(postList.get(position).getBody().substring(0, 20)).append("..."));
viewHolder.tvId.setText(String.valueOf(postList.get(position).getUserId()));
viewHolder.parentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = postList.get(position).getId();
if (listener != null) {
listener.onMethodCallback(id);
}
}
});
}
#Override
public int getItemCount() {
return postList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle;
TextView tvBody;
TextView tvId;
LinearLayout parentLayout;
public ViewHolder(View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tvTitle);
tvBody = itemView.findViewById(R.id.tvBody);
tvId = itemView.findViewById(R.id.tvId);
parentLayout = itemView.findViewById(R.id.parentLayout);
}
}
}
And my MainActivity:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivityLog";
private CompositeDisposable disposable = new CompositeDisposable();
#BindView(R.id.rvPosts)
RecyclerView rvPosts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
rvPosts.setHasFixedSize(true);
rvPosts.setLayoutManager(new LinearLayoutManager(this));
populateList();
logItems();
}
private void populateList() {
MainViewModel viewModel = ViewModelProviders.of(MainActivity.this).get(MainViewModel.class);
viewModel.makeQuery().observe(MainActivity.this, new Observer<List<Post>>() {
#Override
public void onChanged(#Nullable List<Post> posts) {
PostAdapter adapter = new PostAdapter(posts, getApplicationContext());
rvPosts.setAdapter(adapter);
}
});
}
public void logItems() {
PostAdapter adapter = new PostAdapter();
adapter.setListener(new AdapterCallback() {
#Override
public void onMethodCallback(int id) {
MainViewModel viewModel = ViewModelProviders.of(MainActivity.this).get(MainViewModel.class);
viewModel.makeSingleQuery(id).observe(MainActivity.this, new Observer<Post>() {
#Override
public void onChanged(#Nullable final Post post) {
Log.d(TAG, "onChanged: data response");
Log.d(TAG, "onChanged: " + post);
}
});
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
disposable.clear();
}
}
The populateList() method works just fine, but the logItems() method is the problem.
So when i click on a view in RecyclerView I expect the log to output the title, description and ID of the post that was clicked. nut nothing happens...
So, any help would be appreciated.
Make adapter global variable i.e. a field. Use the same object to set every properties.
private PostAdapter adapter;
Replace your logItems method with this:
public void logItems() {
adapter.setListener(new AdapterCallback() {
#Override
public void onMethodCallback(int id) {
MainViewModel viewModel = ViewModelProviders.of(MainActivity.this).get(MainViewModel.class);
viewModel.makeSingleQuery(id).observe(MainActivity.this, new Observer<Post>() {
#Override
public void onChanged(#Nullable final Post post) {
Log.d(TAG, "onChanged: data response");
Log.d(TAG, "onChanged: " + post);
}
});
}
});
}
And populateList with this:
private void populateList() {
MainViewModel viewModel = ViewModelProviders.of(MainActivity.this).get(MainViewModel.class);
viewModel.makeQuery().observe(MainActivity.this, new Observer<List<Post>>() {
#Override
public void onChanged(#Nullable List<Post> posts) {
adapter = new PostAdapter(posts, getApplicationContext());
rvPosts.setAdapter(adapter);
logItems();
}
});
}
And don't call logItems() from onCreate
This is how I implement with my ListAdapters:
public class FeedbackListAdapter extends RecyclerView.Adapter<FeedbackListAdapter.ViewHolder> {
private final ArrayList<Feedback> feedbacks;
private View.OnClickListener onItemClickListener;
private View.OnLongClickListener onItemLongClickListener;
private final Context context;
public FeedbackListAdapter(ArrayList<Feedback> feedbacks, Context context) {
this.feedbacks = feedbacks;
this.context = context;
}
public void setItemClickListener(View.OnClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setOnItemLongClickListener(View.OnLongClickListener onItemLongClickListener){
this.onItemLongClickListener = onItemLongClickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder{
final TextView feedback, created, updated;
final LinearLayout mainLayout;
ViewHolder(View iv) {
super(iv);
/*
* Associate layout elements to Java declarations
* */
mainLayout = iv.findViewById(R.id.main_layout);
feedback = iv.findViewById(R.id.feedback);
created = iv.findViewById(R.id.created_string);
updated = iv.findViewById(R.id.updated_string);
}
}
#Override
public int getItemCount() {
return feedbacks.size();
}
#Override
#NonNull
public FeedbackListAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_feedback_table_row, parent, false);
return new FeedbackListAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(final #NonNull FeedbackListAdapter.ViewHolder holder, final int position) {
/*
* Bind data to layout
* */
try{
Feedback feedback = feedbacks.get(position);
holder.feedback.setText(feedback.getContent());
holder.created.setText(feedback.getCreated());
holder.updated.setText(feedback.getUpdated());
holder.mainLayout.setOnClickListener(this.onItemClickListener);
holder.mainLayout.setOnLongClickListener(this.onItemLongClickListener);
holder.mainLayout.setTag(feedback.getDbID());
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
holder.mainLayout.setBackgroundResource(outValue.resourceId);
}catch(IndexOutOfBoundsException e){
e.printStackTrace();
}
}
}
In onPopulateList you create an adaptor:
PostAdapter adapter = new PostAdapter(posts, getApplicationContext());
rvPosts.setAdapter(adapter);
However in public void logItems() { you used a different adapter
PostAdapter adapter = new PostAdapter();
adapter.setListener(new AdapterCallback() {
#Override
public void onMethodCallback(int id) {
...
}
});
Therefore the list is being populated with 1 adapter, but you are setting the listener on an unused second adapter.
The fix is to use the same adapter for both. If you make the adapater a field, and don't create a new one inside of logItems, but just set your listener it should work.
i.e.
// as a field in your class
private PostAdapter adapter;
then
// in `populateList()`
adapter = new PostAdapter(posts, getApplicationContext());
rvPosts.setAdapter(adapter);
and
// in `logItems()`
adapter.setListener(new AdapterCallback() {
#Override
public void onMethodCallback(int id) {
...
}
});
In Adapter
public class CustomerListAdapter extends RecyclerView.Adapter<CustomerListAdapter.OrderItemViewHolder> {
private Context mCtx;
ProgressDialog progressDialog;
//we are storing all the products in a list
private List<CustomerModel> customeritemList;
public CustomerListAdapter(Context mCtx, List<CustomerModel> orderitemList) {
this.mCtx = mCtx;
this.customeritemList = orderitemList;
progressDialog = new ProgressDialog(mCtx);
}
#NonNull
#Override
public OrderItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.activity_customer_list, null);
return new OrderItemViewHolder(view, mCtx, customeritemList);
}
#Override
public void onBindViewHolder(#NonNull OrderItemViewHolder holder, int position) {
CustomerModel customer = customeritemList.get(position);
try {
//holder.textViewPINo.setText("PINo \n"+Integer.toString( order.getPINo()));
holder.c_name.setText(customer.getCustomerName());
holder.c_address.setText(customer.getAddress());
holder.c_contact.setText(customer.getMobile());
holder.i_name.setText(customer.getInteriorName());
holder.i_contact.setText(customer.getInteriorMobile());
holder.i_address.setText(customer.getAddress());
} catch (Exception E) {
E.printStackTrace();
}
}
#Override
public int getItemCount() {
return customeritemList.size();
}
class OrderItemViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener {
AlertDialog.Builder alert;
private Context mCtx;
TextView c_name, c_contact, c_address, i_name, i_contact, i_address;
TextView OrderItemID, MaterialType, Price2, Qty, AQty;
//we are storing all the products in a list
private List<CustomerModel> orderitemList;
public OrderItemViewHolder(View itemView, Context mCtx, List<CustomerModel> orderitemList) {
super(itemView);
this.mCtx = mCtx;
this.orderitemList = orderitemList;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
// CatelogOrderDetailModel catelogOrderDetailModel = new CatelogOrderDetailModel();
c_name = itemView.findViewById(R.id.customerName);
c_contact = itemView.findViewById(R.id.contact);
c_address = itemView.findViewById(R.id.address);
i_name = itemView.findViewById(R.id.interiorName);
i_address = itemView.findViewById(R.id.interiorAddress);
i_contact = itemView.findViewById(R.id.interiorContact);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
CustomerModel orderitem = this.orderitemList.get(position);
}
#Override
public boolean onLongClick(View v) {
int position = getAdapterPosition();
CustomerModel orderitem = this.orderitemList.get(position);
if (v.getId() == itemView.getId()) {
// showUpdateDeleteDialog(order);
try {
} catch (Exception E) {
E.printStackTrace();
}
Toast.makeText(mCtx, "lc: ", Toast.LENGTH_SHORT).show();
}
return true;
}
}
}

Using multiple RecyclerView with one Adapter class

I have 3 RecyclerView to display most visited market, close by markets and favorite markets.
I have created 3 difference instance of MarketAdapter class for the three RecyclerView
Everything works fine, but my Activity implements one OnClickListener and I cant figure out which adapter was clicked. Is it possible to programmatically determine the Adapter that was clicked from the OnClickListener?
Here is my MarketAdapter Class
public class MarketAdapter extends RecyclerView.Adapter<MarketAdapter.ViewHolder> {
ArrayList<Markets> mMarket = new ArrayList<>();
Context mContext;
private final MarketsItemsClickListener mItemsClickListener;
private final MarketLongClickListener mLongClickListener;
private final MarketClickListener mClickListener;
public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener){
mContext = context;
mItemsClickListener = itemsClickListener;
mLongClickListener = longClickListener;
mClickListener = clickListener;
}
public interface MarketLongClickListener{
void onLongClick(int position);
}
public interface MarketClickListener{
void onClick(int position);
}
public interface MarketsItemsClickListener{
void imageViewOnClickListener(View view, int position);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
Context context = viewGroup.getContext();
int layoutForListItem = R.layout.list_market;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutForListItem, viewGroup, shouldAttachToParentImmediately);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
viewHolder.bindView(i);
}
#Override
public int getItemCount() {
if(mMarket != null) return mMarket.size();
return 0;
}
public void setData(ArrayList<Markets> markets){
mMarket = markets;
notifyDataSetChanged();
}
public void addData(Markets market, int position){
mMarket.add(0, market);
notifyDataSetChanged();
}
public Markets getItem(int position){return mMarket.get(position);}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener{
ImageView mImageView;
TextView mNameTextView, mCityTextView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image_view);
mNameTextView = itemView.findViewById(R.id.name_text_view);
mCityTextView = itemView.findViewById(R.id.city_text_view);
itemView.setOnLongClickListener(this);
itemView.setOnClickListener(this);
}
void bindView(int position){
Markets market = getItem(position);
mCityTextView.setText(market.getCity());
mNameTextView.setText(market.getName());
}
#Override
public void onClick(View v) {
//Get position of Adapter
int position = getAdapterPosition();
//Handle the click
mClickListener.onClick(position);
}
#Override
public boolean onLongClick(View v) {
return false;
}
}
}
and OnClickListener from Activity
#Override
public void onClick(int position) {}
You can pass a tag in the constructor and get that tag back via a click listener to identify the click as
private final MarketsItemsClickListener mItemsClickListener;
private final MarketLongClickListener mLongClickListener;
private final MarketClickListener mClickListener;
private final String mTag;
public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener, String tag){
mTag = tag
mContext = context;
mItemsClickListener = itemsClickListener;
mLongClickListener = longClickListener;
mClickListener = clickListener;
}
Modify the listener as
public interface MarketClickListener{
void onClick(int position, String tag);
}
and the listener code in activity as
#Override
public void onClick(int position, String tag) {
switch(tag){
case "adapter1":
break;
case "adapter2":
break;
case "adapter3":
break;
}
}
and create adapter object as
MarketAdapter adapter = new MarketAdapter("adapter1"....);
MarketAdapter adapter1 = new MarketAdapter("adapter2"....);
MarketAdapter adapter2 = new MarketAdapter("adapter3"....);
and use
mClickListener.onClick(position, mTag);
Note: You can use enums as well
You can add a attribute inside MarketAdapter so that you can tell what instance is that adapter.
Change your custom click listener to receive the adapter type:
public interface MarketClickListener {
//You can change this to receive any data you want from the adapter
void onClick(int position, int adapterType);
}
Add the constants, the identifier attribute and change the listener in your adatper:
public class MarketAdapter extends RecyclerView.Adapter<MarketAdapter.ViewHolder> {
//The constants types
public static int MOST_VISITED_MARKETS = 1;
public static int CLOSE_BY_MARKETS = 2;
public static int FAVORITE_MARKETS = 3;
//New attribute
private int adapterType;
...
//Keep the listener
private final MarketClickListener mClickListener;
public MarketAdapter(Context context, MarketsItemsClickListener itemsClickListener, MarketClickListener clickListener, MarketLongClickListener longClickListener, int adapterType){
...
//Set the type
adapterType = adapterType;
}
...
}
In your activity:
mostVisitedRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.MOST_VISITED_MARKETS ));
closeByRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.CLOSE_BY_MARKETS));
favoritesRecyclerView.setAdapter(new MarketAdapter(this,itemsClickListener,clickListener,longClickListener,MarketAdapter.FAVORITE_MARKETS));
In your view holder, change the onClick:
#Override
public void onClick(View v) {
//Get position of Adapter
int position = getAdapterPosition();
//Handle the click
mClickListener.onClick(position,adapterType);
}
I didn't test this but I think it will do the trick. Try it out.
If you want to do it this way, I would add a new variable to the adapters constructor, and then use a case/if statement to determine what you want to do in your onbindviewholder.

Finding the context for Glide Android

I'm trying to show pictures in a GridView. This Grid View is filled by an Adapter.
I always had the problem that the application is very laggy when it inflates a new card. After some searching in the internet i found Glide, which could maybe help to make the performance better.
Now I'm stuck because i can't imagine what context i should pass in at Glide.with(...):
Glide.with(**CONTEXT**).load(sights.get(i).mImageRessourceID).into(sightViewHolder.sightPhoto);
To build the Cards i use: MainActivity -> Fragment -> Adapter.
That's the code from the adapter:
public class SightCardAdapter extends RecyclerView.Adapter<SightCardAdapter.SightViewHolder> {
public static class SightViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sightName;
ImageView sightPhoto;
SightViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
sightName = (TextView) itemView.findViewById(R.id.sight_name);
sightPhoto = (ImageView) itemView.findViewById(R.id.sight_photo);
}
}
List<Sight> sights;
SightCardAdapter(List<Sight> sights) {
this.sights = sights;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public SightViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
SightViewHolder pvh = new SightViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(SightViewHolder sightViewHolder, int i) {
sightViewHolder.sightName.setText(sights.get(i).mName);
//sightViewHolder.sightPhoto.setImageResource(sights.get(i).mImageRessourceID);
Glide.with().load(sights.get(i).mImageRessourceID).into(sightViewHolder.sightPhoto); // missing context
}
#Override
public int getItemCount() {
return sights.size();
}
}
Can anybody please give me some hint? I can't image what I should pass in.
PS: Additionally if anybody has some tipps how to make my code more efficient i would be very grateful :)
You can get Context from Any View Object.
Glide.with(sightViewHolder.sightPhoto.getContext()).load(sights.get(i).mImageRessourceID).into(sightViewHolder.sightPhoto);
While passing data to the Adapter also pass a parameter Context. If you are calling your Adapter from Fragment that is child of MainActivity, simply pass getApplicationContext() as context to your Adapter.
SightCardAdapter(Context context,List<Sight> sights) {
this.sights = sights;
this.context=context;
}
while calling from Fragment.
SightCardAdapter(getApplicationContext(),sights);
Pass Context when you create object for Adapter., Changed code below
public class SightCardAdapter extends RecyclerView.Adapter<SightCardAdapter.SightViewHolder> {
public static class SightViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sightName;
ImageView sightPhoto;
SightViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
sightName = (TextView) itemView.findViewById(R.id.sight_name);
sightPhoto = (ImageView) itemView.findViewById(R.id.sight_photo);
}
}
Context context;
List<Sight> sights;
SightCardAdapter(List<Sight> sights,Context context) {
this.sights = sights;
this.context = context;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public SightViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
SightViewHolder pvh = new SightViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(SightViewHolder sightViewHolder, int i) {
sightViewHolder.sightName.setText(sights.get(i).mName);
//sightViewHolder.sightPhoto.setImageResource(sights.get(i).mImageRessourceID);
Glide.with(context).load(sights.get(i).mImageRessourceID).into(sightViewHolder.sightPhoto); // missing context
}
#Override
public int getItemCount() {
return sights.size();
}
}
Pass your context in adapter like this
Private Context mContext;
SightCardAdapter(List<Sight> sights,Context mContext) {
this.sights = sights;
this.mContext = mContext;
}
Glide.with(mContext).load("url").into(imageView);
for efficient use..
private RequestManager glideManager;
public MyAdater(Context context, Object activityOrFragment){
if (object instanceof Fragment) {
glideManager = Glide.with((Fragment) object);
} else if (object instanceof Activity) {
glideManager = Glide.with((Activity) object);
}
}
#Override
public void onBindViewHolder(ViewHolderGeneric viewHolder, int position) {
glideManager
.load(item.getResizedImageUrl())
.placeholder(R.drawable.emptystates_card_bg_none)
.fitCenter()
.into(ivGoods);
}
Adapter
MyRecyclerAdapter adapter = new MyRecyclerAdapter(mContext, this); //this -> Activity or Fragment
Try
Either pass context from activity while creating adapter object or get it from itemView.
Context context = itemView.getContext();
Pass this context to Glide.
Context context;//declare this globle
SightCardAdapter(Context context, List<Sight> sights) {
this.context=context;// add context in constructor of adapter class
this.sights = sights;
}
Now, use context in Glide as below:
Glide.with(context).load(sights.get(i).mImageRessourceID).into(sightViewHolder.sightPhoto);

RecyclerView isn't attached to Adapter

I have this strage error. I'm downloading data from API and I want to print it in RecyclerView nested in Fragment called ListFragment. This fragment is one of three which I use in ViewPager. ViewPager works fine. For now, I want to display only two textViews. Layout for them has name single_data_layout. List<Feature> features is my DataResponse. Project builds normaly without issues and I receive in Log that "Data is successfully downloaded". When I run app in DebugMode I get message that my RecyclerView isn't attached to adapter. Any ideas?
ApiClient:
public interface ApiClient {
#GET("/query?format=geojson&starttime&minsig=700")
Call<DataResponse> getData();
}
ApiClientFactory:
public class ApiClientFactory {
public static final String baseURL = "https://earthquake.usgs.gov/fdsnws/event/1/";
public ApiClient createApiClient(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(ApiClient.class);
}
}
DataAdapter:
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.DataViewHolder> {
private List<Feature> features;
private ListFragment listFragment;
private Context context;
private LayoutInflater inflater;
public DataAdapter(List<Feature> features) {
this.features = features;
}
#Override
public DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(context);
View contractView = inflater.inflate(R.layout.single_data_layout, parent, false);
return new DataViewHolder(contractView);
}
#Override
public void onBindViewHolder(DataViewHolder holder, int position) {
holder.place.setText(features.get(position).getProperties().getPlace());
holder.alert.setText(features.get(position).getProperties().getAlert());
}
#Override
public int getItemCount() {
return features.size();
}
public static class DataViewHolder extends RecyclerView.ViewHolder {
private final TextView place;
private final TextView alert;
public DataViewHolder(View view) {
super(view);
place = (TextView) view.findViewById(R.id.place_text_view);
alert = (TextView) view.findViewById(R.id.alert_text_view);
}
}
}
ListFragment:
public class ListFragment extends Fragment {
private RecyclerView recyclerView;
private static final String TAG = ListFragment.class.getSimpleName();
private ApiClient apiClient;
private List<Feature> features;
private RecyclerView.LayoutManager layoutManager;
private DataAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
getData();
return view;
}
private void getData() {
apiClient = new ApiClientFactory().createApiClient();
apiClient.getData().enqueue(new Callback<DataResponse>() {
#Override
public void onResponse(Call<DataResponse> call, Response<DataResponse> response) {
if (response.isSuccessful()) {
features = response.body().getFeatures();
adapter = new DataAdapter(features);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
Log.d(TAG, "Data successfully downloaded");
}
#Override
public void onFailure(Call<DataResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}
You should change the way you inflate the layout. This should do the trick.
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.DataViewHolder> {
private List<Feature> features;
public DataAdapter(List<Feature> features) {
this.features = features;
}
#Override
public DataAdapter.DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.single_data_layout, parent, false);
return new DataViewHolder(view);
}
#Override
public void onBindViewHolder(DataViewHolder holder, int position) {
holder.place.setText(features.get(position).getProperties().getPlace());
holder.alert.setText(features.get(position).getProperties().getAlert());
}
#Override
public int getItemCount() {
return features.size();
}
public static class DataViewHolder extends RecyclerView.ViewHolder {
private final TextView place;
private final TextView alert;
public DataViewHolder(View view) {
super(view);
place = (TextView) view.findViewById(R.id.place_text_view);
alert = (TextView) view.findViewById(R.id.alert_text_view);
}
}
}
I see that the adapter class don't have a context , I guess if you add to the adapter constructor Context c as a second parameter your problem will be solved
try to replase
public DataAdapter(List<Feature> features) {
this.features = features;
}
by this
public DataAdapter(List<Feature> features, Context c) {
this.features = features;
this.context = c;
}
and replace this line in the fragment class
adapter = new DataAdapter(features);
by this
adapter = new DataAdapter(features,getActivity());
hope this will help you :)

Categories

Resources