自定义BaseAdapter具有不同的行布局,convertView为null

时间:2015-03-12 18:53:41

标签: java android nullpointerexception baseadapter

我无法弄清楚为什么我使用不同行类型的自定义NullPointerException获得BaseAdapter。我正在使用ViewHolder模式,当我得到这个NPE时,ViewHolder为空。但是查看下面的代码,是不是总会引用ViewHolder?

使用getItemViewType应始终返回有效的行布局,并在第一个switch语句中覆盖所有这些类型,以处理行的膨胀。

这一行是给我问题的问题:

case TYPE_TEXT_YOU: if (message != null) holder.message.setText(message);

这很奇怪,因为之前工作正常。我没有太大变化,但现在它给了我这个问题。请帮忙!!!

public class ChatAdapter extends BaseAdapter {

private static final int TYPE_TEXT_YOU = 0;
private static final int TYPE_AUDIO_YOU = 1;
private static final int TYPE_TEXT_THEM = 2;
private static final int TYPE_AUDIO_THEM = 3;
private static final int TYPE_MATCH_NOTICE = 4;
private static final int TYPE_EMPTY_ROW = 5;

private Context mContext;
private List<ChatMessage> mMessages;
private String mPartnerUserId;
private SharedPrefs mPrefs;
private DatabaseHelper mDb;
private User mUser;
private User mPartnerUser;
private AudioHelper mAudioHelper;

public ChatAdapter(Context context, List<ChatMessage> messages, String partnerUserId) {
    mContext = context;
    mMessages = messages;
    mPartnerUserId = partnerUserId;
    mPrefs = new SharedPrefs(context);
    mAudioHelper = AudioHelper.getInstance(context, partnerUserId);
    mDb = DatabaseHelper.getInstance(context);
    mUser = mDb.getUser(mPrefs.getUserId());
    mPartnerUser = mDb.getUser(partnerUserId);
}

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

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

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

@Override
public int getItemViewType(int position) {
    ChatMessage message = mMessages.get(position);

    switch (message.getMessageType()) {
        case ChatMessage.TYPE_GAME_DATE:
            return TYPE_MATCH_NOTICE;

        case ChatMessage.TYPE_TEXT:
            if (message.getSenderUserId().equals(mPrefs.getUserId())) {
                return TYPE_TEXT_YOU;
            }
            else {
                return TYPE_TEXT_THEM;
            }

        case ChatMessage.TYPE_AUDIO:
            if (message.getSenderUserId().equals(mPrefs.getUserId())) {
                return TYPE_AUDIO_YOU;
            }
            else {
                return TYPE_AUDIO_THEM;
            }

        default:
            return TYPE_EMPTY_ROW;
    }
}

@Override
public int getViewTypeCount() {
    return 6;
}

public class ViewHolder {
    private ImageView avatar;
    private CustomTextView timestamp;
    private CustomTextView message;
    private CustomTextView date;
    private CustomTextView time;
    private LinearLayout btnPlayAudio;
    private ImageView ivPlayAudio;
    private ProgressBar spinPlayingAudio;
    private CustomTextView tvPlayAudio;
    private ImageView gameCover;
    private ProgressBar spinGameCover;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    int type = getItemViewType(position);

    if (convertView == null) {
        holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context
                .LAYOUT_INFLATER_SERVICE);

        switch (type) {
            case TYPE_TEXT_YOU:
                convertView = inflater.inflate(R.layout.row_chat_you, parent, false);
                holder.avatar = (ImageView) convertView.findViewById(R.id.avatar_you);
                holder.message = (CustomTextView) convertView.findViewById(R.id.message_you);
                holder.timestamp = (CustomTextView) convertView.findViewById(R.id.timestamp_you);
                break;

            case TYPE_AUDIO_YOU:
                convertView = inflater.inflate(R.layout.row_chat_audio_you, parent, false);
                holder.avatar = (ImageView) convertView.findViewById(R.id.avatar_you);
                holder.timestamp = (CustomTextView) convertView.findViewById(R.id.timestamp_you);
                holder.btnPlayAudio = (LinearLayout) convertView.findViewById(R.id.btn_play_audio_you);
                holder.ivPlayAudio = (ImageView) convertView.findViewById(R.id.iv_play_audio);
                holder.spinPlayingAudio = (ProgressBar) convertView.findViewById(R.id.spin_playing_audio);
                holder.tvPlayAudio = (CustomTextView) convertView.findViewById(R.id.tv_play_audio);
                break;

            case TYPE_TEXT_THEM:
                convertView = inflater.inflate(R.layout.row_chat_them, parent, false);
                holder.avatar = (ImageView) convertView.findViewById(R.id.avatar_them);
                holder.message = (CustomTextView) convertView.findViewById(R.id.message_them);
                holder.timestamp = (CustomTextView) convertView.findViewById(R.id.timestamp_them);
                break;

            case TYPE_AUDIO_THEM:
                convertView = inflater.inflate(R.layout.row_chat_audio_them, parent, false);
                holder.avatar = (ImageView) convertView.findViewById(R.id.avatar_them);
                holder.timestamp = (CustomTextView) convertView.findViewById(R.id.timestamp_them);
                holder.btnPlayAudio = (LinearLayout) convertView.findViewById(R.id.btn_play_audio_them);
                holder.ivPlayAudio = (ImageView) convertView.findViewById(R.id.iv_play_audio);
                holder.spinPlayingAudio = (ProgressBar) convertView.findViewById(R.id.spin_playing_audio);
                holder.tvPlayAudio = (CustomTextView) convertView.findViewById(R.id.tv_play_audio);
                break;

            case TYPE_MATCH_NOTICE:
                convertView = inflater.inflate(R.layout.row_chat_match_notice, parent, false);
                holder.gameCover = (ImageView) convertView.findViewById(R.id.game_cover);
                holder.spinGameCover = (ProgressBar) convertView.findViewById(R.id.spin_game_cover);
                holder.date = (CustomTextView) convertView.findViewById(R.id.date);
                holder.time = (CustomTextView) convertView.findViewById(R.id.time);
                break;

            case TYPE_EMPTY_ROW:
                convertView = inflater.inflate(R.layout.row_padding_10dp, parent, false);
                break;
        }
        convertView.setTag(holder);
    }
    else holder = (ViewHolder) convertView.getTag();

