更新后的Listview错误获取新数据

时间:2014-12-26 12:43:39

标签: java android listview android-listview

java.lang.IllegalStateException: adapter的内容已更改,但ListView未收到通知。确保不从后台线程修改适配器的内容,而只是从UI线程修改。确保您的适配器调用notifyDataSetChanged()

所以当你到达列表的最后时我正在使用自定义listView我会显示一个页脚视图,并在将使用listView的Activity / Fragment上创建一个实现的监听器。我的问题是当我在这个方法上调用服务并使用适配器的数据更新数组时我收到了该错误。我在适配器上调用了一个服务,因为我需要特定显示行的数据。

这是我的代码:

自定义列表视图:

public class EndlessListView extends ListView implements OnScrollListener {

    private View footer;
    private boolean isLoading;
    private EndlessListener listener;
    private ArrayAdapter<?> adapter;
    private boolean isReachEnd;

    public EndlessListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setOnScrollListener(this);
    }

    public EndlessListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnScrollListener(this);
    }

    public EndlessListView(Context context) {
        super(context);
        this.setOnScrollListener(this);
    }

    public void refreshList() {
        this.removeFooterView(footer);
        this.requestLayout();
        adapter.notifyDataSetChanged();
        isLoading = false;
    }

    public void setListener(EndlessListener listener) {
        this.listener = listener;
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {

        if (getAdapter() == null)
            return;

        if (getAdapter().getCount() == 0)
            return;

        int l = visibleItemCount + firstVisibleItem;
        if (l >= totalItemCount && !isLoading && !isReachEnd) {
            // It is time to add new data. We call the listener
            this.addFooterView(footer);
            this.requestLayout();
            isLoading = true;
            listener.loadData();
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    public void setLoadingView(int resId) {
        LayoutInflater inflater = (LayoutInflater) super.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        footer = (View) inflater.inflate(resId, null);
        this.addFooterView(footer);

    }

    public void setAdapter(ArrayAdapter<?> adapter) {
        super.setAdapter(adapter);
        this.adapter = adapter;
        this.removeFooterView(footer);
    }

    public void addNewData(ArrayList data) {
        this.removeFooterView(footer);
        this.requestLayout();
        adapter.addAll(data);
        adapter.notifyDataSetChanged();
        isLoading = false;
    }

    public void removeFooter() {
        if (adapter != null) {
            this.removeFooterView(footer);
            isLoading = false;
            this.adapter.notifyDataSetChanged();
            this.requestLayout();
        }
    }

    public void addFooter() {
        if (adapter != null) {
            this.addFooterView(footer);
            isLoading = true;
            this.adapter.notifyDataSetChanged();
            this.requestLayout();
        }
    }


    public EndlessListener setListener() {
        return listener;
    }

    public static interface EndlessListener {
        public void loadData();
    }

    public boolean isReachEnd() {
        return isReachEnd;
    }

    public void setReachEnd(boolean isReachEnd) {
        this.isReachEnd = isReachEnd;
    }

    public boolean isLoading() {
        return isLoading;
    }

    public void setLoading(boolean isLoading) {
        this.isLoading = isLoading;
    }

    @Override
    public ArrayAdapter<?> getAdapter() {
        return adapter;
    }

    public View getFooter() {
        return footer;
    }

    @Override
    public void setClickable(boolean clickable) {
        super.setClickable(clickable);
    }}

获取数据并更新适配器的数组:

public void getMatcher() {
    try {
        gettingMatcher = true;
        Timber.i(getString(R.string.getting_mather));
        HomeRequest.createMatcherRequest(getActivity(), new RequestController.ResponseListener<JSONObject>() {
            @Override
            public void onStart() {
                ((AuthorizedActivity) getActivity()).showProgress(true);
            }

            @Override
            public void onResponse(JSONObject response) {
                parseMatcher(response);
            }

            @Override
            public void onError(int error, String message) {
                gettingMatcher = false;
                ((AuthorizedActivity) getActivity()).showProgress(false);
                Utils.showToast(getActivity(), getString(R.string.error_unexpected));
            }
        });
    } catch (Exception e) {
        gettingMatcher = false;
        Timber.e(e, getString(R.string.error_getting_matcher));
        Crashlytics.logException(e);
    }
}

/**
 * Parse the data from the web services and load the UI
 *
 * @param response
 */
private void parseMatcher(JSONObject response) {
    MatcherResponse matcherResponse = new MatcherResponse(false, "");
    ArrayList<User> auxDiscover = new ArrayList<>();
    if (response == null) {
        Timber.e(getString(R.string.error_empty_response));
        Utils.showToast(getActivity(), getString(R.string.error_empty_response));
        ((AuthorizedActivity) getActivity()).showProgress(false);
        gettingMatcher = false;
        return;
    }

    try {
        Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .create();
        matcherResponse = gson.fromJson(response.toString(), MatcherResponse.class);
        if (matcherResponse.isSuccess()) {
            auxDiscover = matcherResponse.getDiscover();
            if (auxDiscover.size() > 0) {
                discoversData.addAll(auxDiscover);
                adapter.notifyDataSetChanged();
                discovers.removeFooter();
            }
        } else {
            Timber.e(getString(R.string.error_parsing_matcher));
            Utils.showToast(getActivity(), getString(R.string.error_unexpected));
        }
        gettingMatcher = false;
        ((AuthorizedActivity) getActivity()).showProgress(false);
    } catch (Exception e) {
        ((AuthorizedActivity) getActivity()).showProgress(false);
        gettingMatcher = false;
        Timber.e(getString(R.string.error_parsing_matcher));
        Crashlytics.logException(e);
    }
}

适配器:

 public class DiscoverEndlessAdapter extends ArrayAdapter {

    private ArrayList<User> itemList;
    private Context ctx;
    private static OnClickDiscoverEvents onClickDiscoverEvents;
    private DiscoverFragment fragment;

    public DiscoverEndlessAdapter(Context ctx, ArrayList<User> itemList, OnClickDiscoverEvents onClickDiscoverEvents, DiscoverFragment fragment) {
        super(ctx, R.layout.adapter_discover, itemList);
        this.itemList = itemList;
        this.ctx = ctx;
        this.onClickDiscoverEvents = onClickDiscoverEvents;
        this.fragment = fragment;
    }

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

    @Override
    public User getItem(int i) {
        return itemList.get(i);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        return getDiscoverRow(position, convertView, parent, holder);
    }

    static class ViewHolder {
        @InjectView(R.id.adapter_discover_title)
        TextView title;
        @InjectView(R.id.adapter_discover_subtitle)
        TextView subTitle;
        @InjectView(R.id.adapter_discover_avatar)
        ImageView avatar;
        @InjectView(R.id.adapter_discover_connect)
        TextView connectWith;
        @InjectView(R.id.adapter_discover_message)
        ImageButton message;
        @InjectView(R.id.adapter_discover_description)
        TextView description;
        @InjectView(R.id.adapter_discover_more)
        ImageButton more;
        @InjectView(R.id.adapter_discover_avatar_connection)
        ImageView avatarConnection;
        @InjectView(R.id.adapter_discover_avatar_connection_2)
        ImageView avatarConnection2;
        @InjectView(R.id.adapter_discover_avatar_connection_3)
        ImageView avatarConnection3;
        @InjectView(R.id.adapter_discover_avatar_connection_4)
        ImageView avatarConnection4;
        @InjectView(R.id.adapter_discover_connection_opacity)
        TextView avatarConnectionOpacity;
        @InjectView(R.id.adapter_discover_message)
        ImageButton messageButton;
        @InjectView(R.id.adapter_discover_more)
        ImageButton optionButton;

        /*OnClick*/
        @OnClick(R.id.adapter_discover_message)
        public void onGoChat(View view) {
            onClickDiscoverEvents.showProfile(view);
        }

        @OnClick(R.id.adapter_discover_more)
        public void onShowMoreOption(View view) {
            onClickDiscoverEvents.showOption(view);
        }

        private Context ctx;

        public ViewHolder(View view, Context ctx) {
            ButterKnife.inject(this, view);
            this.ctx = ctx;
        }
    }

    /**
     * Create the view for the chat data row
     *
     * @param position
     * @param convertView
     * @param parent
     * @param holder
     * @return
     */
    private View getDiscoverRow(int position, View convertView, ViewGroup parent, ViewHolder holder) {
        try {
            User user = getItem(position);
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            } else {
                LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.adapter_discover, parent, false);
                holder = new ViewHolder(convertView, ctx);
                convertView.setTag(holder);
            }

            // Title
            String title = Utils.getNameFromUser(user);
            holder.title.setText(title);

            // Subtitle
            String subTitle = Utils.getRoleAndLocationFromUser(user);
            holder.subTitle.setText(subTitle);

            // Description
            String description = user.getAccomplishment();
            holder.description.setText(description);

            //Avatar
            Utils.setImageToImageViewFromUrl(ctx, holder.avatar, user.getImage(), user.getFirstName(), user.getLastName());

            //ImageButtons
            holder.more.setFocusable(false);
            holder.message.setFocusable(false);

            //CommonConnections
            if (user.getCommonConnections() == null)
                getCommonConnections(user.getId(), position);
            else {
                ArrayList<Connection> connections = user.getCommonConnections();
                if (connections.size() > 0) {
                    if ((connections.size() > 0) && (holder.avatarConnection.getVisibility() != View.VISIBLE)) {
                        Connection connection = connections.get(0);
                        Utils.setImageToImageViewFromUrl(ctx, holder.avatarConnection, connection.getImage(), connection.getFirstName(), connection.getLastName());
                        holder.avatarConnection.setVisibility(View.VISIBLE);
                    }

                    if ((connections.size() > 1) && (holder.avatarConnection2.getVisibility() != View.VISIBLE)) {
                        Connection connection = connections.get(1);
                        Utils.setImageToImageViewFromUrl(ctx, holder.avatarConnection2, connection.getImage(), connection.getFirstName(), connection.getLastName());
                        holder.avatarConnection2.setVisibility(View.VISIBLE);
                    }

                    if ((connections.size() > 2) && (holder.avatarConnection3.getVisibility() != View.VISIBLE)) {
                        Connection connection = connections.get(2);
                        Utils.setImageToImageViewFromUrl(ctx, holder.avatarConnection3, connection.getImage(), connection.getFirstName(), connection.getLastName());
                        holder.avatarConnection3.setVisibility(View.VISIBLE);
                    }

                    if ((connections.size() > 3) && (holder.avatarConnection4.getVisibility() != View.VISIBLE)) {
                        Connection connection = connections.get(3);
                        Utils.setImageToImageViewFromUrl(ctx, holder.avatarConnection4, connection.getImage(), connection.getFirstName(), connection.getLastName());
                        holder.avatarConnection4.setVisibility(View.VISIBLE);
                    }

                    if ((connections.size() > 4) && (holder.avatarConnectionOpacity.getVisibility() != View.VISIBLE)) {
                        int quantity = connections.size() - 4;
                        String moreConnections = "+" + quantity;
                        if (quantity > 0) {
                            holder.avatarConnectionOpacity.setText(moreConnections);
                            holder.avatarConnectionOpacity.setVisibility(View.VISIBLE);
                        }
                    }
                } else {
                    if (isCommon(user.getSkills())) {
                        holder.avatarConnection.setImageResource(R.drawable.ic_common_skill);
                    } else
                        holder.avatarConnection.setVisibility(View.GONE);

                    if (isCommon(user.getCompanies())) {
                        holder.avatarConnection2.setImageResource(R.drawable.ic_common_work);
                    } else
                        holder.avatarConnection2.setVisibility(View.GONE);

                    holder.avatarConnection3.setVisibility(View.GONE);
                    holder.avatarConnection4.setVisibility(View.GONE);
                    holder.avatarConnectionOpacity.setVisibility(View.GONE);
                }
            }

            //Buttons
            holder.messageButton.setTag(user);
            holder.optionButton.setTag(user);

        } catch (Exception e) {
            Timber.e(e, ctx.getString(R.string.error_getview_discover_adapter));
            Crashlytics.log(ctx.getString(R.string.error_getview_discover_adapter));
        }

        return convertView;
    }


    public void getCommonConnections(long caliberId, final int position) {
        try {
            Timber.i(ctx.getString(R.string.getting_common_connections));
            HomeRequest.createCommonConnectionsRequest(ctx, caliberId, new RequestController.
                    ResponseListener<JSONObject>() {
                @Override
                public void onStart() {

                }

                @Override
                public void onResponse(JSONObject response) {
                    parseCommonConnections(response, position);
                }

                @Override
                public void onError(int error, String message) {
                    Toast.makeText(ctx, ctx.getString(R.string.error_unexpected), Toast.LENGTH_SHORT).show();
                }
            });
        } catch (Exception e) {
            Timber.e(e, ctx.getString(R.string.error_getting_common_connections));
            Crashlytics.logException(e);
        }
    }

    /**
     * Parse the data from the web services and load the UI
     *
     * @param response
     */
    private void parseCommonConnections(JSONObject response, int position) {
        CommonConnectionsResponse commonConnectionsResponse = new CommonConnectionsResponse();
        ArrayList<Connection> connections = new ArrayList<>();
        if (response == null) {
            Timber.e(ctx.getString(R.string.error_empty_response));
            return;
        }

        try {
            Gson gson = new GsonBuilder()
                    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                    .create();
            commonConnectionsResponse = gson.fromJson(response.toString(), CommonConnectionsResponse.class);
            if (commonConnectionsResponse.isSuccess()) {
                itemList.get(position).setCommonConnections(commonConnectionsResponse.getConnections().getConnections());
                fragment.discoversData.get(position).setCommonConnections(commonConnectionsResponse.getConnections().getConnections());
            } else {
                itemList.get(position).setCommonConnections(new ArrayList<Connection>());
                fragment.discoversData.get(position).setCommonConnections(new ArrayList<Connection>());
                Timber.i(ctx.getString(R.string.no_common_connections, Utils.getNameFromUser(fragment.discoversData.get(position))));
            }
            notifyDataSetChanged();
        } catch (Exception e) {
            Timber.e(ctx.getString(R.string.error_parsing_common_connections));
            Crashlytics.logException(e);
        }
    }

    /**
     * Return common value of skill or company object from list
     *
     * @param list
     * @return
     */
    private boolean isCommon(ArrayList<?> list) {
        if ((list != null) && (list.size() > 0)) {
            for (int i = 0; i < list.size(); i++) {
                Object object = list.get(i);
                if (object instanceof Skill) {
                    if (((Skill) object).isCommon())
                        return true;
                } else if (object instanceof Company) {
                    if (((Company) object).isCommon())
                        return true;
                } else
                    return false;
            }
        } else
            return false;
        return false;
    }
}

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以在修改适配器内的数据之前尝试调用setAdapter(null)。