【问题标题】:Updating listView through a custom adapter in a fragment通过片段中的自定义适配器更新 listView
【发布时间】:2026-01-27 17:20:05
【问题描述】:

我正在尝试在我的 android 应用程序中创建一个消息传递系统。当用户进入消息片段时,我需要用上一条消息填充消息列表。根据我的阅读,最好的方法是使用自定义适配器。

这是我的消息适配器

public class MessageAdapter extends ArrayAdapter<message>  {
private final MessagesFragment context;
private final int layoutResourceId;
private final ArrayList<message> messages;

public MessageAdapter(MessagesFragment messagesFragment, int layoutResourceId, ArrayList<message> messages) {
    super(null, layoutResourceId);
    this.context = messagesFragment;
    this.layoutResourceId = layoutResourceId;
    this.messages = messages;

}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
    View row = convertView;
    ViewHolder  holder = null;
    int direction = messages.get(i).userType;
    //show message on left or right, depending on if
    //it's incoming or outgoing

    if (row == null) {
        LayoutInflater inflater = ((MessagesFragment)context).getLayoutInflater(); 

        int res = 0;
        if (direction == DIRECTION_INCOMING) {
            res = R.layout.message_right;
        } else if (direction == DIRECTION_OUTGOING) {
            res = R.layout.message_left;
        }    
        convertView = inflater.inflate(res, viewGroup, false);
        holder = new ViewHolder();
        holder.txtMessage = (TextView) convertView.findViewById(R.id.txtMessage);
        holder.txtDate = (TextView) convertView.findViewById(R.id.txtDate);
        row.setTag(holder);
    }

     holder.txtMessage.setText(messages.get(i).message);
     holder.txtDate.setText(messages.get(i).time);

     return row;
}

static class ViewHolder
{
    TextView txtMessage;
    TextView txtDate;
}

}

我在我的片段中的 onCreateView 中调用它。

        // Generates all of the messages
    ArrayList<message> messages = getMessages;
    View messagesView = inflater.inflate(R.layout.messages, container, false);
    ListView listView = (ListView)messagesView.findViewById(R.id.listMessages);
    listView.setAdapter(new MessageAdapter(MessagesFragment.this, R.id.listMessages, messages));
    ...

每当我输入片段时,我的应用程序就会崩溃。我已经获取了一些示例代码并应用于我的应用程序,但我无法让它工作。我没有看到任何建议或明显错误?

【问题讨论】:

  • 你能把崩溃日志放上去吗?并更改“super(null, layoutResourceId);”到“super(messagesFragment.getActivity(), layoutResourceId);”

标签: android android-fragments android-arrayadapter listadapter


【解决方案1】:

看起来您的设计方式错误 - 您的 MessageAdapter 将片段作为参考。相反,您的活动应该创建和使用您的片段并在您的片段中,实例化您的适配器并做它应该做的任何事情,例如检索消息数据并填充您的列表。 因此,您的活动上下文将传递给您的片段 - 然后使用相同的上下文传递给您的自定义适配器的构造函数。

【讨论】:

  • 嗯,这是在我的片段中。我的活动调用我的片段,并在片段中的 oncreate 上尝试将适配器设置为 listView。我应该将什么传递给我的适配器?我从Here 阅读的指南在上下文中传递,这是一个活动。我把它改成了我的 Fragment,eclipse 建议我把它改成我的 MessageFragment。
【解决方案2】:

在您的片段中更改:

 listView.setAdapter(new MessageAdapter(MessagesFragment.this, R.id.listMessages, messages));

 listView.setAdapter(new MessageAdapter(MessagesFragment.this.getActivity(), R.id.listMessages, messages));

在您的适配器中更改:

private final MessagesFragment context;

    public MessageAdapter(MessagesFragment messagesFragment, int layoutResourceId, ArrayList<message> messages) {
        super(null, layoutResourceId);
        this.context = messagesFragment;
        this.layoutResourceId = layoutResourceId;
        this.messages = messages;
}

private final Context context;

public MessageAdapter(Context context, int layoutResourceId, ArrayList<message> messages) {
        super(context, layoutResourceId);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.messages = messages;
}

【讨论】:

  • 我收到来自片段更改的错误。特别是 MessagesFragment.getActivity()。
  • 使用 getActivity() 修复它;它运行,但仍然崩溃。
  • @confusedProgrammer 请发布崩溃日志
【解决方案3】:
public class MessageAdapter extends ArrayAdapter<message>  {
private final MessagesFragment context;
private final int layoutResourceId;
private final ArrayList<message> messages;

public MessageAdapter(MessagesFragment messagesFragment, int layoutResourceId, ArrayList<message> messages) {
    super(null, layoutResourceId);
    this.context = messagesFragment;
    this.layoutResourceId = layoutResourceId;
    this.messages = messages;

}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
    View row = convertView;
    ViewHolder  holder = null;
    int direction = messages.get(i).userType;
    //show message on left or right, depending on if
    //it's incoming or outgoing

    if (row == null) {
        LayoutInflater inflater = ((MessagesFragment)context).getLayoutInflater(); 

        int res = 0;
        if (direction == DIRECTION_INCOMING) {
            res = R.layout.message_right;
        } else if (direction == DIRECTION_OUTGOING) {
            res = R.layout.message_left;
        }    
        convertView = inflater.inflate(res, viewGroup, false);
        holder = new ViewHolder();
        holder.txtMessage = (TextView) convertView.findViewById(R.id.txtMessage);
        holder.txtDate = (TextView) convertView.findViewById(R.id.txtDate);
        row.setTag(holder);
    }
     //You have get tag every time else it will through NullPointerException
     holder = (ViewHolder)row.getTag();
     holder.txtMessage.setText(messages.get(i).message);
     holder.txtDate.setText(messages.get(i).time);

     return row;
}

static class ViewHolder
{
    TextView txtMessage;
    TextView txtDate;
}

检查上面的代码你犯了一些错误,我已经纠正了。

【讨论】: