NotifyDatasetChanged无法使用自定义适配器

时间:2016-10-07 15:27:19

标签: android listview adapter

我正在尝试使用自定义适配器填充ListView 我想使用NotifyDatasetChanged刷新布局,但它不起作用 我从HTTP请求中检索一些JSON数据,然后操纵结果字符串,然后填充ListView

我的代码有什么问题? 更新代码(有关建议)

public class CalendarioFragment extends Fragment {
    ListView listView;
    ArrayList<Calendario> calenList;
    CalendarioAdapter adapter;
    String json;
    ArrayList<String> arrayId = new ArrayList<String>();
    ArrayList<String> arrayData = new ArrayList<String>();

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.calendario_layout, null);

        listView = (ListView) view.findViewById(R.id.listCale);
        listView.setEmptyView(view.findViewById(R.id.emptyElement));

        calenList = new ArrayList<Calendario>();
        adapter = new CalendarioAdapter(getActivity(), calenList);
        listView.setAdapter(adapter);

        execQuery("query", "0");

        return view;
    }

    private void execQuery(final String query, final String taskId) {
        final MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse() {
            @Override
            public void onTaskCompleted(String output) {

                if (output == null) {
                    Toast.makeText(getActivity(), "Nessuna connessione internet attiva!", Toast.LENGTH_SHORT).show();
                } else {
                    json = output;

                    try {
                        ParseJson();
                        calenList.clear();

                        String[] ids = arrayId.toArray(new String[arrayId.size()]);
                        String[] date = arrayData.toArray(new String[arrayData.size()]);

                        for (int i = 0; i < ids.length; i++) {
                            Calendario calendario = new Calendario();
                            calendario.setId(ids[i]);
                            calendario.setData(date[i]);

                            calenList.add(calendario);
                            adapter.updateData(calenList);
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, getActivity());

        asyncTask.execute(query, taskId);
    }

    private void ParseJson() throws JSONException {
        JSONObject jsonObject = new JSONObject(json);
        JSONArray jsonArray = jsonObject.getJSONArray("risposta");

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject JO = jsonArray.getJSONObject(i);
            arrayId.add(JO.getString("ID"));
            arrayData.add(JO.getString("DATA"));
        }
    }
}

这是CustomAdapterCode:

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class CalendarioAdapter extends BaseAdapter {
    private ArrayList listData;
    private LayoutInflater layoutInflater;
    final static String TAG = "sb.dl";

    public CalendarioAdapter(Context context, ArrayList listData) {
        Log.d(TAG, "CalendarioAdapter");
        this.listData = listData;
        layoutInflater = LayoutInflater.from(context);
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Log.d(TAG, "CalendarioAdapter.getView");
        ViewHolder holder;

        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.calendario_row_layout, null);
            holder = new ViewHolder();
            holder.edId = (TextView) convertView.findViewById(R.id.edId);
            holder.edData = (TextView) convertView.findViewById(R.id.edData);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Calendario newsItem = (Calendario) listData.get(position);
        holder.edId.setText(newsItem.getId());
        holder.edData.setText(newsItem.getData());

        return convertView;
    }

    static class ViewHolder {
        TextView edId;
        TextView edData;
    }

public void updateData(ArrayList<Calendario> updatedData) {
    listData = updatedData;
    this.notifyDataSetChanged();
}
}

4 个答案:

答案 0 :(得分:0)

<强>问题:

listDataCale类中的变量。当您为其设置新值时,Cale类中的变量将被修改。设置数据副本的其余代码不会更改。换句话说,当您修改CalendarioAdapter类中的listData时,Cale内的数据不会更新。

<强>解决方案:

更改后,您需要再次将更新的listData传递给适配器。为此,您需要在CalendarioAdapter适配器内创建一个方法,该方法将负责更新适配器内部的数据,然后调用notifyDataSetChanged()

将此方法添加到CalendarioAdapter适配器:

public void updateData(ArrayList<Calendario> updatedData) {
    listDataInYourAdapter = newData;
    this.notifyDataSetChanged();
}

现在使用该方法,在Cale类中替换为:

adapter.notifyDataSetChanged();

用这个:

updateData(listData);

答案 1 :(得分:0)

这三行之后

listData = new ArrayList<Calendario>();
adapter = new CalendarioAdapter(getActivity(), listData);
listView.setAdapter(adapter);

您永远不应该重新分配 listData。完成后,适配器中列表的引用已分离,不再可以通知更新。

因此,您需要在列表中clear(),然后addAll()

例如,

ParseJson(); // You should really pass 'output' as a parameter here
listData = getListData(); // Don't re-assign

改为执行此操作,然后通知

ParseJson();
listData.clear();
listData.addAll(getListData());

或者,为什么要拨打listData.addAll(getListData());?您已经有了这种方法,可以正确清除,添加和通知。

private ArrayList<Calendario> getListData() {

    listData.clear(); // Cleared
    String[] ids = arrayId.toArray(new String[arrayId.size()]);
    String[] date = arrayData.toArray(new String[arrayData.size()]);

    for (int i = 0; i < ids.length; i++) {
        Calendario calendario = new Calendario();
        calendario.setId(ids[i]);
        calendario.setData(date[i]);

        listData.add(calendario); // Adding
    }

    adapter.notifyDataSetChanged(); // Notify

    return listData;
}

所以,实际上,你只需要在AsyncTask中使用这两行(并且再次添加output作为ParseJson的参数,你不需要保存json = output )。

ParseJson();
getListData();

答案 2 :(得分:0)

我解决了! 那是一件蠢事!

在parseJson sub中,我需要在填充之前清除数组!

private void ParseJson() throws JSONException {
    JSONObject jsonObject = new JSONObject(json);
    JSONArray jsonArray = jsonObject.getJSONArray("risposta");

    arrayId.clear();
    arrayData.clear();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject JO = jsonArray.getJSONObject(i);
            arrayId.add(JO.getString("ID"));
            arrayData.add(JO.getString("DATA"));
        }
    }

答案 3 :(得分:0)

再次重新分配列表 - &gt;这不是推荐的行为。 以下是正确的方法: 适配器内部:public void update(List<ItemMessage> updatedList){ list.clear(); list.addAll(updatedList); notifyDataSetChanged();}

  • 不要忘记使用处理程序