37 * Optimization: ListView is smart enough to try re-using the same view for an item |
37 * Optimization: ListView is smart enough to try re-using the same view for an item |
38 * with the same ID, but it still calls getView for those items when the list changes. |
38 * with the same ID, but it still calls getView for those items when the list changes. |
39 * Since lines with a given ID never change in our chatlog, we can avoid the effort |
39 * Since lines with a given ID never change in our chatlog, we can avoid the effort |
40 * of TextView.setText in many cases by checking if the view is already set up for the |
40 * of TextView.setText in many cases by checking if the view is already set up for the |
41 * line with the right ID - but to do that, the view needs to remember the ID it's |
41 * line with the right ID - but to do that, the view needs to remember the ID it's |
42 * holding the text for. That's what the LoglineView does. |
42 * holding the text for. That's what the LoglineView does. |
43 */ |
43 */ |
44 class LoglineView extends TextView { |
44 class LoglineView extends TextView { |
45 long chatlogId = -1; |
45 long chatlogId = -1; |
46 |
46 |
47 public LoglineView(Context context) { |
47 public LoglineView(Context context) { |
48 super(context); |
48 super(context); |
49 } |
49 } |
50 } |
50 } |
51 |
51 |
52 /** |
52 /** |
53 * For performance reasons, the chatlog is implemented as ListView instead of a |
53 * For performance reasons, the chatlog is implemented as ListView instead of a |
54 * single TextView (although I later learned that TextView might also have |
54 * single TextView (although I later learned that TextView might also have |
55 * facilities for efficient appending with limited backlog... oh well, this |
55 * facilities for efficient appending with limited backlog... oh well, this |
56 * works). Every chat line is a line in the ListView, and this adapter prepares |
56 * works). Every chat line is a line in the ListView, and this adapter prepares |
57 * the textviews from a messagelog in an efficient way. |
57 * the textviews from a messagelog in an efficient way. |
58 */ |
58 */ |
59 public class ChatlogAdapter extends BaseAdapter implements MessageLog.Listener { |
59 public class ChatlogAdapter extends BaseAdapter implements MessageLog.Listener { |
60 long idOffset = 0; |
60 long idOffset = 0; |
61 private List<CharSequence> log = new ArrayList<CharSequence>(); |
61 private List<CharSequence> log = new ArrayList<CharSequence>(); |
62 private Context context; |
62 private Context context; |
63 |
|
64 public ChatlogAdapter(Context context) { |
|
65 this.context = context; |
|
66 } |
|
67 |
|
68 public int getCount() { |
|
69 return log.size(); |
|
70 } |
|
71 |
63 |
72 public Object getItem(int position) { |
64 public ChatlogAdapter(Context context) { |
73 return log.get(position); |
65 this.context = context; |
74 } |
66 } |
75 |
67 |
76 public long getItemId(int position) { |
68 public int getCount() { |
77 return position+idOffset; |
69 return log.size(); |
78 } |
70 } |
79 |
71 |
80 public boolean hasStableIds() { |
72 public Object getItem(int position) { |
81 return true; |
73 return log.get(position); |
82 } |
74 } |
83 |
75 |
84 public void clear() { |
76 public long getItemId(int position) { |
85 idOffset += log.size(); |
77 return position+idOffset; |
86 log.clear(); |
78 } |
87 notifyDataSetChanged(); |
79 |
88 } |
80 public boolean hasStableIds() { |
89 |
81 return true; |
90 public void lineAdded(CharSequence text) { |
82 } |
91 log.add(text); |
83 |
92 notifyDataSetChanged(); |
84 public void clear() { |
93 } |
85 idOffset += log.size(); |
94 |
86 log.clear(); |
95 public void lineRemoved() { |
87 notifyDataSetChanged(); |
96 log.remove(0); |
88 } |
97 idOffset += 1; |
89 |
98 notifyDataSetChanged(); |
90 public void lineAdded(CharSequence text) { |
99 } |
91 log.add(text); |
100 |
92 notifyDataSetChanged(); |
101 public void setLog(Collection<CharSequence> log) { |
93 } |
102 idOffset += log.size(); |
94 |
103 this.log = new ArrayList<CharSequence>(log); |
95 public void lineRemoved() { |
104 notifyDataSetChanged(); |
96 log.remove(0); |
105 } |
97 idOffset += 1; |
106 |
98 notifyDataSetChanged(); |
107 public View getView(int position, View convertView, ViewGroup parent) { |
99 } |
108 LoglineView v = (LoglineView)convertView; |
100 |
109 if (v == null) { |
101 public void setLog(Collection<CharSequence> log) { |
110 v = new LoglineView(context); |
102 idOffset += log.size(); |
111 v.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); |
103 this.log = new ArrayList<CharSequence>(log); |
112 v.setMovementMethod(LinkMovementMethod.getInstance()); |
104 notifyDataSetChanged(); |
113 } |
105 } |
114 long id = getItemId(position); |
106 |
115 if(id != v.chatlogId) { |
107 public View getView(int position, View convertView, ViewGroup parent) { |
116 v.setText(log.get(position)); |
108 LoglineView v = (LoglineView)convertView; |
117 v.chatlogId = id; |
109 if (v == null) { |
118 } |
110 v = new LoglineView(context); |
119 return v; |
111 v.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); |
120 } |
112 v.setMovementMethod(LinkMovementMethod.getInstance()); |
|
113 } |
|
114 long id = getItemId(position); |
|
115 if(id != v.chatlogId) { |
|
116 v.setText(log.get(position)); |
|
117 v.chatlogId = id; |
|
118 } |
|
119 return v; |
|
120 } |
121 } |
121 } |