    String message = mMessages.get(position).getMessage();
    String timestamp = mMessages.get(position).getTimeStamp();
    final String audioFilepath = mMessages.get(position).getFilepath();
    DateTime dateTime;
    DateTimeFormatter formatter = DateTimeFormat.forPattern(GlobalVars.FORMAT_MESSAGE_TIMESTAMP);

    final ViewHolder finalHolder = holder;

    switch (type) {
        case TYPE_TEXT_YOU:
            if (message != null) holder.message.setText(message);

            if (timestamp != null && !timestamp.isEmpty()) {
                try {
                    dateTime = ISODateTimeFormat.dateTime().parseDateTime(timestamp);
                    if (dateTime != null) holder.timestamp.setText(formatter.print(dateTime));
                }
                catch (IllegalArgumentException e) { e.printStackTrace(); }
            }

            if (mUser != null && mUser.getAvatarType() != null && !mUser.getAvatarType().isEmpty()) {
                try {
                    holder.avatar.setImageDrawable(mContext.getResources().getDrawable(ViewHelper
                            .getAvatarHeadDrawableId(mContext, mUser.getAvatarType())));
                }
                catch (Resources.NotFoundException e) { e.printStackTrace(); }
            }
            break;

        case TYPE_AUDIO_YOU:
            if (timestamp != null && !timestamp.isEmpty()) {
                try {
                    dateTime = ISODateTimeFormat.dateTime().parseDateTime(timestamp);
                    if (dateTime != null) holder.timestamp.setText(formatter.print(dateTime));
                }
                catch (IllegalArgumentException e) { e.printStackTrace(); }
            }

            if (mUser != null && mUser.getAvatarType() != null && !mUser.getAvatarType().isEmpty()) {
                try {
                    holder.avatar.setImageDrawable(mContext.getResources().getDrawable(ViewHelper
                            .getAvatarHeadDrawableId(mContext, mUser.getAvatarType())));
                }
                catch (Resources.NotFoundException e) { e.printStackTrace(); }
            }

            holder.btnPlayAudio.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (audioFilepath != null && !audioFilepath.isEmpty()) {
                        mAudioHelper.changeViewsOfStoppedAudioMessage();
                        mAudioHelper.setPlayingAudioViews(finalHolder.ivPlayAudio,
                                finalHolder.spinPlayingAudio, finalHolder.tvPlayAudio);
                        mAudioHelper.playAudio(audioFilepath);
                    }
                }
            });
            break;

        case TYPE_TEXT_THEM:
            if (message != null) holder.message.setText(message);

            if (timestamp != null && !timestamp.isEmpty()) {
                try {
                    dateTime = ISODateTimeFormat.dateTime().parseDateTime(timestamp);
                    if (dateTime != null) holder.timestamp.setText(formatter.print(dateTime));
                }
                catch (IllegalArgumentException e) { e.printStackTrace(); }
            }

            if (mPartnerUser != null && mPartnerUser.getAvatarType() != null) {
                try {
                    holder.avatar.setImageDrawable(mContext.getResources().getDrawable(ViewHelper
                            .getAvatarHeadDrawableId(mContext, mPartnerUser.getAvatarType())));
                }
                catch (Resources.NotFoundException e) { e.printStackTrace(); }
            }
            break;

        case TYPE_AUDIO_THEM:
            if (timestamp != null && !timestamp.isEmpty()) {
                try {
                    dateTime = ISODateTimeFormat.dateTime().parseDateTime(timestamp);
                    if (dateTime != null) holder.timestamp.setText(formatter.print(dateTime));
                }
                catch (IllegalArgumentException e) { e.printStackTrace(); }
            }

            if (mPartnerUser != null && mPartnerUser.getAvatarType() != null) {
                try {
                    holder.avatar.setImageDrawable(mContext.getResources().getDrawable(ViewHelper
                            .getAvatarHeadDrawableId(mContext, mPartnerUser.getAvatarType())));
                }
                catch (Resources.NotFoundException e) { e.printStackTrace(); }
            }

            holder.btnPlayAudio.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (audioFilepath != null && !audioFilepath.isEmpty()) {
                        mAudioHelper.changeViewsOfStoppedAudioMessage();
                        mAudioHelper.setPlayingAudioViews(finalHolder.ivPlayAudio,
                                finalHolder.spinPlayingAudio, finalHolder.tvPlayAudio);
                        mAudioHelper.playAudio(audioFilepath);
                    }
                }
            });
            break;

        case TYPE_MATCH_NOTICE:
            if (message != null) {
                if (message.contains("{")) {
                    Bundle info = null;
                    message = message.substring(message.indexOf("{"));
                    try {
                        JSONObject obj = new JSONObject(message);
                        info = JsonHelper.parseMatchNoticeMessageJson(obj);
                    }
                    catch (JSONException e) { e.printStackTrace(); }

                    if (info != null) {
                        if (info.containsKey(GlobalVars.KEY_GAME) && info.containsKey(GlobalVars
                                .KEY_PLATFORM)) {
                            Game game = mDb.getGame(info.getString(GlobalVars.KEY_GAME),
                                    info.getString(GlobalVars.KEY_PLATFORM));

                            if (game != null && game.getCoverPhoto() != null) {
                                ViewHelper.loadOrDownloadGameCover(mContext, game.getCoverPhoto(),
                                        holder.gameCover, holder.spinGameCover);
                            }
                        }

                        if (info.containsKey(GlobalVars.KEY_GAME_TIME)) {
                            String matchTime = info.getString(GlobalVars.KEY_GAME_TIME);

                            if (matchTime != null && !matchTime.isEmpty()) {
                                try {
                                    dateTime = ISODateTimeFormat.dateTime().parseDateTime(matchTime);

                                    if (dateTime != null) {
                                        holder.date.setText(DateTimeFormat.forPattern(GlobalVars
                                                .FORMAT_DATE_WITH_DAY_OF_WEEK).print(dateTime));
                                        holder.time.setText(DateTimeFormat.forPattern(GlobalVars
                                                .FORMAT_TIME).print(dateTime));
                                    }
                                }
                                catch (IllegalArgumentException e) { e.printStackTrace(); }
                            }
                        }
                    }
                }
            }
            break;
    }

    return convertView;
}

public void refreshList(List<ChatMessage> updatedMessages) {
    mMessages.clear();
    mMessages.addAll(updatedMessages);
    this.notifyDataSetChanged();
}

}

我的Stacktrace

java.lang.NullPointerException
   at com.walintukai.lovelup.adapters.ChatAdapter$ViewHolder.access$100(ChatAdapter.java:118)
   at com.walintukai.lovelup.adapters.ChatAdapter.getView(ChatAdapter.java:201)
   at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:230)
   at android.widget.AbsListView.obtainView(AbsListView.java:2739)
   at android.widget.ListView.makeAndAddView(ListView.java:1801)
   at android.widget.ListView.fillUp(ListView.java:733)
   at android.widget.ListView.fillGap(ListView.java:670)
   at android.widget.AbsListView.trackMotionScroll(AbsListView.java:6747)
   at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3988)
   at android.widget.AbsListView.onTouchMove(AbsListView.java:4840)
   at android.widget.AbsListView.onTouchEvent(AbsListView.java:4668)
   at android.view.View.dispatchTouchEvent(View.java:8135)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2417)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2141)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2423)
   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2156)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2295)
   at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1622)
   at android.app.Activity.dispatchTouchEvent(Activity.java:2565)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2243)
   at android.view.View.dispatchPointerEvent(View.java:8343)
   at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4743)
   at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4609)
   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4167)
   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4221)
   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4190)
   at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4301)
   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4198)
   at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4358)
   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4167)
   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4221)
   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4190)
   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4198)
   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4167)
   at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6517)
   at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6434)
   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6405)
   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6370)
   at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6597)
   at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
   at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
   at android.os.MessageQueue.next(MessageQueue.java:138)
   at android.os.Looper.loop(Looper.java:123)
   at android.app.ActivityThread.main(ActivityThread.java:5579)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:515)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
   at dalvik.system.NativeStart.main(NativeStart.java)

1 个答案:

答案 0 :(得分:0)

玩了一遍,找到了答案。所以我猜这些行的一些标记是null所以它会调用带有else的{​​{1}}语句convertView.getTag()

解决方案是检查null是否如此:

convertView.getTag() == null