@@ -40,27 +40,28 @@ So say we have these chat messages in our Firebase database:
40
40
41
41
We can represent a chat message with this Java class:
42
42
43
- public class ChatMessage {
44
- String message;
45
- String name;
43
+ ``` java
44
+ public class ChatMessage {
45
+ String message;
46
+ String name;
46
47
47
- public ChatMessage() {
48
- }
49
-
50
- public ChatMessage(String name, String message) {
51
- this.message = message;
52
- this.name = name;
53
- }
48
+ public ChatMessage () {
49
+ }
54
50
55
- public String getMessage() {
56
- return message;
57
- }
51
+ public ChatMessage (String name , String message ) {
52
+ this . message = message;
53
+ this . name = name;
54
+ }
58
55
59
- public String getName() {
60
- return name;
61
- }
56
+ public String getMessage () {
57
+ return message;
62
58
}
63
59
60
+ public String getName () {
61
+ return name;
62
+ }
63
+ }
64
+ ```
64
65
A few things to note here:
65
66
66
67
* the field have the exact same name as the properties in Firebase. This allows Firebase to automatically map the properties to these fields.
@@ -70,28 +71,30 @@ A few things to note here:
70
71
71
72
A little-known feature of Firebase for Android is that you can pass an instance of this ` ChatMessage ` class to ` setValue() ` :
72
73
73
- Firebase ref = new Firebase("https://nanochat.firebaseio.com/");
74
- ChatMessage msg = new ChatMessage("puf", "Hello FirebaseUI world!");
75
- ref.push().setValue(msg);
76
-
74
+ ``` java
75
+ Firebase ref = new Firebase (" https://nanochat.firebaseio.com/" );
76
+ ChatMessage msg = new ChatMessage (" puf" , " Hello FirebaseUI world!" );
77
+ ref. push(). setValue(msg);
78
+ ```
77
79
The Firebase Android client will read the values from the ` msg ` and write them into the properties of the new child in the database.
78
80
79
81
Conversely, we can read a ` ChatMessage ` straight from a ` DataSnapshot ` in our event handlers:
80
82
81
- ref.limitToLast(5).addValueEventListener(new ValueEventListener() {
82
- @Override
83
- public void onDataChange(DataSnapshot snapshot) {
84
- for (DataSnapshot msgSnapshot: snapshot.getChildren()) {
85
- ChatMessage msg = msgSnapshot.getValue(ChatMessage.class);
86
- Log.i("Chat", chat.getName()+": "+chat.getMessage());
87
- }
88
- }
89
- @Override
90
- public void onCancelled(FirebaseError firebaseError) {
91
- Log.e("Chat", "The read failed: " + firebaseError.getMessage());
83
+ ``` java
84
+ ref. limitToLast(5 ). addValueEventListener(new ValueEventListener () {
85
+ @Override
86
+ public void onDataChange (DataSnapshot snapshot ) {
87
+ for (DataSnapshot msgSnapshot: snapshot. getChildren()) {
88
+ ChatMessage msg = msgSnapshot. getValue(ChatMessage . class);
89
+ Log . i(" Chat" , chat. getName()+ " : " + chat. getMessage());
92
90
}
93
- });
94
-
91
+ }
92
+ @Override
93
+ public void onCancelled (FirebaseError firebaseError ) {
94
+ Log . e(" Chat" , " The read failed: " + firebaseError. getMessage());
95
+ }
96
+ });
97
+ ```
95
98
In the above snippet we have a query for the last 5 chat messages. Whenever those change (i.e. when an new message is added)
96
99
we get the ` ChatMessage ` objects from the ` DataSnapshot ` with ` getValue(ChatMessage.class) ` . The Firebase Android client will
97
100
then read the properties that it got from the database and map them to the fields of our ` ChatMessage ` class.
@@ -105,53 +108,59 @@ But when we build our app using FirebaseUI, we often won't need to register our
105
108
106
109
We'll assume you've already added a ` ListView ` to your layout and have looked it up in the ` onCreate ` method of your activity:
107
110
108
- @Override
109
- protected void onCreate(Bundle savedInstanceState) {
110
- super.onCreate(savedInstanceState);
111
- setContentView(R.layout.activity_main);
111
+ ``` java
112
+ @Override
113
+ protected void onCreate(Bundle savedInstanceState) {
114
+ super . onCreate(savedInstanceState);
115
+ setContentView(R . layout. activity_main);
112
116
113
- ListView messagesView = (ListView) findViewById(R.id.messages_list);
114
- }
117
+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
118
+ }
119
+ ```
115
120
116
121
#### Set up connection to Firebase
117
122
118
123
First we'll tell Firebase that we intend to use it in this activity and set up a reference to the database of chat message.
119
124
120
- @Override
121
- protected void onCreate(Bundle savedInstanceState) {
122
- super.onCreate(savedInstanceState);
123
- setContentView(R.layout.activity_main);
125
+ ``` java
126
+ @Override
127
+ protected void onCreate(Bundle savedInstanceState) {
128
+ super . onCreate(savedInstanceState);
129
+ setContentView(R . layout. activity_main);
124
130
125
- ListView messagesView = (ListView) findViewById(R.id.messages_list);
131
+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
126
132
127
- Firebase.setAndroidContext(this);
128
- Firebase ref = new Firebase("https://nanochat.firebaseio.com");
129
- }
133
+ Firebase . setAndroidContext(this );
134
+ Firebase ref = new Firebase (" https://nanochat.firebaseio.com" );
135
+ }
136
+ ```
130
137
131
138
#### Create custom FirebaseListAdapter subclass
132
139
133
140
Next, we need to create a subclass of the ` FirebaseListAdapter ` with the correct parameters and implement its ` populateView ` method:
134
141
135
- @Override
136
- protected void onCreate(Bundle savedInstanceState) {
137
- super.onCreate(savedInstanceState);
138
- setContentView(R.layout.activity_main);
142
+ ``` java
143
+ @Override
144
+ protected void onCreate(Bundle savedInstanceState) {
145
+ super . onCreate(savedInstanceState);
146
+ setContentView(R . layout. activity_main);
139
147
140
- ListView messagesView = (ListView) findViewById(R.id.messages_list);
148
+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
141
149
142
- Firebase.setAndroidContext(this);
143
- Firebase ref = new Firebase("https://nanochat.firebaseio.com");
150
+ Firebase . setAndroidContext(this );
151
+ Firebase ref = new Firebase (" https://nanochat.firebaseio.com" );
144
152
145
- mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
146
- @Override
147
- protected void populateView(View view, ChatMessage chatMessage) {
148
- ((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
149
- ((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());
153
+ mAdapter = new FirebaseListAdapter<ChatMessage > (this , ChatMessage . class, android. R . layout. two_line_list_item, ref) {
154
+ @Override
155
+ protected void populateView (View view , ChatMessage chatMessage ) {
156
+ ((TextView )view. findViewById(android. R . id. text1)). setText(chatMessage. getName());
157
+ ((TextView )view. findViewById(android. R . id. text2)). setText(chatMessage. getMessage());
150
158
151
- }
152
- };
153
- messagesView.setListAdapter(mAdapter);
154
- }
159
+ }
160
+ };
161
+ messagesView. setListAdapter(mAdapter);
162
+ }
163
+ ```
155
164
156
165
In this last snippet we create a subclass of ` FirebaseListAdapter ` .
157
166
We tell is that it is of type ` <ChatMessage> ` , so that it is a type-safe collection. We also tell it to use
@@ -171,51 +180,55 @@ correct `TextView` controls from the `view`. The code is a bit verbose, but hey.
171
180
Finally, we need to clean up after ourselves. When the activity is destroyed, we need to call ` release() `
172
181
on the ` ListAdapter ` so that it can stop listening for changes in the Firebase database.
173
182
174
- @Override
175
- protected void onDestroy() {
176
- super.onDestroy();
177
- mAdapter.cleanup();
178
- }
183
+ ``` java
184
+ @Override
185
+ protected void onDestroy() {
186
+ super . onDestroy();
187
+ mAdapter. cleanup();
188
+ }
189
+ ```
179
190
180
191
#### Sending chat messages
181
192
182
193
Remember when we showed how to use the ` ChatMessage ` class in ` setValue() ` .
183
194
We can now use that in our activity to allow sending a message:
184
195
185
- @Override
186
- protected void onCreate(Bundle savedInstanceState) {
187
- super.onCreate(savedInstanceState);
188
- setContentView(R.layout.activity_main);
189
-
190
- ListView messagesView = (ListView) findViewById(R.id.messages_list);
191
-
192
- Firebase.setAndroidContext(this);
193
- Firebase ref = new Firebase("https://nanochat.firebaseio.com");
194
-
195
- mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
196
- @Override
197
- protected void populateView(View view, ChatMessage chatMessage) {
198
- ((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
199
- ((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());
200
- }
201
- };
202
- setListAdapter(mAdapter);
203
-
204
- final EditText mMessage = (EditText) findViewById(R.id.message_text);
205
- findViewById(R.id.send_button).setOnClickListener(new View.OnClickListener() {
206
- @Override
207
- public void onClick(View v) {
208
- mRef.push().setValue(new ChatMessage("puf", mMessage.getText().toString()));
209
- mMessage.setText("");
210
- }
211
- });
212
- }
196
+ ``` java
197
+ @Override
198
+ protected void onCreate(Bundle savedInstanceState) {
199
+ super . onCreate(savedInstanceState);
200
+ setContentView(R . layout. activity_main);
213
201
214
- @Override
215
- protected void onDestroy() {
216
- super.onDestroy();
217
- mAdapter.cleanup();
218
- }
202
+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
203
+
204
+ Firebase . setAndroidContext(this );
205
+ Firebase ref = new Firebase (" https://nanochat.firebaseio.com" );
206
+
207
+ mAdapter = new FirebaseListAdapter<ChatMessage > (this , ChatMessage . class, android. R . layout. two_line_list_item, ref) {
208
+ @Override
209
+ protected void populateView (View view , ChatMessage chatMessage ) {
210
+ ((TextView )view. findViewById(android. R . id. text1)). setText(chatMessage. getName());
211
+ ((TextView )view. findViewById(android. R . id. text2)). setText(chatMessage. getMessage());
212
+ }
213
+ };
214
+ setListAdapter(mAdapter);
215
+
216
+ final EditText mMessage = (EditText ) findViewById(R . id. message_text);
217
+ findViewById(R . id. send_button). setOnClickListener(new View .OnClickListener () {
218
+ @Override
219
+ public void onClick (View v ) {
220
+ mRef. push(). setValue(new ChatMessage (" puf" , mMessage. getText(). toString()));
221
+ mMessage. setText(" " );
222
+ }
223
+ });
224
+ }
225
+
226
+ @Override
227
+ protected void onDestroy() {
228
+ super . onDestroy();
229
+ mAdapter. cleanup();
230
+ }
231
+ ```
219
232
220
233
Et voila: a minimal, yet fully functional, chat app in about 30 lines of code. Not bad, right?
221
234
@@ -235,35 +248,39 @@ A ViewHolder is similar to container of a ViewGroup that allows simple lookup of
235
248
If we use the same layout as before (` android.R.layout.two_line_list_item ` ), there are two ` TextView ` s in there.
236
249
We can wrap that in a ViewHolder with:
237
250
238
- private static class ChatMessageViewHolder extends RecyclerView.ViewHolder {
239
- TextView messageText;
240
- TextView nameText;
251
+ ``` java
252
+ private static class ChatMessageViewHolder extends RecyclerView .ViewHolder {
253
+ TextView messageText;
254
+ TextView nameText;
241
255
242
- public ChatMessageViewHolder(View itemView) {
243
- super(itemView);
244
- nameText = (TextView)itemView.findViewById(android.R.id.text1);
245
- messageText = (TextView) itemView.findViewById(android.R.id.text2);
246
- }
256
+ public ChatMessageViewHolder (View itemView ) {
257
+ super (itemView);
258
+ nameText = (TextView )itemView. findViewById(android. R . id. text1);
259
+ messageText = (TextView ) itemView. findViewById(android. R . id. text2);
247
260
}
261
+ }
262
+ ```
248
263
249
264
There's nothing magical going on here; we're just mapping numeric IDs and casts into a nice, type-safe contract.
250
265
251
266
### Create a custom FirebaseListAdapter
252
267
253
268
Just like we did for FirebaseListAdapter, we'll create an anonymous subclass for our ChatMessages:
254
269
255
- RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
256
- recycler.setHasFixedSize(true);
257
- recycler.setLayoutManager(new LinearLayoutManager(this));
258
-
259
- mAdapter = new FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder>(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) {
260
- @Override
261
- public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) {
262
- chatMessageViewHolder.nameText.setText(chatMessage.getName());
263
- chatMessageViewHolder.messageText.setText(chatMessage.getMessage());
264
- }
265
- };
266
- recycler.setAdapter(mAdapter);
270
+ ``` java
271
+ RecyclerView recycler = (RecyclerView ) findViewById(R . id. messages_recycler);
272
+ recycler. setHasFixedSize(true );
273
+ recycler. setLayoutManager(new LinearLayoutManager (this ));
274
+
275
+ mAdapter = new FirebaseRecyclerViewAdapter<ChatMessage , ChatMessageViewHolder > (ChatMessage . class, android. R . layout. two_line_list_item, ChatMessageViewHolder . class, mRef) {
276
+ @Override
277
+ public void populateViewHolder (ChatMessageViewHolder chatMessageViewHolder , ChatMessage chatMessage ) {
278
+ chatMessageViewHolder. nameText. setText(chatMessage. getName());
279
+ chatMessageViewHolder. messageText. setText(chatMessage. getMessage());
280
+ }
281
+ };
282
+ recycler. setAdapter(mAdapter);
283
+ ```
267
284
268
285
Like before, we get a custom RecyclerView populated with data from Firebase by setting the properties to the correct fields.
269
286
0 commit comments