简体   繁体   中英

How to call DialogFragment from RecyclerView.ViewHolder (with interface implement)

I saw few related questions about this kind of situation, but couldn't find any solution, so my problem goes like this.

I have tabLayout which hold's 4 fragments, Im delivering data to user in frag number 3 (catalog), this frag hold recyclerView for cardView im trying to implement onclicklistner for card which will invoke dialogFragment, I understand the most efficient way to do so, is using interface for the viewHolder, i face one problem the recyclerView adapter constructor .

Here is the the catalog frag:

public class CatalogFragment extends Fragment implements CustomAdapter.OnItemClickListener {

private FloatingActionButton mSharedFab;
private List<MyProducts> productsList;

//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;

private CustomAdapter.OnItemClickListener listener;//////LISTNER FOR DIALOG???

//Volley Request 
private RequestQueue requestQueue;

//request counter 
private int requestCount = 1;
private static final String URL_INDEX = "http://myserverip/product.php";
//Tag values to read from json
public static final String TAG_IMAGE_URL = "product_img";
public static final String TAG_PRODUCT_SN = "product_serial_num";
public static final String TAG_PRODUCT_TITLE = "product_title";
public static final String TAG_PRODUCT_PRICE = "product_price";
public static final String TAG_PRODUCT_DESCRIPTION = "product_description";

public CatalogFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_catalog, container, false);
    recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
    layoutManager = new LinearLayoutManager(getActivity().getApplicationContext(), LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(layoutManager);
    //recyclerView.setHasFixedSize(true);
    RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
    itemAnimator.setAddDuration(1000);
    itemAnimator.setRemoveDuration(1000);
    recyclerView.setItemAnimator(itemAnimator);

    //Initializing our product list
    productsList = new ArrayList<>();
    requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());

    // fetch data
    getData();



    //initialize adapter

    adapter = new CustomAdapter(listener, productsList, getActivity());
    //Adding adapter to recyclerview
    recyclerView.setAdapter(adapter);
    return view ;
}
 @Override
public void onItemClicked(View v) {
    DialogAddToCartFragment df= new DialogAddToCartFragment();
    df.show(getFragmentManager(), "Dialog");
}

the adapter instantiated with 3 params, with customadapter.

the customAdapter class:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

public interface OnItemClickListener {
    void onItemClicked(View v);
}

private OnItemClickListener listener;
//Image loader inst for image
private ImageLoader imageLoader;

private Context context;
public Snackbar snackbar;
String title;
//List  all products
List<MyProducts> myProducts;

public CustomAdapter( OnItemClickListener listener, List<MyProducts> myProducts, Context context)
{
    super();
    this.listener = listener;
    this.myProducts = myProducts;
    this.context = context;
}

@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.product_list, parent, false);
    ViewHolder viewHolder = new ViewHolder(v);
    return viewHolder;
}

@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {

    if( myProducts != null) {
        MyProducts myProducts1 = myProducts.get(position);
        imageLoader = ImageVolley.getInstance(context).getImageLoader();
        imageLoader.get(myProducts1.getProductImage(), ImageLoader.getImageListener(holder.imageView, R.drawable.android_store_log, android.R.drawable.ic_dialog_alert));
        title = myProducts1.getProductTitle();
        //Showing data to the views
        holder.imageView.setImageUrl(myProducts1.getProductImage(), imageLoader);
        holder.textViewProductTitle.setText(myProducts1.getProductTitle());
        holder.textViewProductDescription.setText(myProducts1.getProductDescription());
        holder.textViewProductSerialNumber.setText(myProducts1.getProductSn());
        holder.textViewProductPrice.setText(myProducts1.getProductPrice());
    }
}

