I want to send data from an adapter to a fragment that is already open.
In the main activity, there are two fragments already open, fragment A and fragment B. In fragment A, I have a RecyclerView and CardView placed. When one of the card views is clicked, I want to send its data to fragment B. And I get an NPE when calling mCallbacks.
if (mCallbacks != null){
mCallbacks.onItemClicked(strStockName);}
In this case, I used an interface. But I need more explanation about it.
Here is my adapter's code:
public class adapterStock extends RecyclerView.Adapter<adapterStock.ViewHolder> {
private String[] stockNameDataSet;
private Context mContext;
//==============================================
//---- interface
public interface Callbacks{
public void onItemClicked(String StockName);
}
private Callbacks mCallbacks;
//==============================================
public adapterStock(Context context, String[] DataSet){
stockNameDataSet = DataSet;
mContext = context;
}
#NonNull
#Override
public adapterStock.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
View view = layoutInflater.inflate(R.layout.cv_stock, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
final String strStockName = stockNameDataSet[position];
holder.tbxStockName.setText(stockNameDataSet[position]);
holder.cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Snackbar.make(view, "Stock "+strStockName, Snackbar.LENGTH_LONG).show();
if (mCallbacks != null){
mCallbacks.onItemClicked(strStockName);
}
}
});
}
#Override
public int getItemCount() {
return stockNameDataSet.length;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public View view;
public TextView tbxStockName;
public CardView cardView;
public ViewHolder(View v){
super (v);
tbxStockName = (TextView) v.findViewById(R.id.cvTbxItemStockName);
cardView = (CardView) v.findViewById(R.id.cvStock);
}
}
public void setCallbacks(Callbacks callbacks){
this.mCallbacks = callbacks;
}
}
And here is fragment A:
public class AFrag extends Fragment implements adapterStock.Callbacks {
private String strStockName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_A, container, false);
tbxStock = (TextView) view.findViewById(R.id.tbxR);
return view;
}
#Override
public void onItemClicked(String StockName) {
Toast.makeText(getActivity(), "Stock terpilih " + StockName, Toast.LENGTH_LONG).show();
tbxStock.setText(strStockName);
}
}
Suggestions are appreciated. Thanks.
Include, setCallbacks(this) in your fragment A once adapterStock instance is created.
setCallbacks(this) in your fragment
Change this
public adapterStock(Context context, String[] DataSet){
stockNameDataSet = DataSet;
mContext = context;
}
to this
public adapterStock(Context context, String[] DataSet, Callbacks mCallbacks){
stockNameDataSet = DataSet;
mContext = context;
this.mCallbacks=mCallbacks;
}
in fragment's adapterStock instance, pass the mCallbacks as this (i.e., new adapterStock(context, dataset,this))
note: two other answers also correct
Related
I am adding data into an addToSepetims arraylist and I want to use it in another fragment but I cant get this arraylist
public class productAdapter extends RecyclerView.Adapter<productAdapter.ViewHolder> {
ArrayList<product_bilgileri> product_bilgileris = new ArrayList<product_bilgileri>();
LayoutInflater layoutInflater;
Context context;
ArrayList<AddToSepetim> addToSepetims = new ArrayList<AddToSepetim>();
public productAdapter(ArrayList<product_bilgileri> product_bilgileris, Context context) {
this.product_bilgileris = product_bilgileris;
this.context = context;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.productName.setText(product_bilgileris.get(position).getProductname());
holder.description.setText(product_bilgileris.get(position).getDescription());
holder.imageView.setImageDrawable(context.getResources().getDrawable(product_bilgileris.get(position).getImage()));
holder.ratingBar.setRating((product_bilgileris.get(position).getRating()));
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String a =holder.productName.getText().toString();
String b =holder.description.getText().toString();
int c = R.drawable.iphone5;
//Toast.makeText(context, ""+a, Toast.LENGTH_SHORT).show();
addToSepetims.add(new AddToSepetim(a,b,c));
}
});
}
This is Where I want to use addToSepetims arraylist :
public class SepetimFragment extends Fragment {
RecyclerView recyclerView;
ArrayList<AddToSepetim> addToSepetims = new ArrayList<AddToSepetim>();
public SepetimFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_sepetim, container, false);
recyclerView = view.findViewById(R.id.products_recylerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(layoutManager);
SepetimAdapter sepetimAdapter = new SepetimAdapter(addToSepetims,getActivity());
recyclerView.setAdapter(sepetimAdapter);
return view;
}
}
I have also SepetimAdapter Class
public class SepetimAdapter extends RecyclerView.Adapter<SepetimAdapter.ViewHolder> {
ArrayList<AddToSepetim> addToSepetims = new ArrayList<AddToSepetim>();
LayoutInflater layoutInflater;
public SepetimAdapter(ArrayList<AddToSepetim> addToSepetims, Context context) {
this.addToSepetims = addToSepetims;
this.context = context;
}
Context context;
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.row_product_sepetim,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.productName.setText(addToSepetims.get(position).getProductname());
holder.description.setText(addToSepetims.get(position).getDescription());
holder.imageView.setImageDrawable(context.getResources().getDrawable(addToSepetims.get(position).getImage()));
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// addToSepetims.remove(addToSepetims.get(position));
}
});
}
#Override
public int getItemCount() {
return addToSepetims.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView productName,description;
ImageView imageView;
Button button;
public ViewHolder(#NonNull View itemView) {
super(itemView);
productName = itemView.findViewById(R.id.product_Name);
description = itemView.findViewById(R.id.descripton);
imageView = itemView.findViewById(R.id.product_pic);
button = itemView.findViewById(R.id.deleteFromCard);
}
}
}
Second QUESTION :
Product adapter class in onBindViewHolder class :
int c = R.drawable.iphone5;
in this line I want to get holder.imageView instead of "R.drawable.iphone5"
How can I do that ?
You can share data between fragments through a ViewModel:
Add dependency in build.gradle (Module:app) level.
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
implementation "android.arch.lifecycle:runtime:2.2.0"
Create a custom ViewModel class that extends from AndroidViewModel
Here added the list you want to be shared between fragments.
public class MainViewModel extends AndroidViewModel {
private ArrayList<product_bilgileri> products;
public TempViewModel(#NonNull Application application) {
super(application);
}
public ArrayList<product_bilgileri> getProducts() {
return products;
}
public void setProducts(ArrayList<product_bilgileri> products) {
this.products = products;
}
}
Instantiate the ViewModel instance in activity/fragment
// In activity
MainViewModel mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
// In fragment
MainViewModel mViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
Then set the list of data with mViewModel.setProducts(myList) and retrieve it with mViewModel.getProducts()
For more info, check the documentation. Also check this article.
i am trying to add a recyclerview on a fragment
fragments code:
public class MediaPlayerController extends Fragment{
private static final String TAG = "MediaPlayerController";
private RecyclerView recyclerViewb;
private RecycleViewAdapter myAdapter;
private ArrayList<String> myRecordings = new ArrayList<>();
//private DBHelper dbHelper;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: started");
View v = inflater.inflate(R.layout.media_player_area, container, false);
recyclerViewb = (RecyclerView)v.findViewById(R.id.recyclerViewXml);
//dbHelper = new DBHelper(v.getContext(), null, null, 1);
myRecordings.add("hau");
myRecordings.add("hau2");
myRecordings.add("hau3");
myRecordings.add("hau4");
myRecordings.add("ha5");
myRecordings.add("hau23");
myRecordings.add("ha31u");
myRecordings.add("haudsa");
System.out.println("what does this print?"+myRecordings);
myAdapter = new RecycleViewAdapter(v.getContext(), myRecordings);
recyclerViewb.setAdapter(myAdapter);
recyclerViewb.setLayoutManager(new LinearLayoutManager(v.getContext()));
Log.d(TAG, "onCreateView: returned");
return v;
}
in the logs i see that that it doesn't even get to the RecycleViewAdapter sections of code at all the fragment is completely blank
i get not errors as well
public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.ViewHolder>{
private static final String TAG = "RecycleViewAdapter";
private Context mContext;
private ArrayList<String> mRecName = new ArrayList<>();
public RecycleViewAdapter(Context mContext, ArrayList<String> mRecName) {
this.mContext = mContext;
this.mRecName = mRecName;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Log.d(TAG, "onCreateViewHolder: i am here");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_recycle, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: called");
holder.recTxt.setText(mRecName.get(position).toString());
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext, "sas gamaw", Toast.LENGTH_LONG);
}
});
}
#Override
public int getItemCount() {
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder{
RelativeLayout parentLayout;
TextView recTxt;
public ViewHolder(View itemView) {
super(itemView);
recTxt = itemView.findViewById(R.id.recTextView);
parentLayout = itemView.findViewById(R.id.parentLayoutXml);
}
}
}
in the logs it only displays oncreateView started and the myRecordings arraylist
onCreateView: started
I/System.out: what does this print?[hau, hau2, hau3, hau4, ha5,
hau23, ha31u, haudsa]
MediaPlayerController: onCreateView: returned
i can't think of what is going wrong :/ please help out
i also want to add that i am fairly new to android studio thanks
your code problem it is in Recycler Adapter in getItemCount() method,
You don't return any Item , you must change it to :
#Override
public int getItemCount() {
return mRecName.size();
}
I am trying to create an interface between my Recyclerview Adapter and an Activity, so that when an item in the adapter is clicked, the Activity will react accordingly but the listener is always null.
Interface
public interface UrlTagCatClickedListener {
public void onUrlTagCatClicked (String chemicalURL);
}
Adapter
public class TagCatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<TagCatItem> mTagCatItems;
private int lastPosition = -1;
private UrlTagCatClickedListener mTagCatClickedListener;
public TagCatAdapter(List<TagCatItem> tagCatItems, Context context) {
super();
this.mTagCatItems = tagCatItems;
this.mContext = context;
this.mTagCatClickedListener = null;
}
public void setTagCatClickedListener (UrlTagCatClickedListener tagCatClickedListener) {
this.mTagCatClickedListener = tagCatClickedListener;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tag_cat_item, parent, false);
return new ItemViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final TagCatItem tagCatItem = mTagCatItems.get(position);
((ItemViewHolder) holder).chemicalTitle.setText(Html.fromHtml(tagCatItem.getChemicalTitle()));
((ItemViewHolder) holder).chemicalDate.setText(tagCatItem.getChemicalDate());
((ItemViewHolder) holder).chemicalTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTagCatClickedListener != null) { // mTagCatClickedListener is always null
mTagCatClickedListener.onUrlTagCatClicked(tagCatItem.getChemicalURL());
}
}
});
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
public TextView chemicalTitle, chemicalDate;
public ItemViewHolder(final View mView) {
super(mView);
chemicalTitle = (TextView) mView.findViewById(R.id.tagcat_title);
chemicalDate = (TextView) mView.findViewById(R.id.tagcat_date);
}
}
#Override
public int getItemCount() {
return mTagCatItems.size();
}
}
Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate called")
//Skipped a lot of codes that doesn't relate to the queation
List<TagCatItem> mTagCatItems = new ArrayList<>();
TagCatAdapter tagCatAdapter = new TagCatAdapter(mTagCatItems, this);
tagCatAdapter.setTagCatClickedListener(new UrlTagCatClickedListener() {
#Override
public void onUrlTagCatClicked(String chemicalURL) {
Log.d(TAG, "I go the url!!!!!!!!!! and it is + " + chemicalURL);
}
});
}
Please, do you have an idea why it's null and how I can fix it?
You have two different instances of TagCatAdapter in your given setup; one in the Activity, and one in the Fragment. You're setting the UrlTagCatClickedListener you've posted on the one created in the Activity, but it's the Fragment's TagCatAdapter instance that you're setting on the RecyclerView. That one doesn't have the listener set, so its mTagCatClickedListener is always null.
You just need to move the given UrlTagCatClickedListener to the TagCatAdapter in the Fragment, and remove the TagCatAdapter from the Activity, as you're not using that one anyway.
I'm not quite sure if this is possible, but I'm trying to change the content of a custom DialogFragment (read: content as in 1 imageview, and 3 textviews) inside of a Recyclerview adapter.
My current custom DialogFragment:
public class ServiceDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.service_card, container, false);
}
}
And the layout:
As you see in the image above: I have a list behind the where the DialogFragment is displayed and whenever I press one of those "buttons" that DialogFragment appears. But my question is: how do I change the content of the custom DialogFragment inside of my Recyclerview Adapter?
My adapter:
public class ServiceAdapter extends RecyclerView.Adapter<ServiceAdapter.ViewHolder>{
private final String TAG = "******* Service Adapter";
private ArrayList<ServiceObject> mDataset;
private Context mContext;
private Resources mResources;
private Context location;
public ServiceAdapter(ArrayList<ServiceObject> mDataset, Context mContext, Resources mResources) {
this.mDataset = mDataset;
this.mContext = mContext;
this.mResources = mResources;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
location = parent.getContext();
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.service_box, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(mDataset.get(position).getTitle());
holder.icon.setImageResource(mResources.getIdentifier(Integer.toString(mDataset.get(position).getIcon()), "drawable", "net.example.adapter"));
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemCount() {
return mDataset == null ? 0 : mDataset.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView title, desc, price;
ImageView icon;
public ViewHolder(View v) {
super(v);
title = (TextView) v.findViewById(R.id.service_box_title);
price = (TextView) v.findViewById(R.id.service_card_price);
icon = (ImageView) v.findViewById(R.id.service_box_icon);
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
FragmentActivity activity = (FragmentActivity)(mContext);
FragmentManager fm = activity.getSupportFragmentManager();
ServiceDialogFragment alertDialog = new ServiceDialogFragment();
alertDialog.show(fm, "display_service");
}
}
}
Thanks to #raghunandan, I figured it out. Resource: http://developer.android.com/reference/android/app/DialogFragment.html
guys i need help with this matter i have been going through my code for a couple of days to figure whats going wrong but i couldn't figure it out.
I have a fragment with a RecyclerView i initialize the Adapter data with an image place holder and some default text and the fragment shows them as expected then using a loader i fetch data from the internet and parse and pass the new data to the Adapter (all of this happens as required) until the data reaches the Adapter then Taaadaaaa the initial data disappears and the new data is not showing actually the fragment shows a blank screen definitely i am doing something wrong please advise.
This is the fragment code
public class fragment_MovieStartGridlayout extends android.support.v4.app.Fragment implements MyGridAdapter.MyGridAdapterListener{
private static RecyclerView myRecyclerView;
private static MyGridAdapter myGridAdapter;
private static RecyclerView.LayoutManager rvLayoutManager;
private LoaderManager.LoaderCallbacks<ArrayList<HashMap>> dataLoaderCallbacks;
private OnFragmentInteractionListener mListener;
public fragment_MovieStartGridlayout() {
}
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataLoaderCallbacks = new LoaderManager.LoaderCallbacks<ArrayList<HashMap>>() {
#Override
public Loader<ArrayList<HashMap>> onCreateLoader(int id, Bundle args) {
return new DataLoader(getActivityContext(), MyUriBuilder.DISCOVER, null);
}
#Override
public void onLoadFinished(Loader<ArrayList<HashMap>> loader,ArrayList<HashMap> data) {
myGridAdapter.setMyAdapterData(data);
}
#Override
public void onLoaderReset(Loader<ArrayList<HashMap>> loader) {
loader.reset();
}
};
getLoaderManager().initLoader(0, null, dataLoaderCallbacks);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragGridLayout = inflater.inflate(R.layout.fragment_gridlayout_movie_start, container, false);
myRecyclerView = (RecyclerView) fragGridLayout.findViewById(R.id.myViewRecycler);
rvLayoutManager = new GridLayoutManager(getActivityContext(),2);
myRecyclerView.setLayoutManager(rvLayoutManager);
myGridAdapter = new MyGridAdapter(getActivityContext());
myRecyclerView.setAdapter(myGridAdapter);
return fragGridLayout;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDataSetChanged(boolean state) {
if (state){
myGridAdapter.notifyDataSetChanged();
}
}
public interface OnFragmentInteractionListener {
public void onFragmentInteraction(Uri uri);
}
public Context getActivityContext(){
return this.getActivity();
}
}
and this is the Adapter for the RecyclerView
public class MyGridAdapter extends RecyclerView.Adapter<MyGridAdapter.MyViewHolder> {
LayoutInflater layoutInflater;
private static ArrayList<HashMap> data=null;
private Context mContext;
public static Bitmap placeHolder;
public MyGridAdapter(Context context){
mContext = context;
setInitialData();
placeHolder = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.android_blue);
}
public interface MyGridAdapterListener{
public void onDataSetChanged(boolean state);
}
private MyGridAdapterListener listener = null;
public void registerListener(MyGridAdapterListener newListener){
listener = newListener;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
layoutInflater = LayoutInflater.from(context);
View v = layoutInflater.inflate(R.layout.gridlayout_item_movie_start, parent, false);
MyViewHolder vHolder=new MyViewHolder(v);
return vHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
HashMap singleData = data.get(position);
String movieRate = String.valueOf(singleData.get(MyJSONDataParser.TAG_VOTE_AVERAGE)) ;
holder.movieTitle.setText((String)singleData.get(MyJSONDataParser.TAG_TITLE));
holder.moviePoster.setImageBitmap(placeHolder);
holder.movieRating.setRating(Float.valueOf(movieRate));
}
#Override
public int getItemCount() {
return data.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView movieTitle;
RoundedImageView moviePoster;
RatingBar movieRating;
public MyViewHolder(View v) {
super(v);
movieTitle = (TextView) v.findViewById(R.id.movieTitleTextView);
moviePoster = (RoundedImageView) v.findViewById(R.id.roundImageView);
movieRating = (RatingBar) v.findViewById(R.id.ratingBar);
}
}
private boolean dataChanged = false;
public void setMyAdapterData(ArrayList<HashMap> data){
this.data = data;
dataChanged = true;
if (listener != null){
listener.onDataSetChanged(dataChanged);
}
}
protected void setInitialData(){
HashMap initialItem = new HashMap();
ArrayList<HashMap> initialData = new ArrayList<>(20);
initialItem.put(MyJSONDataParser.TAG_TITLE, "Loading...");
initialItem.put(MyJSONDataParser.TAG_MOVIE_BITMAP, placeHolder);
initialItem.put(MyJSONDataParser.TAG_VOTE_AVERAGE, 3.3);
for (int i = 0;i<20;i++){
initialData.add(initialItem);
}
this.data = initialData;
}
}
I did call notifyDataSetChanged
but this was not the issue after alooooooooot of testing and Logging the problem was with setAdapterData method where i just passed the data reference from the loader to the adapter but this didn't work and i had to clone the arraylist instead of just passing the reference which sounds strange to me and i still don't understand why I had to do that if you can take a look at the setAdapterData method in MyGridAdapter class and tell me what do you think
Try invoking notifyDataSetChanged() when you modify your adapter data:
public void setMyAdapterData(ArrayList<HashMap> data){
this.data = data;
dataChanged = true;
notifyDataSetChanged();
if (listener != null){
listener.onDataSetChanged(dataChanged);
}
}
I see that you attempt to do this in the callback on your listener, but perhaps it is null and therefore never firing the notification?
[COMMENT]
When I want to replace the entire collection of data in my adapter I often write a method similar to this:
public void setData(List<MyData> newData) {
this.data.clear();
this.data.addAll(newData);
this.notifyDataSetChanged();
}