1

我正在使用 smack(XMPP 库)和Mosby's MvpFagment在列表视图(他/她的连接)中显示用户名册。

我得到了以下代码,它在不同的片段中工作,只是使用 Retrofit 库进行网络调用:

public void loadListData(final List<NeighbourListItemModel> itemsList) {
    Log.e("list", itemsList.size() + "");
    listViewAdapter.clear();
    listViewAdapter.addThemAll(itemsList);
    listViewAdapter.notifyDataSetChanged();
}

RosterListenerusing调用roster.addRosterListener(new RosterListener() { .. });

NeighbourListItemModel只是一个简单的 POJO 类,有一些 getter 和 setts。

但是,这会产生AbstractXMPPConnection﹕ Exception in async packet listener android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.错误,可能是因为 XMP 连接在其自己的线程中运行。

现在,如果我将代码更改为以下内容:

@Override
public void loadListData(final List<NeighbourListItemModel> itemsList) {
    Log.e("list", itemsList.size() + "");
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            listViewAdapter.clear();
            listViewAdapter.addThemAll(itemsList);
            listViewAdapter.notifyDataSetChanged();
        }
    });
}

我得到一个java.lang.NullPointerException: Attempt to invoke virtual method 'int getLayout()' on a null object reference错误。其中 getLayout 定义在:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolderAbstractClass viewHolder;
        if (null == convertView || null == convertView.getTag()) {
            viewHolder = getItem(position).getDefaultViewHolder(mItemType);
            convertView = LayoutInflater.from(getContext()).inflate(viewHolder.getLayout(), null);
            viewHolder.findViewsById(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolderAbstractClass) convertView.getTag();
        }

        BaseModel previousItem = position > 0 ? getItem(position - 1) : null;
        viewHolder.setup(getItem(position), previousItem, mCaller.getContext(), position);

        return convertView;
    }

视图持有者抽象类没有什么特别之处:

public abstract class ViewHolderAbstractClass {

    abstract public int getLayout();

    abstract public void findViewsById(View view);

    abstract public void initializeComponentBehavior(BaseModel item, Context context, int position);

    public void setup(BaseModel item, BaseModel previous_item, Context context, int position) {
        initializeComponentBehavior(item, context, position);
    }

}

所以很明显这个viewHolder变量是空的,但我不知道为什么。我的适配器定义为new BaseListAdapter(this, R.layout.neighbours_list_item, new ArrayList<ChatItemModel>(), Constants.DATA_TYPE.CHAT);

就像我说的,当我使用 Retrofit 拨打电话时,以前的代码正在运行,但我怀疑在自己的线程中运行的 XMPP 让我很头疼。

4

2 回答 2

1

问题在于,Constants.DATA_TYPE itemType指的是另一个模型,而不是NeighbourListItemModel导致返回空值的模型。stacktrace 没有清楚地显示这一点,但至少现在已经解决了。

于 2015-08-28T12:10:49.663 回答
0

1)我认为这段代码viewHolder = getItem(position).getDefaultViewHolder(mItemType)是一个嫌疑犯。似乎代码正在缓存ViewHolder类,问题是您无法缓存或保存 UI ID。我相信您会注意到其他开发人员只是创建了一个ViewHolder.

除此之外,请发布 getDefaultViewHolder 的代码。

2)另一个,我怀疑findViewsById() 方法无法工作,因为它似乎正在尝试缓存 UI ID 以找到正确的 View 对象。

** 这个缓存 UI ID 的问题现在更加明显(!),因为您在单独的线程上获取 ID。

但是,您可以在单独的 UI 线程上更新 UI 视图。您可以在单独的线程上获取 UI ID,但不要缓存它,立即使用它。

于 2015-08-25T17:43:03.373 回答