This is my first question in Stack Overflow, I have been building a simple chat application on Android which loads the chat History from a online database and it will be displayed in a list view using a customised message adapter.
Here is the current state of the program:
However, the layout of the list items is not correct after the 6th chat message down the array list, and all the following chat messages are repeating the layout of the first 6 messages.
Here is the code for my adapter:
public class messageAdapter extends ArrayAdapter<chatMessage> {
private Activity activity;
private List<chatMessage> messages;
public messageAdapter(Activity context, int resource, List<chatMessage> objects) {
super(context, resource, objects);
this.activity = context;
this.messages = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
int layoutResource = 0; // determined by view type
chatMessage chatMessage = getItem(position);
int viewType = getItemViewType(position);
if (chatMessage.isMine()) {
layoutResource = R.layout.chat_bubble_right;
} else {
layoutResource = R.layout.chat_bubble_left;
}
if (convertView != null) {
holder = (ViewHolder) convertView.getTag();
} else {
convertView = inflater.inflate(layoutResource, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
Log.d("ViewID", "generated");
}
//set message content
holder.message.setText(chatMessage.getContent());
return convertView;
}
@Override
public int getViewTypeCount() {
// return the total number of view types. this value should never change
// at runtime
return 2;
}
@Override
public int getItemViewType(int position) {
// return a value between 0 and (getViewTypeCount - 1)
return position % 2;
}
private class ViewHolder {
private TextView message;
public ViewHolder(View v) {
message = (TextView) v.findViewById(R.id.txt_msg);
}
}
And this is the method that I load chat messages into the Array List:
private class getChatHistory extends AsyncTask<DBConnection,Long,JSONArray> {
@Override
protected JSONArray doInBackground(DBConnection... params) {
return params[0].getChatHistory(userID);
}
@Override
protected void onPostExecute(JSONArray jsonArray) {
chatData = jsonArray;
if (chatData != null)
{
for (int i = 0; i < chatData.length(); i++)
{
JSONObject currentItem = null;
try
{
currentItem = chatData.getJSONObject(i);
int msgID = currentItem.getInt("MessageID");
String currentText = currentItem.getString("MessageContent");
int senderID = currentItem.getInt("SenderID");
int receiverID = currentItem.getInt("ReceiverID");
chatMessage currentMessage = new chatMessage(currentText, senderID, userID);
Log.d("Is Mine", Boolean.toString(currentMessage.isMine()));
messageHistory.add(currentMessage);
DBAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
}
And here is the JSONArray I obtained from the PHP file that I ran:
[{"MessageID":"1","SenderID":"1","ReceiverID":"8","Duration":"2.4","MessageContent":"agnblean liajiaj vliwv fla","MessageLength":"26","Status":"received","Date":"2016-04-04 14:00:00"},
{"MessageID":"2","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwfcofawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:00"},
{"MessageID":"3","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwfjurawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:05"},
{"MessageID":"4","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwalwrawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:10"},
{"MessageID":"5","SenderID":"1","ReceiverID":"8","Duration":"3.1","MessageContent":"akwuehrgeubwalwrawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:01:10"},
{"MessageID":"8","SenderID":"1","ReceiverID":"8","Duration":"4.6","MessageContent":"vsjkgkgredjegwhkaga","MessageLength":"23","Status":"received","Date":"2016-04-05 05:00:00"},
{"MessageID":"9","SenderID":"8","ReceiverID":"1","Duration":"5.2","MessageContent":"agrlanwligna","MessageLength":"21","Status":"received","Date":"2016-04-06 00:00:00"},
{"MessageID":"10","SenderID":"8","ReceiverID":"1","Duration":"7.2","MessageContent":"akewgaughurawaarg","MessageLength":"12","Status":"received","Date":"2016-04-12 00:00:00"},
{"MessageID":"11","SenderID":"1","ReceiverID":"8","Duration":"7.2","MessageContent":"wgkakjrgnjange","MessageLength":"41","Status":"received","Date":"2016-04-15 00:00:00"},
{"MessageID":"12","SenderID":"1","ReceiverID":"8","Duration":"4.67","MessageContent":"yikes","MessageLength":"5","Status":"received","Date":"2016-04-21 00:00:00"},
{"MessageID":"13","SenderID":"8","ReceiverID":"1","Duration":"8.2","MessageContent":"iobanoine","MessageLength":"4","Status":"received","Date":"2016-04-30 00:00:00"}]
So I thought that this would produce the correct layout for the chat history, which the active user being user ID = 1, and all the message with sender ID = 1 should be on the right hand side of the list view, but instead I got this:
This is the screenshot of the 5-8th element in the list view, but the 7th element is on the right hand side instead of being on the left hand side, and the later element keep on repeating the previous 6 element's pattern. I have checked the log for the convert view and it only shows up 6 times, is that in anyway related to this error? And how do I solve this problem of the adapter not locating the list item resource correctly?
EDIT : I have changed the override of the getItemViewType() into this
@Override
public int getItemViewType(int position) {
chatMessage chatMessage = getItem(position);
if (chatMessage.isMine()) {
return 0;
} else {
return 1;
}
}
And I have also removed the override method for getViewTypeCount, and changed the condition a bit in the getView() method:
int viewType = getItemViewType(position);
if (viewType==0) {
layoutResource = R.layout.chat_bubble_right;
} else {
layoutResource = R.layout.chat_bubble_left;
}
Now the chat message list is in normal order up to the 8th element, and then the order become incorrect again.
EDIT 2
I have trace the log for the number of list item generated (i.e. new items) and this is the result I get after scrolling down to the bottom of the list view:
04-06 19:23:54.894 11202-11202/com.example.user.normalinterface D/ViewID: generated
04-06 19:23:54.907 11202-11202/com.example.user.normalinterface D/ViewID: generated
04-06 19:23:54.912 11202-11202/com.example.user.normalinterface D/ViewID: generated
04-06 19:23:54.914 11202-11202/com.example.user.normalinterface D/ViewID: generated
04-06 19:23:56.850 11202-11202/com.example.user.normalinterface D/ViewID: generated
is this in anyway related to my problem? It seeems that all the subsequent record in the list view are repeating the pattern from the first 5 item in the list.
答案 0 :(得分:0)
I think it come from the getViewTypeCount()
method. Here you say that you have 2 different types of layout. And with the method getItemViewType()
you say that the different types are one out of 2 messages. But you don't event use the type in the getView method.
Apparently you don't need those 2 types, so I would recommend that you just remove the 2 methods :
getViewTypeCount()
and
getItemViewType()
I don't think you need them in you case.
EDIT :
You actually need those method, but you overrided getItemViewType
badly.
@Override
public int getItemViewType(int position) {
chatMessage chatMessage = getItem(position);
if (chatMessage.isMine()) {
return 0;
} else {
return 1;
}
}
答案 1 :(得分:0)
根据我的经验,但可能与此无关,您需要在适配器中调用notifyDataSetChanged(),因此在适配器中设置一个名为refreshData的方法,如下所示:
public void refreshData(ArrayList<yourList> data) {
mValues.clear();
mValues.addAll(data);
notifyDataSetChanged();
}
并从您的活动中致电:
mAdapter.refreshData(newData)
将新数据作为参数。
另外,请确保正确引用适配器类,因此请尝试添加到类的开头:
private final DBAdapter mAdapter;
然后在getChaHistory中添加:
mAdapter = DBAdapter
这个想法是你有一个正确引用适配器的句柄。请注意对上一个答案的更改,现在调用mAdapter.refreshData(newData)而不是DBAdapter.refreshData(newdata)。真的,我觉得你应该把适配器传递到课堂上,这就是我的工作,但是你可以尝试这种方式,看看你是如何进行的?
答案 2 :(得分:0)
这将正常工作,但不会那么快。如果&#34; isMine()&#34;它决定实例化哪个布局取决于值。如果&#34; isMine()为true,则实例化包含右对齐TextView的布局。否则,实例化其他布局(TextView左对齐)。
@Override
public View getView(int position, View convertView, ViewGroup parent){
if(messages.get(position).isMine()){
item = ((Activity)context).getLayoutInflater().inflate(R.layout.chat_bubble_right,null);
}
else{
item = ((Activity)context).getLayoutInflater().inflate(R.layout.chat_bubble_left,null);
}
// set the text in the view.
((TextView) item.findViewById(R.id.chat_text)).setText(data.get(position).getMessage());
return item;
}
chat_text id引用实例化布局中的TextView。 (两个布局都包含一个带有id chat_text的TextView)
我使用此Google IO事件作为资源:
https://www.youtube.com/watch?v=wDBM6wVEO70