@Override
public int getItemCount() {
    return myProducts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
    //Views
    public NetworkImageView imageView;
    public TextView textViewProductTitle;
    public TextView textViewProductDescription;
    public TextView textViewProductSerialNumber;
    public TextView textViewProductPrice;

    //Initializing Views
    public ViewHolder(final View itemView) {
        super(itemView);
        imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewProduct);
        textViewProductTitle = (TextView) itemView.findViewById(R.id.textViewProductTitle);
        textViewProductDescription = (TextView) itemView.findViewById(R.id.textViewProductDescription);
        textViewProductSerialNumber = (TextView) itemView.findViewById(R.id.textViewProductSerialNumber);
        textViewProductPrice = (TextView) itemView.findViewById(R.id.textViewProductPrice);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onItemClicked(v);/////////DIALOG LISTENER????
            }
        });
    }
}

the DialogFragment:

public class DialogAddToCartFragment extends DialogFragment {



@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_dialog_add_to_cart, new LinearLayout(getActivity()), false);

    // Retrieve layout elements
    //TextView title = (TextView) view.findViewById(R.id.text_title);

    // Set values
    //title.setText("Not perfect yet");

    // Build dialog
    Dialog builder = new Dialog(getActivity());
    builder.requestWindowFeature(Window.FEATURE_NO_TITLE);
    builder.getWindow().setBackgroundDrawable(new ColorDrawable(Color.GREEN));
    builder.setContentView(view);
    return builder;

}

}

As i click on card i get program closed :(

Here is the log:

07-12 08:42:22.685 2808-2808/com.example.get2i.androidstore E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.example.get2i.androidstore, PID: 2808
                                                                          java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.get2i.androidstore.CustomAdapter$OnItemClickListener.onItemClicked(android.view.View)' on a null object reference
                                                                              at com.example.get2i.androidstore.CustomAdapter$ViewHolder$1.onClick(CustomAdapter.java:102)
                                                                              at android.view.View.performClick(View.java:5198)
                                                                              at android.view.View$PerformClick.run(View.java:21147)
                                                                              at android.os.Handler.handleCallback(Handler.java:739)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                              at android.os.Looper.loop(Looper.java:148)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

With what should i instntiate the CustomAdapter.OnItemClickListener listener in the catalogfrag? Any advice would be appriciated, thank you!

instantiate the fragmentManager in the activity itself,

MyActivity.java

 `FragmentManager fragmentManager = getFragmentManager();
 adapter = new CustomAdapter(productsList, fragmentManager);`

CustomAdapter.java

 `CustomAdapter implements MyClickListner{
 CustomAdapter(Arraylist<MyProduct>productsList, FragmentManager 
 fragmentManager) {
      this.productList = productsList;
      this.fragmentManager = fragmentManager;
 }

 `@override
  clickFunction(){
     Fragment myFragment= new MyFilterFragment();
     ((MyFilterFragment) myFragment).show(this.fragmentManager,"tag");
  }`

MyClickListener.java

`public interface MyClickListener(){
   public clickFunction();
}`

what should i instntiate the CustomAdapter.OnItemClickListener listener in the catalogfrag?

Because forget to initialize listener object before passing it to CustomAdapter class constructor. do it as:

listener=this;
adapter = new CustomAdapter(listener, productsList, getActivity());
...

call this method in onBindViewHolder on itemView 's click listener

public void showDialogFragment(View view){
        DialogFragment dialogFragment = DialogFragment.newInstance("Delete item","Are you sure you want to delete this item ?",R.drawable.cancel);
        AppCompatActivity activity = ((AppCompatActivity)view.getContext());
        dialogFragment.show(activity.getSupportFragmentManager(),null);
    }

Hope it helps

Just change this in your CatalogFragment

adapter = new CustomAdapter(listener, productsList, getActivity());

To

adapter = new CustomAdapter(this, productsList, getActivity());

You're getting NPE because you are passing null reference of your listener

You're passing in an empty listener, not the one which you have implemented in your Fragment instance.

Change this line;

adapter = new CustomAdapter(listener, productsList, getActivity());

to this;

adapter = new CustomAdapter(this, productsList, getActivity());

and delete your listener variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM