简体   繁体   中英

ListView custom adapter, remove item using AsyncTask

I am using a custom adapter to display my listview. First and foremost, I retrieve the information I want to display in my listview using an AsyncTask as the information is retrieved from a PHP web service. Then, to delete an item from the listview it once again calls the web service to do so. On success of the deletion of the selected item, the onPostExecute method receives the results and removes the item. Only on refresh of the fragment will it however be deleted from my listview.

 @Override
    public boolean onContextItemSelected(final MenuItem item) {

        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

         switch (item.getItemId()) {
            case VIEW_CONTACT:
                // other actions
                return true;

            case EDIT_CONTACT:

                return true;

            case DELETE_CONTACT:
                // Create AlertDialog for confirmation
                AlertDialog.Builder builder = new AlertDialog.Builder(context)
                        .setTitle("Delete Contact List")
                        .setMessage("Are you sure you want to delete this list?")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                // continue with delete
                                new DeleteTask().execute();
                                dialog.cancel();
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                // do nothing
                            }
                        })
                        .setIcon(android.R.drawable.ic_dialog_alert);

                builder.show();
                return true;
        }

        return true;
    }

The above codes shows the context menu and when user selects delete, an alert dialog will prompt them to confirm the action. When they select ok, it executes the AsyncTask as follows:

public class DeleteTask extends AsyncTask<Void, String ,String>{

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pDialog = ProgressDialog.show(context, null, "Loading", true);
    }

    @Override
    protected String doInBackground(Void... params){
        return  DeleteData();
    }

    @Override
    protected void onPostExecute(String result){
        super.onPostExecute(result);
        pDialog.dismiss();

        if (result.equals("1")) {
            mAdapter.notifyDataSetChanged(); // this bit didn't work in updating/refreshing the listview
            Toast.makeText(context, "List successfully deleted", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(context,
                    "List not deleted", Toast.LENGTH_LONG).show();
        }
    }

    private String DeleteData(){
        int success = 0;

        try {
            List<NameValuePair> paramas = new ArrayList<NameValuePair>();
            paramas.add(new BasicNameValuePair("listid", listID));
            JSONParser jParserDelete = new JSONParser();
            JSONObject jsonObjectA = jParserDelete.makeHttpRequest(Constant.URL
                    + "removeList.php", "GET", paramas);
            success = jsonObjectA.getInt(Constant.TAG_SUCCESS);
            Log.d("contacts", jsonObjectA.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return Integer.toString(success);
    }
}

I tried using the mAdapter.notifyDataSetChanged(); but it didn't work. I know mAdapter is a global variable in the Activity class. Also, to note that my adapter is a custom class. I initially wanted to declare a boolean deleteSuccess globally, then at the onPostExecute set it to true on result == 1, but the onContextItemSelected does not wait for the onPostExecute and just takes the value of deleteSuccess as `false.

Bottom line is, how can I remove the selected item from my adapter and thus successfully "refresh" the ListView right after I delete the item?

Edit:

This is my custom adapter class

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.SectionIndexer;
import android.widget.TextView;

import java.util.ArrayList;

import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;

public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer, Filterable {

    private final Context mContext;
    private int[] mSectionIndices;
    private Character[] mSectionLetters;
    private LayoutInflater mInflater;
    private ArrayList<String> mArrayList;

    // for search function
    private ArrayList<Glossary> glossariesList;
    private ArrayList<Glossary> glossariesListForSearch;

    public ContactsAdapter(Context context, ArrayList<String> arrayList, ArrayList<Glossary> glossaries) {
        super();
        mContext = context;
        mArrayList = arrayList;
        mInflater = LayoutInflater.from(context);
        mSectionIndices = getSectionIndices();
        mSectionLetters = getSectionLetters();

        this.glossariesList = glossaries;
        glossariesListForSearch = glossaries;
    }

    private int[] getSectionIndices() {
        ArrayList<Integer> sectionIndices = new ArrayList<>();
        char lastFirstChar = mArrayList.get(0).charAt(0);
        sectionIndices.add(0);

        for (int i = 1; i < mArrayList.size(); i++) {
            if (mArrayList.get(i).charAt(0) != lastFirstChar) {
                lastFirstChar = mArrayList.get(i).charAt(0);
                sectionIndices.add(i);
            }
        }

        int[] sections = new int[sectionIndices.size()];
        for (int i = 0; i < sectionIndices.size(); i++) {
            sections[i] = sectionIndices.get(i);
        }
        return sections;
    }

    private Character[] getSectionLetters() {

        Character[] letters = new Character[mSectionIndices.length];
        for (int i = 0; i < mSectionIndices.length; i++) {
            letters[i] = mArrayList.get(mSectionIndices[i]).charAt(0);
        }
        return letters;
    }


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

    @Override
    public Object getItem(int position) {
        return glossariesList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.index_list_item_layout, parent, false);
            holder.text = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Glossary glossary = glossariesList.get(position);
        holder.text.setText(glossary.getName());

        return convertView;
    }

    @Override
    public View getHeaderView(int position, View convertView, ViewGroup parent) {
        HeaderViewHolder holder;

        if (convertView == null) {
            holder = new HeaderViewHolder();
            convertView = mInflater.inflate(R.layout.index_header, parent, false);
            holder.text = (TextView) convertView.findViewById(R.id.text1);
            convertView.setTag(holder);
        } else {
            holder = (HeaderViewHolder) convertView.getTag();
        }

        // set header text as first char in name
        CharSequence headerChar = glossariesList.get(position).getName().subSequence(0,1);
        holder.text.setText(headerChar);

        return convertView;
    }

    @Override
    public long getHeaderId(int position) {
        // return the first character of the country as ID because this is what
        // headers are based upon
        return glossariesList.get(position).getName().subSequence(0, 1).charAt(0);
    }

    @Override
    public int getPositionForSection(int section) {
        if (mSectionIndices.length == 0) {
            return 0;
        }

        if (section >= mSectionIndices.length) {
            section = mSectionIndices.length - 1;
        } else if (section < 0) {
            section = 0;
        }
        return mSectionIndices[section];
    }

    @Override
    public int getSectionForPosition(int position) {
        for (int i = 0; i < mSectionIndices.length; i++) {
            if (position < mSectionIndices[i]) {
                return i - 1;
            }
        }
        return mSectionIndices.length - 1;
    }

    @Override
    public Object[] getSections() {
        return mSectionLetters;
    }


    class HeaderViewHolder {
        TextView text;
    }

    class ViewHolder {
        TextView text;
    }


    @Override
    public Filter getFilter() {
        return myFilter;
    }

    Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            ArrayList<Glossary> tempGlossaryList = new ArrayList<>();

            if (constraint != null && glossariesListForSearch != null) {
                int length = glossariesListForSearch.size();
                int i = 0;
                while (i < length) {
                    Glossary item = glossariesListForSearch.get(i);

                    if (item.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
                        tempGlossaryList.add(item);
                    }
                    i++;
                }
                filterResults.values = tempGlossaryList;
                filterResults.count = tempGlossaryList.size();
            }
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            glossariesList = (ArrayList<Glossary>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    };
}

before you call mAdapter.notifyDataSetChanged(); you should remove the element from mAdapter.

您可以使用接口与AsyncTask进行通信

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