I am using smack (XMPP library) and Mosby's MvpFagment
to show the roster of a user in a listview (his/her connections).
I got the following code which works in a different fragment just doing a network call using the Retrofit library:
public void loadListData(final List<NeighbourListItemModel> itemsList) {
Log.e("list", itemsList.size() + "");
listViewAdapter.clear();
listViewAdapter.addThemAll(itemsList);
listViewAdapter.notifyDataSetChanged();
}
Which gets called by a RosterListener
using roster.addRosterListener(new RosterListener() { .. });
The NeighbourListItemModel
is just a simple POJO class having some getters and setts.
However, this gives a AbstractXMPPConnection﹕ Exception in async packet listener
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
error, probably because the XMP connection runs in its own thread.
Now if I change the code to the following:
@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();
}
});
}
I get a java.lang.NullPointerException: Attempt to invoke virtual method 'int getLayout()' on a null object reference
error. Where getLayout is defined in:
@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;
}
The view holder abstract class is nothing special:
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);
}
}
So obviously the viewHolder
variable is null, but I have no idea why. My adapter is defined as new BaseListAdapter(this, R.layout.neighbours_list_item, new ArrayList<ChatItemModel>(), Constants.DATA_TYPE.CHAT);
Like I said, the former code is working when I make a call using Retrofit, but I suspect XMPP running in its own thread is giving me headaches.
The issue was that the Constants.DATA_TYPE itemType
was referring to another model instead of a NeighbourListItemModel
which caused a null return. The stacktrace did not show this clearly, but at least it is solved now.