Als Teil meiner Android-App integriere ich eine sehr einfache benutzerdefinierte Gruppenchat-Funktion. Dies ist nur eine Proof-of-Concept-Funktion. Mir ist bewusst, dass dies vorübergehend ist und dass meine Chats verschwinden, wenn ich meine App neu starte. Meine App verwendet Fragmente und einen ViewPager, um Tabs in meiner App zu erstellen.Warum aktualisiert mein benutzerdefinierter Android ArrayAdapter seine ListView nicht, wenn dem Array neue Daten hinzugefügt werden?
Was ich diese Funktion unterstützen, ist eine LinkedList, die Message-Objekte (Sendezeit, Name des Absenders, Nachricht) enthält. Wann immer ein Chat gesendet oder empfangen wird, wird er der LinkedList hinzugefügt. Zu Beginn meiner MainActivity.java erkläre ich die Liste
public static LinkedList<Message> chatList;
Im onCreate Methode initialisieren ich die Liste
chatList = new LinkedList<Message>();
ich einen Listener-Thread haben, der im Hintergrund läuft, die für eingehende horcht Mitteilungen. Ich habe die Chatliste in diesem Thread in seinem Konstruktor
MyListener myListener = new MyListener(MainActivity.this, chatList);
Thread listenerThread = new Thread(myListener);
listenerThread.start();
Jedes Mal, wenn der Hörer Thread eine Nachricht erhält, steckt sie in die LinkedList
chatList.add(new_message_object);
die Chats anzuzeigen, verwende ich eine Listview, die gesichert ist von einem benutzerdefinierten ArrayAdapter, in dem ich die getView() -Methode überschrieben habe. Der ArrayAdapter ruft das Array über die toArray() -Methode meiner LinkedList ab und zeigt die Chats auf dem Bildschirm an. Dieser Prozess fast funktioniert. Wann immer Chats empfangen werden, ist die LinkedList erfolgreich ausgefüllt. Das Problem besteht darin, dass das ListView die Chats sofort aktualisiert und anzeigt. Wenn ich in meiner App zu einem neuen Fragment/Tab wechsle, dann wechsle zurück zu meinem Chat Tab, dann wird die Liste aufgefüllt; aber ich muss das tun, wann immer ich neue Chats sehen möchte.
Dies gilt auch für alle Chats, die ich lokal (d. H. In meiner Chat-Funktion) eingib. Es wird weiterhin zur LinkedList hinzugefügt, aber die ListView wird nicht aktualisiert.
Ich möchte nicht ein SwipeRefreshLayout verwenden, ich würde lieber die Liste selbst aktualisieren. Ich habe eine Methode in der benutzerdefinierten ArrayAdapter
public void refreshList(){
this.notifyDataSetChanged();
}
ich das nennen, wenn eine neue Nachricht Objekt in die LinkedList hinzugefügt wird, aber es wird die Liste nicht aktualisieren.
Also, was mache ich falsch? Wie ich schon sagte, würde ich das ListView-Update lieber selbst vornehmen als ein richtiges Chat-Programm.
Dank
EDIT:
Wie gewünscht, hier ist meine Gewohnheit 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;
}
}
EDIT 2: mein Chat.java Fragment
Ich füge.
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);
}
}
„Die ArrayAdapter liest die toArray() Methode meiner LinkedList und zeigt die Chats auf dem Bildschirm "- das macht für mich keinen Sinn. Ich schlage vor, dass Sie Ihre Frage editieren und Ihre 'getView()' Methode, oder vielleicht den ganzen 'ArrayAdapter' posten. Im Allgemeinen rufen Sie 'add()'/'insert()'/'remove()' auf dem 'ArrayAdapter' auf, um den Inhalt zu aktualisieren und die angehängte' AdapterView' zu aktualisieren, aber 'notifyDataSetChanged()' (nach der Manipulation der 'List' direkt) sollte den gleichen Effekt haben. – CommonsWare
@CommonsWare All dies bedeutet, dass der ArrayAdapter ein Array benötigt und die LinkedList.toArray() - Methode die LinkedList in ein Array konvertiert, das vom ArrayAdapter verwendet werden kann. – Brian
Ich vermute, dass Sie größere Probleme haben. Ich schlage immer noch vor, dass Sie Ihre Frage bearbeiten und Ihre Unterklasse 'ArrayAdapter' veröffentlichen. – CommonsWare