为什么我的自定义Android ArrayAdapter在向阵列添加新数据时不刷新其ListView?

时间:2016-04-13 16:11:08

标签: android listview android-arrayadapter

作为我的Android应用程序的一部分,我正在集成一个非常简单的自定义群聊功能;这只是一个概念验证功能。我知道这是暂时的,每当我重新启动应用程序时,我的聊天就会消失。我的应用使用Fragments和ViewPager在我的应用中创建标签。

我支持此功能的是一个LinkedList,它包含Message对象(发送时间,发件人姓名,消息)。无论何时发送或接收聊天,都会将其添加到LinkedList。在MainActivity.java的开头,我声明了列表

public static LinkedList<Message> chatList;

在onCreate方法中,我初始化列表

chatList = new LinkedList<Message>();

我有一个在后台运行的侦听器线程,用于侦听传入的消息。我在其构造函数

中将chatList传递给了这个线程
MyListener myListener = new MyListener(MainActivity.this, chatList);
Thread listenerThread = new Thread(myListener);
listenerThread.start();

每当侦听器线程收到消息时,它都会将其粘贴到LinkedList

chatList.add(new_message_object);

要显示聊天记录,我使用由自定义ArrayAdapter支持的ListView,我在其中覆盖了getView()方法。 ArrayAdapter从我的LinkedList的toArray()方法获取数组,并在屏幕上显示聊天。

此过程几乎有效。每当收到聊天时,都会成功填充LinkedList。问题是让ListView立即更新并显示聊天记录。如果我切换到我的应用程序中的新片段/选项卡,然后切换回我的聊天选项卡,然后填充列表;但是,每当我想看到任何新的聊天时,我都必须这样做。

对于我在本地输入的任何聊天(例如,在我的聊天功能中)也是如此。它仍然添加到LinkedList中,但ListView不会刷新。

我不想使用SwipeRefreshLayout,我宁愿列表更新自己。我在自定义ArrayAdapter中创建了一个方法

public void refreshList(){
    this.notifyDataSetChanged();
}

只要将新的消息对象添加到LinkedList,我就会调用它,但它不会刷新列表。

那么,我做错了什么?就像我说的,我更喜欢ListView更新本身,就像正确的聊天程序一样。

由于

修改

根据要求,这是我的自定义ArrayAdapter

public class CustomArrayAdapter extends ArrayAdapter {

    Context context;
    int resource;
    Object[] objects;

    public CustomArrayAdapter(Context context, int resource, Object[] objects) {
        super(context, resource, objects);
        this.context = context;
        this.resource = resource;
        this.objects = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        MessageHolder messageHolder = null;

        if(row == null){
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(resource, parent, false);
            messageHolder = new MessageHolder();
            messageHolder.chat_information = (TextView) row.findViewById(R.id.chat_information);
            messageHolder.chat_message = (TextView) row.findViewById(R.id.chat_message);

            row.setTag(messageHolder);
        } else {
            messageHolder = (MessageHolder) row.getTag();
        }

        Message item = (Message) objects[position];
        messageHolder.chat_information.setText(item.getSenderName() + Constants.NEWLINE + item.getSendTime());
        messageHolder.chat_message.setText(item.getMessageText());

        return row;
    }

    public void refreshList(){
        this.notifyDataSetChanged();
    }

    private class MessageHolder {
        TextView chat_information;
        TextView chat_message;
    }
}

编辑2:

我正在添加我的Chat.java片段。

public class Chat extends Fragment {

    private View rootView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.chat, container, false);
        return rootView;
    }

    @Override
    public void onViewCreated(View rootView, Bundle savedInstanceState) {
        super.onViewCreated(rootView, savedInstanceState);
        displayChats();
    }

    @Override
    public View getView() {
        Button sendChatButton = (Button) rootView.findViewById(R.id.text_send);
        sendChatButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Date rightNow = new Date();
                SimpleDateFormat timeSDF = new SimpleDateFormat(Constants.SIMPLE_TIME);
                SimpleDateFormat dateSDF = new SimpleDateFormat(Constants.SIMPLE_DATE);
                SharedPreferences myAppPreferences = getContext().getSharedPreferences(Constants.PREFS_NAME, getContext().MODE_PRIVATE);
                EditText chatEntryWindow = (EditText)rootView.findViewById(R.id.chat_text_compose);
                String message = chatEntryWindow.getText().toString();
                String username = myAppPreferences.getString("username", Constants.TABLET_ID);
                Message myMessage = new Message(username, message, 0, dateSDF.format(rightNow), timeSDF.format(rightNow));
                CustomArrayAdapter caa = new CustomArrayAdapter(getActivity(), R.layout.outgoing_line_of_chat, MainActivity.chatList);
                caa.add(myMessage);
                caa.notifyDataSetChanged();
                new SendChat(getActivity(), message, username).execute();
            }
        });
        return super.getView();
    }

    public void displayChats(){
        ListView list = (ListView) rootView.findViewById(R.id.chat_text_display);
        ArrayAdapter adapter = new CustomArrayAdapter(getActivity(), R.layout.outgoing_line_of_chat, MainActivity.chatList);
        list.setAdapter(adapter);
    }
}

3 个答案:

答案 0 :(得分:1)

在数组适配器中插入新数据后使用以下命令:

yourAdapterName.notifyDataSetChanged();

答案 1 :(得分:0)

您的CustomArrayAdapter未使用您的LinkedList。它使用Object[]。根据您的问题和评论,我假设您在创建CustomArrayAdapter时,在toArray()上致电LinkedList以获取Object[]

但是,此时Object[]LinkedList完全分离。假设,LinkedList一开始就有5个Message个对象。您拨打toArray(),然后获得包含这5个Object[5]个对象的Message。您稍后在add()上致电LinkedList,添加第6个MessageObject[5]仍然是Object[5],对第6 Message一无所知。 AdapterView将更新的唯一方法是完全替换CustomArrayAdapter

所以,摆脱Object[]ArrayAdapter在其一半构造函数中占用List。所以,替换:

public class CustomArrayAdapter extends ArrayAdapter {

    Context context;
    int resource;
    Object[] objects;

    public CustomArrayAdapter(Context context, int resource, Object[] objects) {
        super(context, resource, objects);
        this.context = context;
        this.resource = resource;
        this.objects = objects;
    }

使用:

public class CustomArrayAdapter extends ArrayAdapter<Message> {

    Context context;
    int resource;

    public CustomArrayAdapter(Context context, int resource, List<Message> messages) {
        super(context, resource, messages);
        this.context = context;
        this.resource = resource;
    }

然后,在getView()中,将Message item = (Message) objects[position];替换为Message item=getItem(position);

最后,当新的Message到达时,请致电add()上的CustomArrayAdapter,这将同时更新您的List<Message>并更新附加的AdapterView。< / p>

答案 2 :(得分:0)

像这样更改代码。这不会做太多改变,

public class CustomArrayAdapter extends ArrayAdapter {

    Context context;
    int resource;
    List objects ;
    Activity activity ;

    public CustomArrayAdapter(Context context, int resource, List objects) {
        super(context, resource, objects);
        this.context = context;
        this.resource = resource;
        //clone the arraylist.
        this.objects = new ArrayList(objects);
        activity = (Activity) context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        MessageHolder messageHolder = null;

        if (row == null) {
            LayoutInflater inflater = LayoutInflater.from(context);
            row = inflater.inflate(resource, parent, false);
            messageHolder = new MessageHolder();
            messageHolder.chat_information = (TextView) row.findViewById(R.id.chat_information);
            messageHolder.chat_message = (TextView) row.findViewById(R.id.chat_message);

            row.setTag(messageHolder);
        } else {
            messageHolder = (MessageHolder) row.getTag();
        }

        Message item = (Message) objects.get(position);
        messageHolder.chat_information.setText(item.getSenderName() + Constants.NEWLINE + item.getSendTime());
        messageHolder.chat_message.setText(item.getMessageText());

        return row;
    }

    public void setObjects(List newObjects)
    {
        if (objects != null)
        {
            objects.clear();
            objects.addAll(newObjects);
        }
    }


    public void refreshList() {
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        });

    }

    private class MessageHolder {
        TextView chat_information;
        TextView chat_message;
    }
}

还有一个聊天消息调用setObjects()方法和链接列表并调用refreshList()方法