@@ -40,27 +40,28 @@ So say we have these chat messages in our Firebase database:
4040
4141We can represent a chat message with this Java class:
4242
43- public class ChatMessage {
44- String message;
45- String name;
43+ ``` java
44+ public class ChatMessage {
45+ String message;
46+ String name;
4647
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+ }
5450
55- public String getMessage() {
56- return message;
57- }
51+ public ChatMessage (String name , String message ) {
52+ this . message = message;
53+ this . name = name;
54+ }
5855
59- public String getName() {
60- return name;
61- }
56+ public String getMessage () {
57+ return message;
6258 }
6359
60+ public String getName () {
61+ return name;
62+ }
63+ }
64+ ```
6465A few things to note here:
6566
6667 * 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:
7071
7172A little-known feature of Firebase for Android is that you can pass an instance of this ` ChatMessage ` class to ` setValue() ` :
7273
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+ ```
7779The Firebase Android client will read the values from the ` msg ` and write them into the properties of the new child in the database.
7880
7981Conversely, we can read a ` ChatMessage ` straight from a ` DataSnapshot ` in our event handlers:
8082
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());
9290 }
93- });
94-
91+ }
92+ @Override
93+ public void onCancelled (FirebaseError firebaseError ) {
94+ Log . e(" Chat" , " The read failed: " + firebaseError. getMessage());
95+ }
96+ });
97+ ```
9598In the above snippet we have a query for the last 5 chat messages. Whenever those change (i.e. when an new message is added)
9699we get the ` ChatMessage ` objects from the ` DataSnapshot ` with ` getValue(ChatMessage.class) ` . The Firebase Android client will
97100then 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
105108
106109We'll assume you've already added a ` ListView ` to your layout and have looked it up in the ` onCreate ` method of your activity:
107110
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);
112116
113- ListView messagesView = (ListView) findViewById(R.id.messages_list);
114- }
117+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
118+ }
119+ ```
115120
116121#### Set up connection to Firebase
117122
118123First we'll tell Firebase that we intend to use it in this activity and set up a reference to the database of chat message.
119124
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);
124130
125- ListView messagesView = (ListView) findViewById(R.id.messages_list);
131+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
126132
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+ ```
130137
131138#### Create custom FirebaseListAdapter subclass
132139
133140Next, we need to create a subclass of the ` FirebaseListAdapter ` with the correct parameters and implement its ` populateView ` method:
134141
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);
139147
140- ListView messagesView = (ListView) findViewById(R.id.messages_list);
148+ ListView messagesView = (ListView ) findViewById(R . id. messages_list);
141149
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" );
144152
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());
150158
151- }
152- };
153- messagesView.setListAdapter(mAdapter);
154- }
159+ }
160+ };
161+ messagesView. setListAdapter(mAdapter);
162+ }
163+ ```
155164
156165In this last snippet we create a subclass of ` FirebaseListAdapter ` .
157166We 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.
171180Finally, we need to clean up after ourselves. When the activity is destroyed, we need to call ` release() `
172181on the ` ListAdapter ` so that it can stop listening for changes in the Firebase database.
173182
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+ ```
179190
180191#### Sending chat messages
181192
182193Remember when we showed how to use the ` ChatMessage ` class in ` setValue() ` .
183194We can now use that in our activity to allow sending a message:
184195
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);
213201
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+ ```
219232
220233Et voila: a minimal, yet fully functional, chat app in about 30 lines of code. Not bad, right?
221234
@@ -235,35 +248,39 @@ A ViewHolder is similar to container of a ViewGroup that allows simple lookup of
235248If we use the same layout as before (` android.R.layout.two_line_list_item ` ), there are two ` TextView ` s in there.
236249We can wrap that in a ViewHolder with:
237250
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;
241255
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);
247260 }
261+ }
262+ ```
248263
249264There's nothing magical going on here; we're just mapping numeric IDs and casts into a nice, type-safe contract.
250265
251266### Create a custom FirebaseListAdapter
252267
253268Just like we did for FirebaseListAdapter, we'll create an anonymous subclass for our ChatMessages:
254269
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+ ```
267284
268285Like before, we get a custom RecyclerView populated with data from Firebase by setting the properties to the correct fields.
269286
0 commit comments