【问题标题】:ListView custom adapter, remove item using AsyncTaskListView 自定义适配器,使用 AsyncTask 删除项目
【发布时间】:2016-01-29 02:40:31
【问题描述】:

我正在使用自定义适配器来显示我的列表视图。首先,我使用 AsyncTask 检索要在列表视图中显示的信息,因为这些信息是从 PHP Web 服务中检索的。然后,要从列表视图中删除一个项目,它会再次调用 Web 服务来执行此操作。成功删除所选项目后,onPostExecute 方法会接收结果并删除该项目。但是,只有在刷新片段时,它才会从我的列表视图中删除。

 @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;
    }

上面的代码显示了上下文菜单,当用户选择删除时,一个警告对话框将提示他们确认操作。当他们选择 ok 时,它会执行 AsyncTask,如下所示:

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);
    }
}

我尝试使用mAdapter.notifyDataSetChanged();,但没有成功。我知道 mAdapter 是 Activity 类中的全局变量。另外,要注意我的适配器是一个自定义类。我最初想全局声明一个布尔值deleteSuccess,然后在onPostExecute 将其设置为true,结果== 1,但onContextItemSelected 不等待onPostExecute,只是将deleteSuccess 的值设为`false。

底线是,如何从适配器中删除所选项目,从而在删除项目后立即成功“刷新”ListView?

编辑:

这是我的自定义适配器类

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();
            }
        }
    };
}

【问题讨论】:

  • 不清楚你是如何定义mAdapter的,但你应该在某个地方调用mAdapter.remove()
  • 我已经为我的自定义适配器添加了代码。调用 mAdapter 后我没有得到删除方法,所以我认为我必须自己实现它。但是我应该怎么做呢?
  • 您可能想要使用 ArrayAdapter 而不是 BaseAdapter。如果要保留BaseAdapter,则需要自己实现remove
  • @cricket_007 嘿,帮了大忙!谢谢你:-)

标签: java android listview android-asynctask


【解决方案1】:

在调用 mAdapter.notifyDataSetChanged(); 之前,您应该从 mAdapter 中删除该元素。

【讨论】:

  • 是的,有效!我将适配器更改为 arrayadapter,因此我可以调用 mAdapter.remove(myObj),然后调用 notifyDataSetChanged。非常感谢你的帮助!干杯
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 2019-03-03
    相关资源
    最近更新 更多