1

This is my code to delete selected item on button click,I added Alert dialog box to this code,After I add this Alert box,Fatal error exception occur.

 public class MycustomAdapter extends BaseAdapter implements ListAdapter {
    public ArrayList<category> list = new ArrayList<category>();
    public Context context;



    public MycustomAdapter(ArrayList<category> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int pos) {
        return list.get(pos);
    }

    @Override
    public long getItemId(int position) {
        return list.get(position).getId();
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.row, null);
        }

        //Handle TextView and display string from your list
        TextView listItemText = (TextView)view.findViewById(R.id.lblreload
        );
        listItemText.setText(list.get(position).getName());

        listItemText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                category row = (category) list.get(position);
                int selected_id = row.getId();
                String budget = row.getName();

                Intent myIntent = new Intent(context, addbudget.class);
                myIntent .putExtra("passed data key",budget);
                myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(myIntent);
            }
        });

        //Handle buttons and add onClickListeners
       TextView deleteBtn = (TextView)view.findViewById(R.id.delete_btn);

        deleteBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                new AlertDialog.Builder(context)
                        .setTitle("Delete entry")
                        .setMessage("Are you sure you want to delete this entry?")
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                SQLiteDatabase db = new DBhelper(context).getWritableDatabase();
                                db.delete(DBhelper.TABLE1, DBhelper.C_ID + "=?", new String[] {Integer.toString(list.get(position).getId())});
                                db.close();
                                list.remove(position);
                                notifyDataSetChanged();

                            }
                        })
                        .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                // do nothing
                            }
                        })
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .show();

            }
        });


        return view;
    }
}

This is the fatal error exception I got when I click the delete button.

 22 20:50:56.546  28837-28837/com.example.username.weddingplanning
 E/AndroidRuntime﹕ FATAL EXCEPTION: main
     android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
             at android.view.ViewRootImpl.setView(ViewRootImpl.java:811)
             at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:265)
             at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:73)
             at android.app.Dialog.show(Dialog.java:282)
             at android.app.AlertDialog$Builder.show(AlertDialog.java:951)
             at com.example.username.weddingplanning.MycustomAdapter$2.onClick(MycustomAdapter.java:101)
             at android.view.View.performClick(View.java:4439)
             at android.view.View$PerformClick.run(View.java:18398)
             at android.os.Handler.handleCallback(Handler.java:725)
             at android.os.Handler.dispatchMessage(Handler.java:92)
             at android.os.Looper.loop(Looper.java:176)
             at android.app.ActivityThread.main(ActivityThread.java:5299)
             at java.lang.reflect.Method.invokeNative(Native Method)
             at java.lang.reflect.Method.invoke(Method.java:511)
             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
             at dalvik.system.NativeStart.main(Native Method)

I have already gone through the similar questions in stack overflow,but I didn't get it.I have this delete button in CustomAdapter class,not in Activity class.

Clay
  • 4,700
  • 3
  • 33
  • 49
xyz
  • 71
  • 3
  • 12
  • I googled for the error message and there are some people who posted about the same error message. Their problem was solved by not using just any 'context' but something like 'MyClassName.this'. See for example [this link](http://stackoverflow.com/questions/5796611/) – Bö macht Blau Oct 22 '15 at 16:47
  • I tried in the same way too,but still no use,as I have Alert dialog box in java class not in Activity class. – xyz Oct 22 '15 at 16:54
  • well, I just copied your OnClickListener into one of my ArrayAdapters and it worked :) I'm sure we'll fix your problem by taking a closer look at that 'context' variable - how do you initialize the adapter? – Bö macht Blau Oct 22 '15 at 16:57
  • initializing mean?? I call this Custom adaptor class in another activity like this `MycustomAdapter adapter = new MycustomAdapter(mArrayList, getApplicationContext());` – xyz Oct 22 '15 at 17:01
  • That's what I wanted to know. So you have to change how you call the adapter class and then how you set the AlertDialog.Builder, I'm writing this as an answer now. – Bö macht Blau Oct 22 '15 at 17:20

1 Answers1

1

The AlertDialog.Builder needs not just any context to work with, it wants an activity. More precisely, it wants the activity which shows the ListView.

So the question is "how do we get the activity from the context"?

First, you need to initialize your adapter using the activity which contains the ListView:

// assuming 'this' means the activity:
adapter = new MyCustomAdapter(myList, this);

Then you can do the following in the 'getView()' method of 'MyCustomAdapter.java' (let's assume the activity is called 'MyActivity'):

deleteBtn.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {

        // you know the condition will be true,
        // but for formal reasons make sure anyway:
        if (context instanceof MyActivity)
        {
            new AlertDialog.Builder((MyActivity)context)
                    .setTitle("Delete entry")
                    .setMessage("Are you sure you want to delete this entry?")
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                     // and so on...
                    })
                    .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // do nothing
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .show();

        }
     }
});

To be on the safe side with the database call, one could still write

SQLiteDatabase db = new DBhelper(context.getApplicationContext()).getWritableDatabase();
Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61
  • ` if (context instanceof MyActivity)` after i add this if loop,my delete function is not working.and tell me something,`adapter = new MyCustomAdapter(myList, this);` I don't need to initialize this again know? – xyz Oct 22 '15 at 17:40
  • @xyz - 1) you need to change the way you initialize the adapter so its constructor gets an instance of the activity and **not** the application context. 2) **if** you change your code like in step 1, the if block will get executed. – Bö macht Blau Oct 22 '15 at 17:46
  • okey,where do I need to add the database code that you mentioned in last line – xyz Oct 22 '15 at 17:59
  • Oh,Thank you so much.It's working.Your answer is perfect.And Is it a must to add that database coding?Because now you coding is working fine without that line – xyz Oct 22 '15 at 18:01
  • 1
    @xyz - not add, **change** :) you call the database if the positive button gets clicked. It's better to call it with the application context. But that's no problem because you can always get that from a context by writing like I suggested. – Bö macht Blau Oct 22 '15 at 18:02