如何通过在自定义列表视图适配器本身中收集消息来显示聊天?
How to show chats by collecting messages in the custom list view adapter itself?
所以,我想做的是使用自定义列表视图适配器在 activity 中显示聊天记录。
I have a HTTPTask Activity handling the server side interaction and responding with a JSONObject. So, every server side interaction is working fine.
What I want to do is keep updating the messages in the chat by keep checking with the API at a set interval to populate messages in the chat if there are any.
我的问题是,这个填充过程应该在适配器中完成还是在 activity 中完成以及如何完成?
还有,viewHolder 在适配器中有什么帮助?
这是我的Activity
public class ChatActivity extends Activity {
TextView toUsername;
EditText replyText;
JSONObject resultObject;
StringBuilder reply,from_user_id,c_id;
MessageListViewAdapter myAdapter;
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
toUsername = (TextView) findViewById(R.id.toUsername);
replyText = (EditText) findViewById(R.id.replyText);
reply = new StringBuilder("");
listView = (ListView) findViewById(R.id.messages);
}
@Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
}
public void sendTextMsg(View view){
reply.delete(0,reply.length());
reply.append(replyText.getText().toString());
if(!reply.toString().equals("")){
Log.d("Values: ","c_id: " + c_id.toString() + " FromUserId: " + from_user_id.toString() + "ReplyText: " + reply.toString());
try{
resultObject = new HttpTask(getBaseContext()).doInBackground("replyInChat",c_id.toString(),replyText.getText().toString(),from_user_id.toString());
if(resultObject.get("status").toString().equals("true")) {
Toast.makeText(getBaseContext(), "Sent.", Toast.LENGTH_SHORT).show();
replyText.setText("");
}
else {
Toast.makeText(getBaseContext(), "Try Again.", Toast.LENGTH_SHORT).show();
}
}
catch(JSONException e){ }
}
}
}
我的适配器似乎不工作。
public class MessageListViewAdapter extends BaseAdapter implements ListAdapter{
private ArrayList<String> list = new ArrayList<String>();
private Context context;
private StringBuilder conversation_id, user_id;
private static int cr_id;
private JSONArray messages;
private JSONObject resultObject;
private ViewHolder viewHolder;
private View rowView;
public MessageListViewAdapter(Context context, String conversation_id, String user_id) {
this.context = context;
this.conversation_id = new StringBuilder(conversation_id.toString());
this.user_id = new StringBuilder(user_id.toString());
cr_id=0;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int pos) {
return list.get(pos);
}
@Override
public long getItemId(int pos) {
//return list.get(pos).getId();
//just return 0 if your list items do not have an Id variable.
return 0;
}
@Override
public boolean isEnabled(int position){
return false;
}
static class ViewHolder{
public TextView ItemText;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
}
}
}
catch(JSONException e){ }
//Handle TextView and display string from your list
//final TextView listItemText = (TextView)rowView.findViewById(R.id.list_item_text);
//listItemText.setText(list.get(position));
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
}
如果一切正常,而您在适配器中显示最新的聊天消息时遇到问题,只需像这样更改您的代码:
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
this.notifyDataSetChanged(); // add this line
}
}
}
catch(JSONException e){ }
在下方评论以获取更多信息
就我个人而言,我会在适配器之外进行网络调用。使用当前的代码,如果用户要上下滚动列表,网络调用将调用多次,这是我确定你不想要的。
可能更好的解决方案是在 activity 中有一个方法来执行调用,然后设置一个计时器,每 2 - 3 分钟调用一次该方法以节省网络调用,您还可以为用户添加一个刷新按钮,让他们可以选择自己刷新数据,这只会调用相同的方法。
View Holder 设计模式可以帮助加快列表视图的速度并保持其流畅,这样想,当页面首次加载时,将多次调用 getView 来填充列表视图。在 getView 方法中,您实例化 UI 小部件,即 textview = (TextView)findviewbyid。现在视图持有者所做的是保留对这些 ui 元素的引用,这意味着您不必继续调用 findViewById.
这里有一篇文章对其进行了更好的解释,并提供了一些示例。
http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
假设您在 activity 中编写网络代码。当您收到回复时,您只需将消息添加到列表中,然后 notifyDataSetChanged();
So, Finally I got it working with some experimentation. Many thanks to Manikanta and Andy Joyce for their valuable answers. If it weren't for them i wouldn't have gone any further from where I was stuck.
这是我在自定义适配器中所做的更改。
public void add(ArrayList<String> list){
this.list.clear();
this.list.addAll(list);
Log.d("List: ",this.list.toString());
this.notifyDataSetChanged();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
这是我添加到我的 activity
@Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
//list.add(c_id.toString());
//list.add(from_user_id.toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
callAsynchronousTask();
//myAdapter.add(list);
}
@Override
public void onPause(){
super.onPause();
timer.cancel();
}
public void callAsynchronousTask() {
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
//list.clear();
try{
resultChatObject = new HttpTask(getBaseContext()).doInBackground("sendMessages",c_id.toString(),String.valueOf(cr_id));
if(resultChatObject.get("status").toString().equals("true")) {
//list.clear();
messages = resultChatObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for (int i = 0; i <= messages.length(); i++) {
list.add(messages.getJSONObject(i).get("reply_text").toString());
if (cr_id < Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString()))
cr_id = Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString());
}
}
}
catch (JSONException e) { }
myAdapter.add(list);
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 10000 ms
}
大家干杯!!!
所以,我想做的是使用自定义列表视图适配器在 activity 中显示聊天记录。
I have a HTTPTask Activity handling the server side interaction and responding with a JSONObject. So, every server side interaction is working fine.
What I want to do is keep updating the messages in the chat by keep checking with the API at a set interval to populate messages in the chat if there are any.
我的问题是,这个填充过程应该在适配器中完成还是在 activity 中完成以及如何完成?
还有,viewHolder 在适配器中有什么帮助?
这是我的Activity
public class ChatActivity extends Activity {
TextView toUsername;
EditText replyText;
JSONObject resultObject;
StringBuilder reply,from_user_id,c_id;
MessageListViewAdapter myAdapter;
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
toUsername = (TextView) findViewById(R.id.toUsername);
replyText = (EditText) findViewById(R.id.replyText);
reply = new StringBuilder("");
listView = (ListView) findViewById(R.id.messages);
}
@Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
}
public void sendTextMsg(View view){
reply.delete(0,reply.length());
reply.append(replyText.getText().toString());
if(!reply.toString().equals("")){
Log.d("Values: ","c_id: " + c_id.toString() + " FromUserId: " + from_user_id.toString() + "ReplyText: " + reply.toString());
try{
resultObject = new HttpTask(getBaseContext()).doInBackground("replyInChat",c_id.toString(),replyText.getText().toString(),from_user_id.toString());
if(resultObject.get("status").toString().equals("true")) {
Toast.makeText(getBaseContext(), "Sent.", Toast.LENGTH_SHORT).show();
replyText.setText("");
}
else {
Toast.makeText(getBaseContext(), "Try Again.", Toast.LENGTH_SHORT).show();
}
}
catch(JSONException e){ }
}
}
}
我的适配器似乎不工作。
public class MessageListViewAdapter extends BaseAdapter implements ListAdapter{
private ArrayList<String> list = new ArrayList<String>();
private Context context;
private StringBuilder conversation_id, user_id;
private static int cr_id;
private JSONArray messages;
private JSONObject resultObject;
private ViewHolder viewHolder;
private View rowView;
public MessageListViewAdapter(Context context, String conversation_id, String user_id) {
this.context = context;
this.conversation_id = new StringBuilder(conversation_id.toString());
this.user_id = new StringBuilder(user_id.toString());
cr_id=0;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int pos) {
return list.get(pos);
}
@Override
public long getItemId(int pos) {
//return list.get(pos).getId();
//just return 0 if your list items do not have an Id variable.
return 0;
}
@Override
public boolean isEnabled(int position){
return false;
}
static class ViewHolder{
public TextView ItemText;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
}
}
}
catch(JSONException e){ }
//Handle TextView and display string from your list
//final TextView listItemText = (TextView)rowView.findViewById(R.id.list_item_text);
//listItemText.setText(list.get(position));
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
}
如果一切正常,而您在适配器中显示最新的聊天消息时遇到问题,只需像这样更改您的代码:
try{
Log.d("cr_id: ",String.valueOf(cr_id).toString());
//This is where the population should've taken place but didn't.
resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
if(resultObject.get("status").toString().equals("true")) {
messages = resultObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for(int i=0;i<=messages.length();i++){
list.add(messages.getJSONObject(i).get("reply_text").toString());
this.notifyDataSetChanged(); // add this line
}
}
}
catch(JSONException e){ }
在下方评论以获取更多信息
就我个人而言,我会在适配器之外进行网络调用。使用当前的代码,如果用户要上下滚动列表,网络调用将调用多次,这是我确定你不想要的。
可能更好的解决方案是在 activity 中有一个方法来执行调用,然后设置一个计时器,每 2 - 3 分钟调用一次该方法以节省网络调用,您还可以为用户添加一个刷新按钮,让他们可以选择自己刷新数据,这只会调用相同的方法。
View Holder 设计模式可以帮助加快列表视图的速度并保持其流畅,这样想,当页面首次加载时,将多次调用 getView 来填充列表视图。在 getView 方法中,您实例化 UI 小部件,即 textview = (TextView)findviewbyid。现在视图持有者所做的是保留对这些 ui 元素的引用,这意味着您不必继续调用 findViewById.
这里有一篇文章对其进行了更好的解释,并提供了一些示例。
http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
假设您在 activity 中编写网络代码。当您收到回复时,您只需将消息添加到列表中,然后 notifyDataSetChanged();
So, Finally I got it working with some experimentation. Many thanks to Manikanta and Andy Joyce for their valuable answers. If it weren't for them i wouldn't have gone any further from where I was stuck.
这是我在自定义适配器中所做的更改。
public void add(ArrayList<String> list){
this.list.clear();
this.list.addAll(list);
Log.d("List: ",this.list.toString());
this.notifyDataSetChanged();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.message_list_layout, null);
//configure view holder
viewHolder = new ViewHolder();
viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
rowView.setTag(viewHolder);
}
else {
//fill data
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.ItemText.setText(list.get(position));
return rowView;
}
这是我添加到我的 activity
@Override
public void onResume(){
super.onResume();
Bundle bundle = getIntent().getExtras();
if(bundle != null){
toUsername.setText("" + bundle.get("ToUsername").toString());
c_id = new StringBuilder(bundle.get("c_id").toString());
from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
//list.add(c_id.toString());
//list.add(from_user_id.toString());
}
myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
listView.setAdapter(myAdapter);
callAsynchronousTask();
//myAdapter.add(list);
}
@Override
public void onPause(){
super.onPause();
timer.cancel();
}
public void callAsynchronousTask() {
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
//list.clear();
try{
resultChatObject = new HttpTask(getBaseContext()).doInBackground("sendMessages",c_id.toString(),String.valueOf(cr_id));
if(resultChatObject.get("status").toString().equals("true")) {
//list.clear();
messages = resultChatObject.getJSONArray("messages");
Log.d("Messages: ",messages.toString());
for (int i = 0; i <= messages.length(); i++) {
list.add(messages.getJSONObject(i).get("reply_text").toString());
if (cr_id < Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString()))
cr_id = Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString());
}
}
}
catch (JSONException e) { }
myAdapter.add(list);
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 10000 ms
}
大家干杯!!!