2

I have button in recycler view rows and I want to show alert dialog on button click.I am setting onClickListener in onBindViewHolder method of adapter class but when I click on button it is showing run time error given below:

> 2019-12-25 22:22:57.140 11041-11041/com.app.aamku E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.aamku, PID: 11041
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
    at android.view.ViewRootImpl.setView(ViewRootImpl.java:765)
    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
    at android.app.Dialog.show(Dialog.java:330)
    at Adapters.ProductAdapter$2.onClick(ProductAdapter.java:174)
    at android.view.View.performClick(View.java:6294)
    at android.view.View$PerformClick.run(View.java:24770)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Below is my code:

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

private Context context;
private List<ProductsModel> productList;

public ProductAdapter(Context context, List<ProductsModel> productList) {
    this.context = context;
    this.productList = productList;
}

@NonNull
@Override
public ProductAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.selectpack_layout,parent,false);

    ViewHolder viewHolder = new ViewHolder(v);

    return viewHolder;
}

@Override
public void onBindViewHolder(@NonNull final ProductAdapter.ViewHolder holder, final int position) {

    final ProductsModel model = productList.get(position);

    holder.marketName.setText(model.getMarketName());

    holder.order.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage("Confirm order");
            builder.setCancelable(true);
            builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {

                    dialogInterface.cancel();
                }
            });
            builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {

                   Toast.makeText(context,"Hello",Toast.Length_SHORT).show();

                }
            });

            AlertDialog alertDialog = builder.create();
            alertDialog.show();

        }
    });
}

@Override
public int getItemCount() {
    return productList.size();
}

public class ViewHolder extends RecyclerView.ViewHolder{

    Button order;
    TextView marketName;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        order = itemView.findViewById(R.id.order);
        marketName = itemView.findViewById(R.id.marketName);

     }
   }
}

How can I overcome this issue someone please let me know what I am doing wrong any help would be appreciated.

THANKS

Digvijay
  • 2,887
  • 3
  • 36
  • 86

3 Answers3

3

I have just copied your dialog code and created simple demo and it's working fine for me. Look into the demo:

Adapter code:

import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;

public class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder> {
private Context context;

public MyListAdapter(Context context) {
    this.context = context;
}

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

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.textView.setText("Fake item list " + position);

    holder.textView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage("Confirm order");
            builder.setCancelable(true);
            builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {

                    dialogInterface.cancel();
                }
            });
            builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Toast.makeText(context, "Hello", Toast.LENGTH_SHORT).show();
                }
            });
            AlertDialog alertDialog = builder.create();
            alertDialog.show();
        }
    });

}


@Override
public int getItemCount() {
    return 15;
}

public static class ViewHolder extends RecyclerView.ViewHolder {
    public TextView textView;

    public ViewHolder(View itemView) {
        super(itemView);
        this.textView = (TextView) itemView.findViewById(R.id.textView);
     }
   }
   }

Activity code:

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    MyListAdapter adapter = new MyListAdapter(this);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);
   }
  }

Activity xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:id="@+id/recyclerView"
tools:context=".MainActivity">
</androidx.recyclerview.widget.RecyclerView>

List item XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightLarge"
>


<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:text="item"
    android:gravity="center_vertical"
    android:textSize="16sp"/>

 </LinearLayout>

Also look into the import and here I am using Android x library.

halfer
  • 19,824
  • 17
  • 99
  • 186
haresh
  • 1,424
  • 2
  • 12
  • 18
1

define Activity activity as variable Pass YourActivity.this while constructor and use AlertDialog.Builder builder = new AlertDialog.Builder(activity); to create dialog

suyash saurabh
  • 365
  • 6
  • 17
0

I had related problem when I want to add alertDialog after press item on fragment.

alertDialog needs a java class that extend activity in the first place, so I know you had an adapter but could you turn it over.

after you tap on the list in the recyclerview, that will engage the public function on the class that extend activity (had onCreate method) who contained the list in the recyclerview and pass any variable along the way.

the function is to run alertDialog with variable that passed and I think you should be fine that way.

or you could manually changed the context to which activity you are on, maybe thats worked.

I am sorry I couldnt give you a example as I am afk rn.

hek
  • 59
  • 1
  • 8